wanpipe-3.5.12.tgz
This commit is contained in:
parent
fbb8feccef
commit
c6acb46c69
|
@ -1 +1 @@
|
|||
wanpipe-3.5.11
|
||||
wanpipe-3.5.12
|
||||
|
|
|
@ -3,11 +3,47 @@ WANPIPE TDM VOICE - IP/WAN Package
|
|||
|
||||
------------------------------------------------------------------------------
|
||||
Author: Nenad Corbic <ncorbic@sangoma.com>
|
||||
Copyright (c) 1995-2009 Sangoma Technologies Inc.
|
||||
Copyright (c) 1995-2010 Sangoma Technologies Inc.
|
||||
|
||||
For more info visit: http://wiki.sangoma.com
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
* Mon Jun 28 2010 Nenad Corbic <ncorbic@sangoma.com> - 3.5.12
|
||||
===================================================================
|
||||
|
||||
- Fixed Dahdi 2.3 Support
|
||||
- Fixed FreeSwitch Openzap HardHDLC option for AFT cards
|
||||
- Fixed wanpipemon support for non aft cards.
|
||||
- Merged USB FXO code from 3.6 release
|
||||
- USB FXO bug fix for 2.6.32 kernels
|
||||
- Support for B800 Analog card
|
||||
- Fixed alarm reporting in DAHDI/ZAPTEL
|
||||
|
||||
- Added Extra EC DSP Configuration Options
|
||||
HWEC_OPERATION_MODE = OCT_NORMAL # OCT_NORMAL: echo cancelation enabled with nlp (default)
|
||||
# OCT_SPEECH: improves software tone detection by disabling NLP (echo possible)
|
||||
# OCT_NO_ECHO:disables echo cancelation but allows VQE/tone functions.
|
||||
HWEC_DTMF_REMOVAL = NO # NO: default YES: remove dtmf out of incoming media (must have hwdtmf enabled)
|
||||
HWEC_NOISE_REDUCTION = NO # NO: default YES: reduces noise on the line - could break fax
|
||||
HWEC_ACUSTIC_ECHO = NO # NO: default YES: enables acustic echo cancelation
|
||||
HWEC_NLP_DISABLE = NO # NO: default YES: guarantees software tone detection (possible echo)
|
||||
HWEC_TX_AUTO_GAIN = 0 # 0: disable -40-0: default tx audio level to be maintained (-20 default)
|
||||
HWEC_RX_AUTO_GAIN = 0 # 0: disable -40-0: default rx audio level to be maintained (-20 default)
|
||||
HWEC_TX_GAIN = 0 # 0: disable -24-24: db values to be applied to tx signal
|
||||
HWEC_RX_GAIN = 0 # 0: disable -24-24: db values to be applied to tx signal
|
||||
|
||||
- Added AIS BLUE Alarm Maintenance Startup option
|
||||
Allows a port to be started in BLUE alarm.
|
||||
|
||||
TE_AIS_MAINTENANCE = NO #NO: defualt YES: Start port in AIS Blue Alarm and keep line down
|
||||
#wanpipemon -i w1g1 -c Ttx_ais_off to disable AIS maintenance mode
|
||||
#wanpipemon -i w1g1 -c Ttx_ais_on to enable AIS maintenance mode
|
||||
|
||||
- Fixed Legacy XDLC compile
|
||||
- Fixed core edge case scenarios where
|
||||
potential race condition could occour.
|
||||
|
||||
|
||||
|
||||
* Thu Apr 08 2010 Nenad Corbic <ncorbic@sangoma.com> - 3.5.11
|
||||
===================================================================
|
||||
|
|
23
Makefile
23
Makefile
|
@ -13,6 +13,7 @@
|
|||
|
||||
PWD=$(shell pwd)
|
||||
KBUILD_VERBOSE=0
|
||||
CC=gcc
|
||||
|
||||
EXTRA_CFLAGS=
|
||||
EXTRA_FLAGS=
|
||||
|
@ -99,7 +100,15 @@ EXTRA_UTIL_FLAGS += -I$(PWD)/patches/kdrivers/wanec -I$(PWD)/patches/kdrivers/wa
|
|||
ENABLE_WANPIPEMON_ZAP=NO
|
||||
ZAPHDLC_PRIV=/etc/wanpipe/.zaphdlc
|
||||
|
||||
EXTRA_CFLAGS += $(EXTRA_FLAGS)
|
||||
PRODUCT_DEFINES= -DCONFIG_PRODUCT_WANPIPE_BASE -DCONFIG_PRODUCT_WANPIPE_AFT -DCONFIG_PRODUCT_WANPIPE_AFT_CORE
|
||||
PRODUCT_DEFINES+= -DCONFIG_PRODUCT_WANPIPE_AFT_TE1 -DCONFIG_PRODUCT_WANPIPE_AFT_TE3 -DCONFIG_PRODUCT_WANPIPE_AFT_56K
|
||||
PRODUCT_DEFINES+= -DCONFIG_WANPIPE_HWEC -DCONFIG_PRODUCT_WANPIPE_SOCK_DATASCOPE -DCONFIG_PRODUCT_WANPIPE_AFT_BRI -DCONFIG_PRODUCT_WANPIPE_AFT_SERIAL
|
||||
PRODUCT_DEFINES+= -DCONFIG_PRODUCT_WANPIPE_TDM_VOICE_DCHAN -DCONFIG_PRODUCT_WANPIPE_CODEC_SLINEAR_LAW -DCONFIG_PRODUCT_WANPIPE_AFT_RM
|
||||
PRODUCT_DEFINES+= -DCONFIG_PRODUCT_WANPIPE_USB -DCONFIG_PRODUCT_WANPIPE_A700 -DCONFIG_PRODUCT_A600 -DCONFIG_PRODUCT_WANPIPE_AFT_A600 -DCONFIG_PRODUCT_WANPIPE_AFT_A700
|
||||
PRODUCT_DEFINES+= -DCONFIG_PRODUCT_WANPIPE_AFT_B601 -DCONFIG_PRODUCT_WANPIPE_AFT_B800
|
||||
|
||||
EXTRA_CFLAGS += $(EXTRA_FLAGS) $(PRODUCT_DEFINES)
|
||||
EXTRA_UTIL_FLAGS += $(PRODUCT_DEFINES)
|
||||
|
||||
|
||||
#Check if zaptel exists
|
||||
|
@ -170,6 +179,9 @@ openzap: all_src all_lib
|
|||
freetdm: all_src all_lib
|
||||
@touch .all_lib .openzap
|
||||
|
||||
g3ti: all_src all_lib
|
||||
@touch .all_lib .openzap
|
||||
|
||||
openzap_ss7: all_src_ss7 all_lib
|
||||
@touch .all_lib
|
||||
|
||||
|
@ -370,6 +382,15 @@ install_pri:
|
|||
@eval "cd ssmg; ./get_sangoma_prid.sh; cd .."
|
||||
$(MAKE) -C ssmg/sangoma_pri/ install SYSINC=$(PWD)/$(WINCLUDE) CC=$(CC) DESTDIR=$(INSTALLPREFIX)
|
||||
|
||||
install_pri_freetdm:
|
||||
@eval "cd ssmg; ./get_sangoma_prid.sh; cd .."
|
||||
$(MAKE) -C ssmg/sangoma_pri/ install_libs install_freetdm_lib SYSINC=$(PWD)/$(WINCLUDE) CC=$(CC) DESTDIR=$(INSTALLPREFIX)
|
||||
|
||||
install_pri_freetdm_update:
|
||||
@eval "cd ssmg; ./get_sangoma_prid.sh --update; cd .."
|
||||
$(MAKE) -C ssmg/sangoma_pri/ install_libs install_freetdm_lib SYSINC=$(PWD)/$(WINCLUDE) CC=$(CC) DESTDIR=$(INSTALLPREFIX)
|
||||
|
||||
|
||||
install_pri_update:
|
||||
@eval "cd ssmg; ./get_sangoma_prid.sh --update; cd .."
|
||||
$(MAKE) -C ssmg/sangoma_pri/ install SYSINC=$(PWD)/$(WINCLUDE) CC=$(CC) DESTDIR=$(INSTALLPREFIX)
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
config ECHO
|
||||
tristate "Line Echo Canceller support"
|
||||
default n
|
||||
---help---
|
||||
This driver provides line echo cancelling support for mISDN and
|
||||
Zaptel drivers.
|
||||
|
||||
To compile this driver as a module, choose M here. The module
|
||||
will be called echo.
|
|
@ -0,0 +1 @@
|
|||
obj-$(CONFIG_ECHO) += echo.o
|
|
@ -0,0 +1,10 @@
|
|||
TODO:
|
||||
- checkpatch.pl cleanups
|
||||
- Lindent
|
||||
- typedef removals
|
||||
- handle bit_operations.h (merge in or make part of common code?)
|
||||
- remove proc interface, only use echo.h interface (proc interface is
|
||||
racy and not correct.)
|
||||
|
||||
Please send patches to Greg Kroah-Hartman <greg@kroah.com> and Cc: Steve
|
||||
Underwood <steveu@coppice.org> and David Rowe <david@rowetel.com>
|
|
@ -0,0 +1,228 @@
|
|||
/*
|
||||
* SpanDSP - a series of DSP components for telephony
|
||||
*
|
||||
* bit_operations.h - Various bit level operations, such as bit reversal
|
||||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Copyright (C) 2006 Steve Underwood
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: bit_operations.h,v 1.11 2006/11/28 15:37:03 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
||||
#if !defined(_BIT_OPERATIONS_H_)
|
||||
#define _BIT_OPERATIONS_H_
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
/*! \brief Find the bit position of the highest set bit in a word
|
||||
\param bits The word to be searched
|
||||
\return The bit number of the highest set bit, or -1 if the word is zero. */
|
||||
static __inline__ int top_bit(unsigned int bits)
|
||||
{
|
||||
int res;
|
||||
|
||||
__asm__(" xorl %[res],%[res];\n"
|
||||
" decl %[res];\n"
|
||||
" bsrl %[bits],%[res]\n"
|
||||
:[res] "=&r" (res)
|
||||
:[bits] "rm"(bits)
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*! \brief Find the bit position of the lowest set bit in a word
|
||||
\param bits The word to be searched
|
||||
\return The bit number of the lowest set bit, or -1 if the word is zero. */
|
||||
static __inline__ int bottom_bit(unsigned int bits)
|
||||
{
|
||||
int res;
|
||||
|
||||
__asm__(" xorl %[res],%[res];\n"
|
||||
" decl %[res];\n"
|
||||
" bsfl %[bits],%[res]\n"
|
||||
:[res] "=&r" (res)
|
||||
:[bits] "rm"(bits)
|
||||
);
|
||||
return res;
|
||||
}
|
||||
#else
|
||||
static __inline__ int top_bit(unsigned int bits)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (bits == 0)
|
||||
return -1;
|
||||
i = 0;
|
||||
if (bits & 0xFFFF0000) {
|
||||
bits &= 0xFFFF0000;
|
||||
i += 16;
|
||||
}
|
||||
if (bits & 0xFF00FF00) {
|
||||
bits &= 0xFF00FF00;
|
||||
i += 8;
|
||||
}
|
||||
if (bits & 0xF0F0F0F0) {
|
||||
bits &= 0xF0F0F0F0;
|
||||
i += 4;
|
||||
}
|
||||
if (bits & 0xCCCCCCCC) {
|
||||
bits &= 0xCCCCCCCC;
|
||||
i += 2;
|
||||
}
|
||||
if (bits & 0xAAAAAAAA) {
|
||||
bits &= 0xAAAAAAAA;
|
||||
i += 1;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static __inline__ int bottom_bit(unsigned int bits)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (bits == 0)
|
||||
return -1;
|
||||
i = 32;
|
||||
if (bits & 0x0000FFFF) {
|
||||
bits &= 0x0000FFFF;
|
||||
i -= 16;
|
||||
}
|
||||
if (bits & 0x00FF00FF) {
|
||||
bits &= 0x00FF00FF;
|
||||
i -= 8;
|
||||
}
|
||||
if (bits & 0x0F0F0F0F) {
|
||||
bits &= 0x0F0F0F0F;
|
||||
i -= 4;
|
||||
}
|
||||
if (bits & 0x33333333) {
|
||||
bits &= 0x33333333;
|
||||
i -= 2;
|
||||
}
|
||||
if (bits & 0x55555555) {
|
||||
bits &= 0x55555555;
|
||||
i -= 1;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*! \brief Bit reverse a byte.
|
||||
\param data The byte to be reversed.
|
||||
\return The bit reversed version of data. */
|
||||
static __inline__ uint8_t bit_reverse8(uint8_t x)
|
||||
{
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
/* If multiply is fast */
|
||||
return ((x * 0x0802U & 0x22110U) | (x * 0x8020U & 0x88440U)) *
|
||||
0x10101U >> 16;
|
||||
#else
|
||||
/* If multiply is slow, but we have a barrel shifter */
|
||||
x = (x >> 4) | (x << 4);
|
||||
x = ((x & 0xCC) >> 2) | ((x & 0x33) << 2);
|
||||
return ((x & 0xAA) >> 1) | ((x & 0x55) << 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*! \brief Bit reverse a 16 bit word.
|
||||
\param data The word to be reversed.
|
||||
\return The bit reversed version of data. */
|
||||
uint16_t bit_reverse16(uint16_t data);
|
||||
|
||||
/*! \brief Bit reverse a 32 bit word.
|
||||
\param data The word to be reversed.
|
||||
\return The bit reversed version of data. */
|
||||
uint32_t bit_reverse32(uint32_t data);
|
||||
|
||||
/*! \brief Bit reverse each of the four bytes in a 32 bit word.
|
||||
\param data The word to be reversed.
|
||||
\return The bit reversed version of data. */
|
||||
uint32_t bit_reverse_4bytes(uint32_t data);
|
||||
|
||||
/*! \brief Find the number of set bits in a 32 bit word.
|
||||
\param x The word to be searched.
|
||||
\return The number of set bits. */
|
||||
int one_bits32(uint32_t x);
|
||||
|
||||
/*! \brief Create a mask as wide as the number in a 32 bit word.
|
||||
\param x The word to be searched.
|
||||
\return The mask. */
|
||||
uint32_t make_mask32(uint32_t x);
|
||||
|
||||
/*! \brief Create a mask as wide as the number in a 16 bit word.
|
||||
\param x The word to be searched.
|
||||
\return The mask. */
|
||||
uint16_t make_mask16(uint16_t x);
|
||||
|
||||
/*! \brief Find the least significant one in a word, and return a word
|
||||
with just that bit set.
|
||||
\param x The word to be searched.
|
||||
\return The word with the single set bit. */
|
||||
static __inline__ uint32_t least_significant_one32(uint32_t x)
|
||||
{
|
||||
return (x & (-(int32_t) x));
|
||||
}
|
||||
|
||||
/*! \brief Find the most significant one in a word, and return a word
|
||||
with just that bit set.
|
||||
\param x The word to be searched.
|
||||
\return The word with the single set bit. */
|
||||
static __inline__ uint32_t most_significant_one32(uint32_t x)
|
||||
{
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
return 1 << top_bit(x);
|
||||
#else
|
||||
x = make_mask32(x);
|
||||
return (x ^ (x >> 1));
|
||||
#endif
|
||||
}
|
||||
|
||||
/*! \brief Find the parity of a byte.
|
||||
\param x The byte to be checked.
|
||||
\return 1 for odd, or 0 for even. */
|
||||
static __inline__ int parity8(uint8_t x)
|
||||
{
|
||||
x = (x ^ (x >> 4)) & 0x0F;
|
||||
return (0x6996 >> x) & 1;
|
||||
}
|
||||
|
||||
/*! \brief Find the parity of a 16 bit word.
|
||||
\param x The word to be checked.
|
||||
\return 1 for odd, or 0 for even. */
|
||||
static __inline__ int parity16(uint16_t x)
|
||||
{
|
||||
x ^= (x >> 8);
|
||||
x = (x ^ (x >> 4)) & 0x0F;
|
||||
return (0x6996 >> x) & 1;
|
||||
}
|
||||
|
||||
/*! \brief Find the parity of a 32 bit word.
|
||||
\param x The word to be checked.
|
||||
\return 1 for odd, or 0 for even. */
|
||||
static __inline__ int parity32(uint32_t x)
|
||||
{
|
||||
x ^= (x >> 16);
|
||||
x ^= (x >> 8);
|
||||
x = (x ^ (x >> 4)) & 0x0F;
|
||||
return (0x6996 >> x) & 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*- End of file ------------------------------------------------------------*/
|
|
@ -0,0 +1,638 @@
|
|||
/*
|
||||
* SpanDSP - a series of DSP components for telephony
|
||||
*
|
||||
* echo.c - A line echo canceller. This code is being developed
|
||||
* against and partially complies with G168.
|
||||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
* and David Rowe <david_at_rowetel_dot_com>
|
||||
*
|
||||
* Copyright (C) 2001, 2003 Steve Underwood, 2007 David Rowe
|
||||
*
|
||||
* Based on a bit from here, a bit from there, eye of toad, ear of
|
||||
* bat, 15 years of failed attempts by David and a few fried brain
|
||||
* cells.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: echo.c,v 1.20 2006/12/01 18:00:48 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
||||
/* Implementation Notes
|
||||
David Rowe
|
||||
April 2007
|
||||
|
||||
This code started life as Steve's NLMS algorithm with a tap
|
||||
rotation algorithm to handle divergence during double talk. I
|
||||
added a Geigel Double Talk Detector (DTD) [2] and performed some
|
||||
G168 tests. However I had trouble meeting the G168 requirements,
|
||||
especially for double talk - there were always cases where my DTD
|
||||
failed, for example where near end speech was under the 6dB
|
||||
threshold required for declaring double talk.
|
||||
|
||||
So I tried a two path algorithm [1], which has so far given better
|
||||
results. The original tap rotation/Geigel algorithm is available
|
||||
in SVN http://svn.rowetel.com/software/oslec/tags/before_16bit.
|
||||
It's probably possible to make it work if some one wants to put some
|
||||
serious work into it.
|
||||
|
||||
At present no special treatment is provided for tones, which
|
||||
generally cause NLMS algorithms to diverge. Initial runs of a
|
||||
subset of the G168 tests for tones (e.g ./echo_test 6) show the
|
||||
current algorithm is passing OK, which is kind of surprising. The
|
||||
full set of tests needs to be performed to confirm this result.
|
||||
|
||||
One other interesting change is that I have managed to get the NLMS
|
||||
code to work with 16 bit coefficients, rather than the original 32
|
||||
bit coefficents. This reduces the MIPs and storage required.
|
||||
I evaulated the 16 bit port using g168_tests.sh and listening tests
|
||||
on 4 real-world samples.
|
||||
|
||||
I also attempted the implementation of a block based NLMS update
|
||||
[2] but although this passes g168_tests.sh it didn't converge well
|
||||
on the real-world samples. I have no idea why, perhaps a scaling
|
||||
problem. The block based code is also available in SVN
|
||||
http://svn.rowetel.com/software/oslec/tags/before_16bit. If this
|
||||
code can be debugged, it will lead to further reduction in MIPS, as
|
||||
the block update code maps nicely onto DSP instruction sets (it's a
|
||||
dot product) compared to the current sample-by-sample update.
|
||||
|
||||
Steve also has some nice notes on echo cancellers in echo.h
|
||||
|
||||
References:
|
||||
|
||||
[1] Ochiai, Areseki, and Ogihara, "Echo Canceller with Two Echo
|
||||
Path Models", IEEE Transactions on communications, COM-25,
|
||||
No. 6, June
|
||||
1977.
|
||||
http://www.rowetel.com/images/echo/dual_path_paper.pdf
|
||||
|
||||
[2] The classic, very useful paper that tells you how to
|
||||
actually build a real world echo canceller:
|
||||
Messerschmitt, Hedberg, Cole, Haoui, Winship, "Digital Voice
|
||||
Echo Canceller with a TMS320020,
|
||||
http://www.rowetel.com/images/echo/spra129.pdf
|
||||
|
||||
[3] I have written a series of blog posts on this work, here is
|
||||
Part 1: http://www.rowetel.com/blog/?p=18
|
||||
|
||||
[4] The source code http://svn.rowetel.com/software/oslec/
|
||||
|
||||
[5] A nice reference on LMS filters:
|
||||
http://en.wikipedia.org/wiki/Least_mean_squares_filter
|
||||
|
||||
Credits:
|
||||
|
||||
Thanks to Steve Underwood, Jean-Marc Valin, and Ramakrishnan
|
||||
Muthukrishnan for their suggestions and email discussions. Thanks
|
||||
also to those people who collected echo samples for me such as
|
||||
Mark, Pawel, and Pavel.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h> /* We're doing kernel work */
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "bit_operations.h"
|
||||
#include "echo.h"
|
||||
|
||||
#define MIN_TX_POWER_FOR_ADAPTION 64
|
||||
#define MIN_RX_POWER_FOR_ADAPTION 64
|
||||
#define DTD_HANGOVER 600 /* 600 samples, or 75ms */
|
||||
#define DC_LOG2BETA 3 /* log2() of DC filter Beta */
|
||||
|
||||
/*-----------------------------------------------------------------------*\
|
||||
FUNCTIONS
|
||||
\*-----------------------------------------------------------------------*/
|
||||
|
||||
/* adapting coeffs using the traditional stochastic descent (N)LMS algorithm */
|
||||
|
||||
#ifdef __bfin__
|
||||
static void __inline__ lms_adapt_bg(struct oslec_state *ec, int clean,
|
||||
int shift)
|
||||
{
|
||||
int i, j;
|
||||
int offset1;
|
||||
int offset2;
|
||||
int factor;
|
||||
int exp;
|
||||
int16_t *phist;
|
||||
int n;
|
||||
|
||||
if (shift > 0)
|
||||
factor = clean << shift;
|
||||
else
|
||||
factor = clean >> -shift;
|
||||
|
||||
/* Update the FIR taps */
|
||||
|
||||
offset2 = ec->curr_pos;
|
||||
offset1 = ec->taps - offset2;
|
||||
phist = &ec->fir_state_bg.history[offset2];
|
||||
|
||||
/* st: and en: help us locate the assembler in echo.s */
|
||||
|
||||
//asm("st:");
|
||||
n = ec->taps;
|
||||
for (i = 0, j = offset2; i < n; i++, j++) {
|
||||
exp = *phist++ * factor;
|
||||
ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15);
|
||||
}
|
||||
//asm("en:");
|
||||
|
||||
/* Note the asm for the inner loop above generated by Blackfin gcc
|
||||
4.1.1 is pretty good (note even parallel instructions used):
|
||||
|
||||
R0 = W [P0++] (X);
|
||||
R0 *= R2;
|
||||
R0 = R0 + R3 (NS) ||
|
||||
R1 = W [P1] (X) ||
|
||||
nop;
|
||||
R0 >>>= 15;
|
||||
R0 = R0 + R1;
|
||||
W [P1++] = R0;
|
||||
|
||||
A block based update algorithm would be much faster but the
|
||||
above can't be improved on much. Every instruction saved in
|
||||
the loop above is 2 MIPs/ch! The for loop above is where the
|
||||
Blackfin spends most of it's time - about 17 MIPs/ch measured
|
||||
with speedtest.c with 256 taps (32ms). Write-back and
|
||||
Write-through cache gave about the same performance.
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
IDEAS for further optimisation of lms_adapt_bg():
|
||||
|
||||
1/ The rounding is quite costly. Could we keep as 32 bit coeffs
|
||||
then make filter pluck the MS 16-bits of the coeffs when filtering?
|
||||
However this would lower potential optimisation of filter, as I
|
||||
think the dual-MAC architecture requires packed 16 bit coeffs.
|
||||
|
||||
2/ Block based update would be more efficient, as per comments above,
|
||||
could use dual MAC architecture.
|
||||
|
||||
3/ Look for same sample Blackfin LMS code, see if we can get dual-MAC
|
||||
packing.
|
||||
|
||||
4/ Execute the whole e/c in a block of say 20ms rather than sample
|
||||
by sample. Processing a few samples every ms is inefficient.
|
||||
*/
|
||||
|
||||
#else
|
||||
static __inline__ void lms_adapt_bg(struct oslec_state *ec, int clean,
|
||||
int shift)
|
||||
{
|
||||
int i;
|
||||
|
||||
int offset1;
|
||||
int offset2;
|
||||
int factor;
|
||||
int exp;
|
||||
|
||||
if (shift > 0)
|
||||
factor = clean << shift;
|
||||
else
|
||||
factor = clean >> -shift;
|
||||
|
||||
/* Update the FIR taps */
|
||||
|
||||
offset2 = ec->curr_pos;
|
||||
offset1 = ec->taps - offset2;
|
||||
|
||||
for (i = ec->taps - 1; i >= offset1; i--) {
|
||||
exp = (ec->fir_state_bg.history[i - offset1] * factor);
|
||||
ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15);
|
||||
}
|
||||
for (; i >= 0; i--) {
|
||||
exp = (ec->fir_state_bg.history[i + offset2] * factor);
|
||||
ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
struct oslec_state *oslec_create(int len, int adaption_mode)
|
||||
{
|
||||
struct oslec_state *ec;
|
||||
int i;
|
||||
|
||||
ec = kzalloc(sizeof(*ec), GFP_KERNEL);
|
||||
if (!ec)
|
||||
return NULL;
|
||||
|
||||
ec->taps = len;
|
||||
ec->log2taps = top_bit(len);
|
||||
ec->curr_pos = ec->taps - 1;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
ec->fir_taps16[i] =
|
||||
kcalloc(ec->taps, sizeof(int16_t), GFP_KERNEL);
|
||||
if (!ec->fir_taps16[i])
|
||||
goto error_oom;
|
||||
}
|
||||
|
||||
fir16_create(&ec->fir_state, ec->fir_taps16[0], ec->taps);
|
||||
fir16_create(&ec->fir_state_bg, ec->fir_taps16[1], ec->taps);
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
ec->xvtx[i] = ec->yvtx[i] = ec->xvrx[i] = ec->yvrx[i] = 0;
|
||||
}
|
||||
|
||||
ec->cng_level = 1000;
|
||||
oslec_adaption_mode(ec, adaption_mode);
|
||||
|
||||
ec->snapshot = kcalloc(ec->taps, sizeof(int16_t), GFP_KERNEL);
|
||||
if (!ec->snapshot)
|
||||
goto error_oom;
|
||||
|
||||
ec->cond_met = 0;
|
||||
ec->Pstates = 0;
|
||||
ec->Ltxacc = ec->Lrxacc = ec->Lcleanacc = ec->Lclean_bgacc = 0;
|
||||
ec->Ltx = ec->Lrx = ec->Lclean = ec->Lclean_bg = 0;
|
||||
ec->tx_1 = ec->tx_2 = ec->rx_1 = ec->rx_2 = 0;
|
||||
ec->Lbgn = ec->Lbgn_acc = 0;
|
||||
ec->Lbgn_upper = 200;
|
||||
ec->Lbgn_upper_acc = ec->Lbgn_upper << 13;
|
||||
|
||||
return ec;
|
||||
|
||||
error_oom:
|
||||
for (i = 0; i < 2; i++)
|
||||
kfree(ec->fir_taps16[i]);
|
||||
|
||||
kfree(ec);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(oslec_create);
|
||||
|
||||
void oslec_free(struct oslec_state *ec)
|
||||
{
|
||||
int i;
|
||||
|
||||
fir16_free(&ec->fir_state);
|
||||
fir16_free(&ec->fir_state_bg);
|
||||
for (i = 0; i < 2; i++)
|
||||
kfree(ec->fir_taps16[i]);
|
||||
kfree(ec->snapshot);
|
||||
kfree(ec);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(oslec_free);
|
||||
|
||||
void oslec_adaption_mode(struct oslec_state *ec, int adaption_mode)
|
||||
{
|
||||
ec->adaption_mode = adaption_mode;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(oslec_adaption_mode);
|
||||
|
||||
void oslec_flush(struct oslec_state *ec)
|
||||
{
|
||||
int i;
|
||||
|
||||
ec->Ltxacc = ec->Lrxacc = ec->Lcleanacc = ec->Lclean_bgacc = 0;
|
||||
ec->Ltx = ec->Lrx = ec->Lclean = ec->Lclean_bg = 0;
|
||||
ec->tx_1 = ec->tx_2 = ec->rx_1 = ec->rx_2 = 0;
|
||||
|
||||
ec->Lbgn = ec->Lbgn_acc = 0;
|
||||
ec->Lbgn_upper = 200;
|
||||
ec->Lbgn_upper_acc = ec->Lbgn_upper << 13;
|
||||
|
||||
ec->nonupdate_dwell = 0;
|
||||
|
||||
fir16_flush(&ec->fir_state);
|
||||
fir16_flush(&ec->fir_state_bg);
|
||||
ec->fir_state.curr_pos = ec->taps - 1;
|
||||
ec->fir_state_bg.curr_pos = ec->taps - 1;
|
||||
for (i = 0; i < 2; i++)
|
||||
memset(ec->fir_taps16[i], 0, ec->taps * sizeof(int16_t));
|
||||
|
||||
ec->curr_pos = ec->taps - 1;
|
||||
ec->Pstates = 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(oslec_flush);
|
||||
|
||||
void oslec_snapshot(struct oslec_state *ec)
|
||||
{
|
||||
memcpy(ec->snapshot, ec->fir_taps16[0], ec->taps * sizeof(int16_t));
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(oslec_snapshot);
|
||||
|
||||
/* Dual Path Echo Canceller ------------------------------------------------*/
|
||||
|
||||
int16_t oslec_update(struct oslec_state *ec, int16_t tx, int16_t rx)
|
||||
{
|
||||
int32_t echo_value;
|
||||
int clean_bg;
|
||||
int tmp, tmp1;
|
||||
|
||||
/* Input scaling was found be required to prevent problems when tx
|
||||
starts clipping. Another possible way to handle this would be the
|
||||
filter coefficent scaling. */
|
||||
|
||||
ec->tx = tx;
|
||||
ec->rx = rx;
|
||||
tx >>= 1;
|
||||
rx >>= 1;
|
||||
|
||||
/*
|
||||
Filter DC, 3dB point is 160Hz (I think), note 32 bit precision required
|
||||
otherwise values do not track down to 0. Zero at DC, Pole at (1-Beta)
|
||||
only real axis. Some chip sets (like Si labs) don't need
|
||||
this, but something like a $10 X100P card does. Any DC really slows
|
||||
down convergence.
|
||||
|
||||
Note: removes some low frequency from the signal, this reduces
|
||||
the speech quality when listening to samples through headphones
|
||||
but may not be obvious through a telephone handset.
|
||||
|
||||
Note that the 3dB frequency in radians is approx Beta, e.g. for
|
||||
Beta = 2^(-3) = 0.125, 3dB freq is 0.125 rads = 159Hz.
|
||||
*/
|
||||
|
||||
if (ec->adaption_mode & ECHO_CAN_USE_RX_HPF) {
|
||||
tmp = rx << 15;
|
||||
#if 1
|
||||
/* Make sure the gain of the HPF is 1.0. This can still saturate a little under
|
||||
impulse conditions, and it might roll to 32768 and need clipping on sustained peak
|
||||
level signals. However, the scale of such clipping is small, and the error due to
|
||||
any saturation should not markedly affect the downstream processing. */
|
||||
tmp -= (tmp >> 4);
|
||||
#endif
|
||||
ec->rx_1 += -(ec->rx_1 >> DC_LOG2BETA) + tmp - ec->rx_2;
|
||||
|
||||
/* hard limit filter to prevent clipping. Note that at this stage
|
||||
rx should be limited to +/- 16383 due to right shift above */
|
||||
tmp1 = ec->rx_1 >> 15;
|
||||
if (tmp1 > 16383)
|
||||
tmp1 = 16383;
|
||||
if (tmp1 < -16383)
|
||||
tmp1 = -16383;
|
||||
rx = tmp1;
|
||||
ec->rx_2 = tmp;
|
||||
}
|
||||
|
||||
/* Block average of power in the filter states. Used for
|
||||
adaption power calculation. */
|
||||
|
||||
{
|
||||
int new, old;
|
||||
|
||||
/* efficient "out with the old and in with the new" algorithm so
|
||||
we don't have to recalculate over the whole block of
|
||||
samples. */
|
||||
new = (int)tx *(int)tx;
|
||||
old = (int)ec->fir_state.history[ec->fir_state.curr_pos] *
|
||||
(int)ec->fir_state.history[ec->fir_state.curr_pos];
|
||||
ec->Pstates +=
|
||||
((new - old) + (1 << ec->log2taps)) >> ec->log2taps;
|
||||
if (ec->Pstates < 0)
|
||||
ec->Pstates = 0;
|
||||
}
|
||||
|
||||
/* Calculate short term average levels using simple single pole IIRs */
|
||||
|
||||
ec->Ltxacc += abs(tx) - ec->Ltx;
|
||||
ec->Ltx = (ec->Ltxacc + (1 << 4)) >> 5;
|
||||
ec->Lrxacc += abs(rx) - ec->Lrx;
|
||||
ec->Lrx = (ec->Lrxacc + (1 << 4)) >> 5;
|
||||
|
||||
/* Foreground filter --------------------------------------------------- */
|
||||
|
||||
ec->fir_state.coeffs = ec->fir_taps16[0];
|
||||
echo_value = fir16(&ec->fir_state, tx);
|
||||
ec->clean = rx - echo_value;
|
||||
ec->Lcleanacc += abs(ec->clean) - ec->Lclean;
|
||||
ec->Lclean = (ec->Lcleanacc + (1 << 4)) >> 5;
|
||||
|
||||
/* Background filter --------------------------------------------------- */
|
||||
|
||||
echo_value = fir16(&ec->fir_state_bg, tx);
|
||||
clean_bg = rx - echo_value;
|
||||
ec->Lclean_bgacc += abs(clean_bg) - ec->Lclean_bg;
|
||||
ec->Lclean_bg = (ec->Lclean_bgacc + (1 << 4)) >> 5;
|
||||
|
||||
/* Background Filter adaption ----------------------------------------- */
|
||||
|
||||
/* Almost always adap bg filter, just simple DT and energy
|
||||
detection to minimise adaption in cases of strong double talk.
|
||||
However this is not critical for the dual path algorithm.
|
||||
*/
|
||||
ec->factor = 0;
|
||||
ec->shift = 0;
|
||||
if ((ec->nonupdate_dwell == 0)) {
|
||||
int P, logP, shift;
|
||||
|
||||
/* Determine:
|
||||
|
||||
f = Beta * clean_bg_rx/P ------ (1)
|
||||
|
||||
where P is the total power in the filter states.
|
||||
|
||||
The Boffins have shown that if we obey (1) we converge
|
||||
quickly and avoid instability.
|
||||
|
||||
The correct factor f must be in Q30, as this is the fixed
|
||||
point format required by the lms_adapt_bg() function,
|
||||
therefore the scaled version of (1) is:
|
||||
|
||||
(2^30) * f = (2^30) * Beta * clean_bg_rx/P
|
||||
factor = (2^30) * Beta * clean_bg_rx/P ----- (2)
|
||||
|
||||
We have chosen Beta = 0.25 by experiment, so:
|
||||
|
||||
factor = (2^30) * (2^-2) * clean_bg_rx/P
|
||||
|
||||
(30 - 2 - log2(P))
|
||||
factor = clean_bg_rx 2 ----- (3)
|
||||
|
||||
To avoid a divide we approximate log2(P) as top_bit(P),
|
||||
which returns the position of the highest non-zero bit in
|
||||
P. This approximation introduces an error as large as a
|
||||
factor of 2, but the algorithm seems to handle it OK.
|
||||
|
||||
Come to think of it a divide may not be a big deal on a
|
||||
modern DSP, so its probably worth checking out the cycles
|
||||
for a divide versus a top_bit() implementation.
|
||||
*/
|
||||
|
||||
P = MIN_TX_POWER_FOR_ADAPTION + ec->Pstates;
|
||||
logP = top_bit(P) + ec->log2taps;
|
||||
shift = 30 - 2 - logP;
|
||||
ec->shift = shift;
|
||||
|
||||
lms_adapt_bg(ec, clean_bg, shift);
|
||||
}
|
||||
|
||||
/* very simple DTD to make sure we dont try and adapt with strong
|
||||
near end speech */
|
||||
|
||||
ec->adapt = 0;
|
||||
if ((ec->Lrx > MIN_RX_POWER_FOR_ADAPTION) && (ec->Lrx > ec->Ltx))
|
||||
ec->nonupdate_dwell = DTD_HANGOVER;
|
||||
if (ec->nonupdate_dwell)
|
||||
ec->nonupdate_dwell--;
|
||||
|
||||
/* Transfer logic ------------------------------------------------------ */
|
||||
|
||||
/* These conditions are from the dual path paper [1], I messed with
|
||||
them a bit to improve performance. */
|
||||
|
||||
if ((ec->adaption_mode & ECHO_CAN_USE_ADAPTION) &&
|
||||
(ec->nonupdate_dwell == 0) &&
|
||||
(8 * ec->Lclean_bg <
|
||||
7 * ec->Lclean) /* (ec->Lclean_bg < 0.875*ec->Lclean) */ &&
|
||||
(8 * ec->Lclean_bg <
|
||||
ec->Ltx) /* (ec->Lclean_bg < 0.125*ec->Ltx) */ ) {
|
||||
if (ec->cond_met == 6) {
|
||||
/* BG filter has had better results for 6 consecutive samples */
|
||||
ec->adapt = 1;
|
||||
memcpy(ec->fir_taps16[0], ec->fir_taps16[1],
|
||||
ec->taps * sizeof(int16_t));
|
||||
} else
|
||||
ec->cond_met++;
|
||||
} else
|
||||
ec->cond_met = 0;
|
||||
|
||||
/* Non-Linear Processing --------------------------------------------------- */
|
||||
|
||||
ec->clean_nlp = ec->clean;
|
||||
if (ec->adaption_mode & ECHO_CAN_USE_NLP) {
|
||||
/* Non-linear processor - a fancy way to say "zap small signals, to avoid
|
||||
residual echo due to (uLaw/ALaw) non-linearity in the channel.". */
|
||||
|
||||
if ((16 * ec->Lclean < ec->Ltx)) {
|
||||
/* Our e/c has improved echo by at least 24 dB (each factor of 2 is 6dB,
|
||||
so 2*2*2*2=16 is the same as 6+6+6+6=24dB) */
|
||||
if (ec->adaption_mode & ECHO_CAN_USE_CNG) {
|
||||
ec->cng_level = ec->Lbgn;
|
||||
|
||||
/* Very elementary comfort noise generation. Just random
|
||||
numbers rolled off very vaguely Hoth-like. DR: This
|
||||
noise doesn't sound quite right to me - I suspect there
|
||||
are some overlfow issues in the filtering as it's too
|
||||
"crackly". TODO: debug this, maybe just play noise at
|
||||
high level or look at spectrum.
|
||||
*/
|
||||
|
||||
ec->cng_rndnum =
|
||||
1664525U * ec->cng_rndnum + 1013904223U;
|
||||
ec->cng_filter =
|
||||
((ec->cng_rndnum & 0xFFFF) - 32768 +
|
||||
5 * ec->cng_filter) >> 3;
|
||||
ec->clean_nlp =
|
||||
(ec->cng_filter * ec->cng_level * 8) >> 14;
|
||||
|
||||
} else if (ec->adaption_mode & ECHO_CAN_USE_CLIP) {
|
||||
/* This sounds much better than CNG */
|
||||
if (ec->clean_nlp > ec->Lbgn)
|
||||
ec->clean_nlp = ec->Lbgn;
|
||||
if (ec->clean_nlp < -ec->Lbgn)
|
||||
ec->clean_nlp = -ec->Lbgn;
|
||||
} else {
|
||||
/* just mute the residual, doesn't sound very good, used mainly
|
||||
in G168 tests */
|
||||
ec->clean_nlp = 0;
|
||||
}
|
||||
} else {
|
||||
/* Background noise estimator. I tried a few algorithms
|
||||
here without much luck. This very simple one seems to
|
||||
work best, we just average the level using a slow (1 sec
|
||||
time const) filter if the current level is less than a
|
||||
(experimentally derived) constant. This means we dont
|
||||
include high level signals like near end speech. When
|
||||
combined with CNG or especially CLIP seems to work OK.
|
||||
*/
|
||||
if (ec->Lclean < 40) {
|
||||
ec->Lbgn_acc += abs(ec->clean) - ec->Lbgn;
|
||||
ec->Lbgn = (ec->Lbgn_acc + (1 << 11)) >> 12;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Roll around the taps buffer */
|
||||
if (ec->curr_pos <= 0)
|
||||
ec->curr_pos = ec->taps;
|
||||
ec->curr_pos--;
|
||||
|
||||
if (ec->adaption_mode & ECHO_CAN_DISABLE)
|
||||
ec->clean_nlp = rx;
|
||||
|
||||
/* Output scaled back up again to match input scaling */
|
||||
|
||||
return (int16_t) ec->clean_nlp << 1;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(oslec_update);
|
||||
|
||||
/* This function is seperated from the echo canceller is it is usually called
|
||||
as part of the tx process. See rx HP (DC blocking) filter above, it's
|
||||
the same design.
|
||||
|
||||
Some soft phones send speech signals with a lot of low frequency
|
||||
energy, e.g. down to 20Hz. This can make the hybrid non-linear
|
||||
which causes the echo canceller to fall over. This filter can help
|
||||
by removing any low frequency before it gets to the tx port of the
|
||||
hybrid.
|
||||
|
||||
It can also help by removing and DC in the tx signal. DC is bad
|
||||
for LMS algorithms.
|
||||
|
||||
This is one of the classic DC removal filters, adjusted to provide sufficient
|
||||
bass rolloff to meet the above requirement to protect hybrids from things that
|
||||
upset them. The difference between successive samples produces a lousy HPF, and
|
||||
then a suitably placed pole flattens things out. The final result is a nicely
|
||||
rolled off bass end. The filtering is implemented with extended fractional
|
||||
precision, which noise shapes things, giving very clean DC removal.
|
||||
*/
|
||||
|
||||
int16_t oslec_hpf_tx(struct oslec_state * ec, int16_t tx)
|
||||
{
|
||||
int tmp, tmp1;
|
||||
|
||||
if (ec->adaption_mode & ECHO_CAN_USE_TX_HPF) {
|
||||
tmp = tx << 15;
|
||||
#if 1
|
||||
/* Make sure the gain of the HPF is 1.0. The first can still saturate a little under
|
||||
impulse conditions, and it might roll to 32768 and need clipping on sustained peak
|
||||
level signals. However, the scale of such clipping is small, and the error due to
|
||||
any saturation should not markedly affect the downstream processing. */
|
||||
tmp -= (tmp >> 4);
|
||||
#endif
|
||||
ec->tx_1 += -(ec->tx_1 >> DC_LOG2BETA) + tmp - ec->tx_2;
|
||||
tmp1 = ec->tx_1 >> 15;
|
||||
if (tmp1 > 32767)
|
||||
tmp1 = 32767;
|
||||
if (tmp1 < -32767)
|
||||
tmp1 = -32767;
|
||||
tx = tmp1;
|
||||
ec->tx_2 = tmp;
|
||||
}
|
||||
|
||||
return tx;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(oslec_hpf_tx);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("David Rowe");
|
||||
MODULE_DESCRIPTION("Open Source Line Echo Canceller");
|
||||
MODULE_VERSION("0.3.0");
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* SpanDSP - a series of DSP components for telephony
|
||||
*
|
||||
* echo.c - A line echo canceller. This code is being developed
|
||||
* against and partially complies with G168.
|
||||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
* and David Rowe <david_at_rowetel_dot_com>
|
||||
*
|
||||
* Copyright (C) 2001 Steve Underwood and 2007 David Rowe
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: echo.h,v 1.9 2006/10/24 13:45:28 steveu Exp $
|
||||
*/
|
||||
|
||||
#ifndef __ECHO_H
|
||||
#define __ECHO_H
|
||||
|
||||
/*! \page echo_can_page Line echo cancellation for voice
|
||||
|
||||
\section echo_can_page_sec_1 What does it do?
|
||||
This module aims to provide G.168-2002 compliant echo cancellation, to remove
|
||||
electrical echoes (e.g. from 2-4 wire hybrids) from voice calls.
|
||||
|
||||
\section echo_can_page_sec_2 How does it work?
|
||||
The heart of the echo cancellor is FIR filter. This is adapted to match the
|
||||
echo impulse response of the telephone line. It must be long enough to
|
||||
adequately cover the duration of that impulse response. The signal transmitted
|
||||
to the telephone line is passed through the FIR filter. Once the FIR is
|
||||
properly adapted, the resulting output is an estimate of the echo signal
|
||||
received from the line. This is subtracted from the received signal. The result
|
||||
is an estimate of the signal which originated at the far end of the line, free
|
||||
from echos of our own transmitted signal.
|
||||
|
||||
The least mean squares (LMS) algorithm is attributed to Widrow and Hoff, and
|
||||
was introduced in 1960. It is the commonest form of filter adaption used in
|
||||
things like modem line equalisers and line echo cancellers. There it works very
|
||||
well. However, it only works well for signals of constant amplitude. It works
|
||||
very poorly for things like speech echo cancellation, where the signal level
|
||||
varies widely. This is quite easy to fix. If the signal level is normalised -
|
||||
similar to applying AGC - LMS can work as well for a signal of varying
|
||||
amplitude as it does for a modem signal. This normalised least mean squares
|
||||
(NLMS) algorithm is the commonest one used for speech echo cancellation. Many
|
||||
other algorithms exist - e.g. RLS (essentially the same as Kalman filtering),
|
||||
FAP, etc. Some perform significantly better than NLMS. However, factors such
|
||||
as computational complexity and patents favour the use of NLMS.
|
||||
|
||||
A simple refinement to NLMS can improve its performance with speech. NLMS tends
|
||||
to adapt best to the strongest parts of a signal. If the signal is white noise,
|
||||
the NLMS algorithm works very well. However, speech has more low frequency than
|
||||
high frequency content. Pre-whitening (i.e. filtering the signal to flatten its
|
||||
spectrum) the echo signal improves the adapt rate for speech, and ensures the
|
||||
final residual signal is not heavily biased towards high frequencies. A very
|
||||
low complexity filter is adequate for this, so pre-whitening adds little to the
|
||||
compute requirements of the echo canceller.
|
||||
|
||||
An FIR filter adapted using pre-whitened NLMS performs well, provided certain
|
||||
conditions are met:
|
||||
|
||||
- The transmitted signal has poor self-correlation.
|
||||
- There is no signal being generated within the environment being
|
||||
cancelled.
|
||||
|
||||
The difficulty is that neither of these can be guaranteed.
|
||||
|
||||
If the adaption is performed while transmitting noise (or something fairly
|
||||
noise like, such as voice) the adaption works very well. If the adaption is
|
||||
performed while transmitting something highly correlative (typically narrow
|
||||
band energy such as signalling tones or DTMF), the adaption can go seriously
|
||||
wrong. The reason is there is only one solution for the adaption on a near
|
||||
random signal - the impulse response of the line. For a repetitive signal,
|
||||
there are any number of solutions which converge the adaption, and nothing
|
||||
guides the adaption to choose the generalised one. Allowing an untrained
|
||||
canceller to converge on this kind of narrowband energy probably a good thing,
|
||||
since at least it cancels the tones. Allowing a well converged canceller to
|
||||
continue converging on such energy is just a way to ruin its generalised
|
||||
adaption. A narrowband detector is needed, so adapation can be suspended at
|
||||
appropriate times.
|
||||
|
||||
The adaption process is based on trying to eliminate the received signal. When
|
||||
there is any signal from within the environment being cancelled it may upset
|
||||
the adaption process. Similarly, if the signal we are transmitting is small,
|
||||
noise may dominate and disturb the adaption process. If we can ensure that the
|
||||
adaption is only performed when we are transmitting a significant signal level,
|
||||
and the environment is not, things will be OK. Clearly, it is easy to tell when
|
||||
we are sending a significant signal. Telling, if the environment is generating
|
||||
a significant signal, and doing it with sufficient speed that the adaption will
|
||||
not have diverged too much more we stop it, is a little harder.
|
||||
|
||||
The key problem in detecting when the environment is sourcing significant
|
||||
energy is that we must do this very quickly. Given a reasonably long sample of
|
||||
the received signal, there are a number of strategies which may be used to
|
||||
assess whether that signal contains a strong far end component. However, by the
|
||||
time that assessment is complete the far end signal will have already caused
|
||||
major mis-convergence in the adaption process. An assessment algorithm is
|
||||
needed which produces a fairly accurate result from a very short burst of far
|
||||
end energy.
|
||||
|
||||
\section echo_can_page_sec_3 How do I use it?
|
||||
The echo cancellor processes both the transmit and receive streams sample by
|
||||
sample. The processing function is not declared inline. Unfortunately,
|
||||
cancellation requires many operations per sample, so the call overhead is only
|
||||
a minor burden.
|
||||
*/
|
||||
|
||||
#include "fir.h"
|
||||
#include "oslec.h"
|
||||
|
||||
/*!
|
||||
G.168 echo canceller descriptor. This defines the working state for a line
|
||||
echo canceller.
|
||||
*/
|
||||
struct oslec_state {
|
||||
int16_t tx, rx;
|
||||
int16_t clean;
|
||||
int16_t clean_nlp;
|
||||
|
||||
int nonupdate_dwell;
|
||||
int curr_pos;
|
||||
int taps;
|
||||
int log2taps;
|
||||
int adaption_mode;
|
||||
|
||||
int cond_met;
|
||||
int32_t Pstates;
|
||||
int16_t adapt;
|
||||
int32_t factor;
|
||||
int16_t shift;
|
||||
|
||||
/* Average levels and averaging filter states */
|
||||
int Ltxacc, Lrxacc, Lcleanacc, Lclean_bgacc;
|
||||
int Ltx, Lrx;
|
||||
int Lclean;
|
||||
int Lclean_bg;
|
||||
int Lbgn, Lbgn_acc, Lbgn_upper, Lbgn_upper_acc;
|
||||
|
||||
/* foreground and background filter states */
|
||||
fir16_state_t fir_state;
|
||||
fir16_state_t fir_state_bg;
|
||||
int16_t *fir_taps16[2];
|
||||
|
||||
/* DC blocking filter states */
|
||||
int tx_1, tx_2, rx_1, rx_2;
|
||||
|
||||
/* optional High Pass Filter states */
|
||||
int32_t xvtx[5], yvtx[5];
|
||||
int32_t xvrx[5], yvrx[5];
|
||||
|
||||
/* Parameters for the optional Hoth noise generator */
|
||||
int cng_level;
|
||||
int cng_rndnum;
|
||||
int cng_filter;
|
||||
|
||||
/* snapshot sample of coeffs used for development */
|
||||
int16_t *snapshot;
|
||||
};
|
||||
|
||||
#endif /* __ECHO_H */
|
|
@ -0,0 +1,295 @@
|
|||
/*
|
||||
* SpanDSP - a series of DSP components for telephony
|
||||
*
|
||||
* fir.h - General telephony FIR routines
|
||||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Copyright (C) 2002 Steve Underwood
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: fir.h,v 1.8 2006/10/24 13:45:28 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \page fir_page FIR filtering
|
||||
\section fir_page_sec_1 What does it do?
|
||||
???.
|
||||
|
||||
\section fir_page_sec_2 How does it work?
|
||||
???.
|
||||
*/
|
||||
|
||||
#if !defined(_FIR_H_)
|
||||
#define _FIR_H_
|
||||
|
||||
/*
|
||||
Blackfin NOTES & IDEAS:
|
||||
|
||||
A simple dot product function is used to implement the filter. This performs
|
||||
just one MAC/cycle which is inefficient but was easy to implement as a first
|
||||
pass. The current Blackfin code also uses an unrolled form of the filter
|
||||
history to avoid 0 length hardware loop issues. This is wasteful of
|
||||
memory.
|
||||
|
||||
Ideas for improvement:
|
||||
|
||||
1/ Rewrite filter for dual MAC inner loop. The issue here is handling
|
||||
history sample offsets that are 16 bit aligned - the dual MAC needs
|
||||
32 bit aligmnent. There are some good examples in libbfdsp.
|
||||
|
||||
2/ Use the hardware circular buffer facility tohalve memory usage.
|
||||
|
||||
3/ Consider using internal memory.
|
||||
|
||||
Using less memory might also improve speed as cache misses will be
|
||||
reduced. A drop in MIPs and memory approaching 50% should be
|
||||
possible.
|
||||
|
||||
The foreground and background filters currenlty use a total of
|
||||
about 10 MIPs/ch as measured with speedtest.c on a 256 TAP echo
|
||||
can.
|
||||
*/
|
||||
|
||||
#if defined(USE_MMX) || defined(USE_SSE2)
|
||||
#include "mmx.h"
|
||||
#endif
|
||||
|
||||
/*!
|
||||
16 bit integer FIR descriptor. This defines the working state for a single
|
||||
instance of an FIR filter using 16 bit integer coefficients.
|
||||
*/
|
||||
typedef struct {
|
||||
int taps;
|
||||
int curr_pos;
|
||||
const int16_t *coeffs;
|
||||
int16_t *history;
|
||||
} fir16_state_t;
|
||||
|
||||
/*!
|
||||
32 bit integer FIR descriptor. This defines the working state for a single
|
||||
instance of an FIR filter using 32 bit integer coefficients, and filtering
|
||||
16 bit integer data.
|
||||
*/
|
||||
typedef struct {
|
||||
int taps;
|
||||
int curr_pos;
|
||||
const int32_t *coeffs;
|
||||
int16_t *history;
|
||||
} fir32_state_t;
|
||||
|
||||
/*!
|
||||
Floating point FIR descriptor. This defines the working state for a single
|
||||
instance of an FIR filter using floating point coefficients and data.
|
||||
*/
|
||||
typedef struct {
|
||||
int taps;
|
||||
int curr_pos;
|
||||
const float *coeffs;
|
||||
float *history;
|
||||
} fir_float_state_t;
|
||||
|
||||
static __inline__ const int16_t *fir16_create(fir16_state_t * fir,
|
||||
const int16_t * coeffs, int taps)
|
||||
{
|
||||
fir->taps = taps;
|
||||
fir->curr_pos = taps - 1;
|
||||
fir->coeffs = coeffs;
|
||||
#if defined(USE_MMX) || defined(USE_SSE2) || defined(__bfin__)
|
||||
fir->history = kcalloc(2 * taps, sizeof(int16_t), GFP_KERNEL);
|
||||
#else
|
||||
fir->history = kcalloc(taps, sizeof(int16_t), GFP_KERNEL);
|
||||
#endif
|
||||
return fir->history;
|
||||
}
|
||||
|
||||
static __inline__ void fir16_flush(fir16_state_t * fir)
|
||||
{
|
||||
#if defined(USE_MMX) || defined(USE_SSE2) || defined(__bfin__)
|
||||
memset(fir->history, 0, 2 * fir->taps * sizeof(int16_t));
|
||||
#else
|
||||
memset(fir->history, 0, fir->taps * sizeof(int16_t));
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline__ void fir16_free(fir16_state_t * fir)
|
||||
{
|
||||
kfree(fir->history);
|
||||
}
|
||||
|
||||
#ifdef __bfin__
|
||||
static inline int32_t dot_asm(short *x, short *y, int len)
|
||||
{
|
||||
int dot;
|
||||
|
||||
len--;
|
||||
|
||||
__asm__("I0 = %1;\n\t"
|
||||
"I1 = %2;\n\t"
|
||||
"A0 = 0;\n\t"
|
||||
"R0.L = W[I0++] || R1.L = W[I1++];\n\t"
|
||||
"LOOP dot%= LC0 = %3;\n\t"
|
||||
"LOOP_BEGIN dot%=;\n\t"
|
||||
"A0 += R0.L * R1.L (IS) || R0.L = W[I0++] || R1.L = W[I1++];\n\t"
|
||||
"LOOP_END dot%=;\n\t"
|
||||
"A0 += R0.L*R1.L (IS);\n\t"
|
||||
"R0 = A0;\n\t"
|
||||
"%0 = R0;\n\t"
|
||||
:"=&d"(dot)
|
||||
:"a"(x), "a"(y), "a"(len)
|
||||
:"I0", "I1", "A1", "A0", "R0", "R1"
|
||||
);
|
||||
|
||||
return dot;
|
||||
}
|
||||
#endif
|
||||
|
||||
static __inline__ int16_t fir16(fir16_state_t * fir, int16_t sample)
|
||||
{
|
||||
int32_t y;
|
||||
#if defined(USE_MMX)
|
||||
int i;
|
||||
mmx_t *mmx_coeffs;
|
||||
mmx_t *mmx_hist;
|
||||
|
||||
fir->history[fir->curr_pos] = sample;
|
||||
fir->history[fir->curr_pos + fir->taps] = sample;
|
||||
|
||||
mmx_coeffs = (mmx_t *) fir->coeffs;
|
||||
mmx_hist = (mmx_t *) & fir->history[fir->curr_pos];
|
||||
i = fir->taps;
|
||||
pxor_r2r(mm4, mm4);
|
||||
/* 8 samples per iteration, so the filter must be a multiple of 8 long. */
|
||||
while (i > 0) {
|
||||
movq_m2r(mmx_coeffs[0], mm0);
|
||||
movq_m2r(mmx_coeffs[1], mm2);
|
||||
movq_m2r(mmx_hist[0], mm1);
|
||||
movq_m2r(mmx_hist[1], mm3);
|
||||
mmx_coeffs += 2;
|
||||
mmx_hist += 2;
|
||||
pmaddwd_r2r(mm1, mm0);
|
||||
pmaddwd_r2r(mm3, mm2);
|
||||
paddd_r2r(mm0, mm4);
|
||||
paddd_r2r(mm2, mm4);
|
||||
i -= 8;
|
||||
}
|
||||
movq_r2r(mm4, mm0);
|
||||
psrlq_i2r(32, mm0);
|
||||
paddd_r2r(mm0, mm4);
|
||||
movd_r2m(mm4, y);
|
||||
emms();
|
||||
#elif defined(USE_SSE2)
|
||||
int i;
|
||||
xmm_t *xmm_coeffs;
|
||||
xmm_t *xmm_hist;
|
||||
|
||||
fir->history[fir->curr_pos] = sample;
|
||||
fir->history[fir->curr_pos + fir->taps] = sample;
|
||||
|
||||
xmm_coeffs = (xmm_t *) fir->coeffs;
|
||||
xmm_hist = (xmm_t *) & fir->history[fir->curr_pos];
|
||||
i = fir->taps;
|
||||
pxor_r2r(xmm4, xmm4);
|
||||
/* 16 samples per iteration, so the filter must be a multiple of 16 long. */
|
||||
while (i > 0) {
|
||||
movdqu_m2r(xmm_coeffs[0], xmm0);
|
||||
movdqu_m2r(xmm_coeffs[1], xmm2);
|
||||
movdqu_m2r(xmm_hist[0], xmm1);
|
||||
movdqu_m2r(xmm_hist[1], xmm3);
|
||||
xmm_coeffs += 2;
|
||||
xmm_hist += 2;
|
||||
pmaddwd_r2r(xmm1, xmm0);
|
||||
pmaddwd_r2r(xmm3, xmm2);
|
||||
paddd_r2r(xmm0, xmm4);
|
||||
paddd_r2r(xmm2, xmm4);
|
||||
i -= 16;
|
||||
}
|
||||
movdqa_r2r(xmm4, xmm0);
|
||||
psrldq_i2r(8, xmm0);
|
||||
paddd_r2r(xmm0, xmm4);
|
||||
movdqa_r2r(xmm4, xmm0);
|
||||
psrldq_i2r(4, xmm0);
|
||||
paddd_r2r(xmm0, xmm4);
|
||||
movd_r2m(xmm4, y);
|
||||
#elif defined(__bfin__)
|
||||
fir->history[fir->curr_pos] = sample;
|
||||
fir->history[fir->curr_pos + fir->taps] = sample;
|
||||
y = dot_asm((int16_t *) fir->coeffs, &fir->history[fir->curr_pos],
|
||||
fir->taps);
|
||||
#else
|
||||
int i;
|
||||
int offset1;
|
||||
int offset2;
|
||||
|
||||
fir->history[fir->curr_pos] = sample;
|
||||
|
||||
offset2 = fir->curr_pos;
|
||||
offset1 = fir->taps - offset2;
|
||||
y = 0;
|
||||
for (i = fir->taps - 1; i >= offset1; i--)
|
||||
y += fir->coeffs[i] * fir->history[i - offset1];
|
||||
for (; i >= 0; i--)
|
||||
y += fir->coeffs[i] * fir->history[i + offset2];
|
||||
#endif
|
||||
if (fir->curr_pos <= 0)
|
||||
fir->curr_pos = fir->taps;
|
||||
fir->curr_pos--;
|
||||
return (int16_t) (y >> 15);
|
||||
}
|
||||
|
||||
static __inline__ const int16_t *fir32_create(fir32_state_t * fir,
|
||||
const int32_t * coeffs, int taps)
|
||||
{
|
||||
fir->taps = taps;
|
||||
fir->curr_pos = taps - 1;
|
||||
fir->coeffs = coeffs;
|
||||
fir->history = kcalloc(taps, sizeof(int16_t), GFP_KERNEL);
|
||||
return fir->history;
|
||||
}
|
||||
|
||||
static __inline__ void fir32_flush(fir32_state_t * fir)
|
||||
{
|
||||
memset(fir->history, 0, fir->taps * sizeof(int16_t));
|
||||
}
|
||||
|
||||
static __inline__ void fir32_free(fir32_state_t * fir)
|
||||
{
|
||||
kfree(fir->history);
|
||||
}
|
||||
|
||||
static __inline__ int16_t fir32(fir32_state_t * fir, int16_t sample)
|
||||
{
|
||||
int i;
|
||||
int32_t y;
|
||||
int offset1;
|
||||
int offset2;
|
||||
|
||||
fir->history[fir->curr_pos] = sample;
|
||||
offset2 = fir->curr_pos;
|
||||
offset1 = fir->taps - offset2;
|
||||
y = 0;
|
||||
for (i = fir->taps - 1; i >= offset1; i--)
|
||||
y += fir->coeffs[i] * fir->history[i - offset1];
|
||||
for (; i >= 0; i--)
|
||||
y += fir->coeffs[i] * fir->history[i + offset2];
|
||||
if (fir->curr_pos <= 0)
|
||||
fir->curr_pos = fir->taps;
|
||||
fir->curr_pos--;
|
||||
return (int16_t) (y >> 15);
|
||||
}
|
||||
|
||||
#endif
|
||||
/*- End of file ------------------------------------------------------------*/
|
|
@ -0,0 +1,281 @@
|
|||
/*
|
||||
* mmx.h
|
||||
* Copyright (C) 1997-2001 H. Dietz and R. Fisher
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef AVCODEC_I386MMX_H
|
||||
#define AVCODEC_I386MMX_H
|
||||
|
||||
/*
|
||||
* The type of an value that fits in an MMX register (note that long
|
||||
* long constant values MUST be suffixed by LL and unsigned long long
|
||||
* values by ULL, lest they be truncated by the compiler)
|
||||
*/
|
||||
|
||||
typedef union {
|
||||
long long q; /* Quadword (64-bit) value */
|
||||
unsigned long long uq; /* Unsigned Quadword */
|
||||
int d[2]; /* 2 Doubleword (32-bit) values */
|
||||
unsigned int ud[2]; /* 2 Unsigned Doubleword */
|
||||
short w[4]; /* 4 Word (16-bit) values */
|
||||
unsigned short uw[4]; /* 4 Unsigned Word */
|
||||
char b[8]; /* 8 Byte (8-bit) values */
|
||||
unsigned char ub[8]; /* 8 Unsigned Byte */
|
||||
float s[2]; /* Single-precision (32-bit) value */
|
||||
} mmx_t; /* On an 8-byte (64-bit) boundary */
|
||||
|
||||
/* SSE registers */
|
||||
typedef union {
|
||||
char b[16];
|
||||
} xmm_t;
|
||||
|
||||
#define mmx_i2r(op,imm,reg) \
|
||||
__asm__ __volatile__ (#op " %0, %%" #reg \
|
||||
: /* nothing */ \
|
||||
: "i" (imm) )
|
||||
|
||||
#define mmx_m2r(op,mem,reg) \
|
||||
__asm__ __volatile__ (#op " %0, %%" #reg \
|
||||
: /* nothing */ \
|
||||
: "m" (mem))
|
||||
|
||||
#define mmx_r2m(op,reg,mem) \
|
||||
__asm__ __volatile__ (#op " %%" #reg ", %0" \
|
||||
: "=m" (mem) \
|
||||
: /* nothing */ )
|
||||
|
||||
#define mmx_r2r(op,regs,regd) \
|
||||
__asm__ __volatile__ (#op " %" #regs ", %" #regd)
|
||||
|
||||
#define emms() __asm__ __volatile__ ("emms")
|
||||
|
||||
#define movd_m2r(var,reg) mmx_m2r (movd, var, reg)
|
||||
#define movd_r2m(reg,var) mmx_r2m (movd, reg, var)
|
||||
#define movd_r2r(regs,regd) mmx_r2r (movd, regs, regd)
|
||||
|
||||
#define movq_m2r(var,reg) mmx_m2r (movq, var, reg)
|
||||
#define movq_r2m(reg,var) mmx_r2m (movq, reg, var)
|
||||
#define movq_r2r(regs,regd) mmx_r2r (movq, regs, regd)
|
||||
|
||||
#define packssdw_m2r(var,reg) mmx_m2r (packssdw, var, reg)
|
||||
#define packssdw_r2r(regs,regd) mmx_r2r (packssdw, regs, regd)
|
||||
#define packsswb_m2r(var,reg) mmx_m2r (packsswb, var, reg)
|
||||
#define packsswb_r2r(regs,regd) mmx_r2r (packsswb, regs, regd)
|
||||
|
||||
#define packuswb_m2r(var,reg) mmx_m2r (packuswb, var, reg)
|
||||
#define packuswb_r2r(regs,regd) mmx_r2r (packuswb, regs, regd)
|
||||
|
||||
#define paddb_m2r(var,reg) mmx_m2r (paddb, var, reg)
|
||||
#define paddb_r2r(regs,regd) mmx_r2r (paddb, regs, regd)
|
||||
#define paddd_m2r(var,reg) mmx_m2r (paddd, var, reg)
|
||||
#define paddd_r2r(regs,regd) mmx_r2r (paddd, regs, regd)
|
||||
#define paddw_m2r(var,reg) mmx_m2r (paddw, var, reg)
|
||||
#define paddw_r2r(regs,regd) mmx_r2r (paddw, regs, regd)
|
||||
|
||||
#define paddsb_m2r(var,reg) mmx_m2r (paddsb, var, reg)
|
||||
#define paddsb_r2r(regs,regd) mmx_r2r (paddsb, regs, regd)
|
||||
#define paddsw_m2r(var,reg) mmx_m2r (paddsw, var, reg)
|
||||
#define paddsw_r2r(regs,regd) mmx_r2r (paddsw, regs, regd)
|
||||
|
||||
#define paddusb_m2r(var,reg) mmx_m2r (paddusb, var, reg)
|
||||
#define paddusb_r2r(regs,regd) mmx_r2r (paddusb, regs, regd)
|
||||
#define paddusw_m2r(var,reg) mmx_m2r (paddusw, var, reg)
|
||||
#define paddusw_r2r(regs,regd) mmx_r2r (paddusw, regs, regd)
|
||||
|
||||
#define pand_m2r(var,reg) mmx_m2r (pand, var, reg)
|
||||
#define pand_r2r(regs,regd) mmx_r2r (pand, regs, regd)
|
||||
|
||||
#define pandn_m2r(var,reg) mmx_m2r (pandn, var, reg)
|
||||
#define pandn_r2r(regs,regd) mmx_r2r (pandn, regs, regd)
|
||||
|
||||
#define pcmpeqb_m2r(var,reg) mmx_m2r (pcmpeqb, var, reg)
|
||||
#define pcmpeqb_r2r(regs,regd) mmx_r2r (pcmpeqb, regs, regd)
|
||||
#define pcmpeqd_m2r(var,reg) mmx_m2r (pcmpeqd, var, reg)
|
||||
#define pcmpeqd_r2r(regs,regd) mmx_r2r (pcmpeqd, regs, regd)
|
||||
#define pcmpeqw_m2r(var,reg) mmx_m2r (pcmpeqw, var, reg)
|
||||
#define pcmpeqw_r2r(regs,regd) mmx_r2r (pcmpeqw, regs, regd)
|
||||
|
||||
#define pcmpgtb_m2r(var,reg) mmx_m2r (pcmpgtb, var, reg)
|
||||
#define pcmpgtb_r2r(regs,regd) mmx_r2r (pcmpgtb, regs, regd)
|
||||
#define pcmpgtd_m2r(var,reg) mmx_m2r (pcmpgtd, var, reg)
|
||||
#define pcmpgtd_r2r(regs,regd) mmx_r2r (pcmpgtd, regs, regd)
|
||||
#define pcmpgtw_m2r(var,reg) mmx_m2r (pcmpgtw, var, reg)
|
||||
#define pcmpgtw_r2r(regs,regd) mmx_r2r (pcmpgtw, regs, regd)
|
||||
|
||||
#define pmaddwd_m2r(var,reg) mmx_m2r (pmaddwd, var, reg)
|
||||
#define pmaddwd_r2r(regs,regd) mmx_r2r (pmaddwd, regs, regd)
|
||||
|
||||
#define pmulhw_m2r(var,reg) mmx_m2r (pmulhw, var, reg)
|
||||
#define pmulhw_r2r(regs,regd) mmx_r2r (pmulhw, regs, regd)
|
||||
|
||||
#define pmullw_m2r(var,reg) mmx_m2r (pmullw, var, reg)
|
||||
#define pmullw_r2r(regs,regd) mmx_r2r (pmullw, regs, regd)
|
||||
|
||||
#define por_m2r(var,reg) mmx_m2r (por, var, reg)
|
||||
#define por_r2r(regs,regd) mmx_r2r (por, regs, regd)
|
||||
|
||||
#define pslld_i2r(imm,reg) mmx_i2r (pslld, imm, reg)
|
||||
#define pslld_m2r(var,reg) mmx_m2r (pslld, var, reg)
|
||||
#define pslld_r2r(regs,regd) mmx_r2r (pslld, regs, regd)
|
||||
#define psllq_i2r(imm,reg) mmx_i2r (psllq, imm, reg)
|
||||
#define psllq_m2r(var,reg) mmx_m2r (psllq, var, reg)
|
||||
#define psllq_r2r(regs,regd) mmx_r2r (psllq, regs, regd)
|
||||
#define psllw_i2r(imm,reg) mmx_i2r (psllw, imm, reg)
|
||||
#define psllw_m2r(var,reg) mmx_m2r (psllw, var, reg)
|
||||
#define psllw_r2r(regs,regd) mmx_r2r (psllw, regs, regd)
|
||||
|
||||
#define psrad_i2r(imm,reg) mmx_i2r (psrad, imm, reg)
|
||||
#define psrad_m2r(var,reg) mmx_m2r (psrad, var, reg)
|
||||
#define psrad_r2r(regs,regd) mmx_r2r (psrad, regs, regd)
|
||||
#define psraw_i2r(imm,reg) mmx_i2r (psraw, imm, reg)
|
||||
#define psraw_m2r(var,reg) mmx_m2r (psraw, var, reg)
|
||||
#define psraw_r2r(regs,regd) mmx_r2r (psraw, regs, regd)
|
||||
|
||||
#define psrld_i2r(imm,reg) mmx_i2r (psrld, imm, reg)
|
||||
#define psrld_m2r(var,reg) mmx_m2r (psrld, var, reg)
|
||||
#define psrld_r2r(regs,regd) mmx_r2r (psrld, regs, regd)
|
||||
#define psrlq_i2r(imm,reg) mmx_i2r (psrlq, imm, reg)
|
||||
#define psrlq_m2r(var,reg) mmx_m2r (psrlq, var, reg)
|
||||
#define psrlq_r2r(regs,regd) mmx_r2r (psrlq, regs, regd)
|
||||
#define psrlw_i2r(imm,reg) mmx_i2r (psrlw, imm, reg)
|
||||
#define psrlw_m2r(var,reg) mmx_m2r (psrlw, var, reg)
|
||||
#define psrlw_r2r(regs,regd) mmx_r2r (psrlw, regs, regd)
|
||||
|
||||
#define psubb_m2r(var,reg) mmx_m2r (psubb, var, reg)
|
||||
#define psubb_r2r(regs,regd) mmx_r2r (psubb, regs, regd)
|
||||
#define psubd_m2r(var,reg) mmx_m2r (psubd, var, reg)
|
||||
#define psubd_r2r(regs,regd) mmx_r2r (psubd, regs, regd)
|
||||
#define psubw_m2r(var,reg) mmx_m2r (psubw, var, reg)
|
||||
#define psubw_r2r(regs,regd) mmx_r2r (psubw, regs, regd)
|
||||
|
||||
#define psubsb_m2r(var,reg) mmx_m2r (psubsb, var, reg)
|
||||
#define psubsb_r2r(regs,regd) mmx_r2r (psubsb, regs, regd)
|
||||
#define psubsw_m2r(var,reg) mmx_m2r (psubsw, var, reg)
|
||||
#define psubsw_r2r(regs,regd) mmx_r2r (psubsw, regs, regd)
|
||||
|
||||
#define psubusb_m2r(var,reg) mmx_m2r (psubusb, var, reg)
|
||||
#define psubusb_r2r(regs,regd) mmx_r2r (psubusb, regs, regd)
|
||||
#define psubusw_m2r(var,reg) mmx_m2r (psubusw, var, reg)
|
||||
#define psubusw_r2r(regs,regd) mmx_r2r (psubusw, regs, regd)
|
||||
|
||||
#define punpckhbw_m2r(var,reg) mmx_m2r (punpckhbw, var, reg)
|
||||
#define punpckhbw_r2r(regs,regd) mmx_r2r (punpckhbw, regs, regd)
|
||||
#define punpckhdq_m2r(var,reg) mmx_m2r (punpckhdq, var, reg)
|
||||
#define punpckhdq_r2r(regs,regd) mmx_r2r (punpckhdq, regs, regd)
|
||||
#define punpckhwd_m2r(var,reg) mmx_m2r (punpckhwd, var, reg)
|
||||
#define punpckhwd_r2r(regs,regd) mmx_r2r (punpckhwd, regs, regd)
|
||||
|
||||
#define punpcklbw_m2r(var,reg) mmx_m2r (punpcklbw, var, reg)
|
||||
#define punpcklbw_r2r(regs,regd) mmx_r2r (punpcklbw, regs, regd)
|
||||
#define punpckldq_m2r(var,reg) mmx_m2r (punpckldq, var, reg)
|
||||
#define punpckldq_r2r(regs,regd) mmx_r2r (punpckldq, regs, regd)
|
||||
#define punpcklwd_m2r(var,reg) mmx_m2r (punpcklwd, var, reg)
|
||||
#define punpcklwd_r2r(regs,regd) mmx_r2r (punpcklwd, regs, regd)
|
||||
|
||||
#define pxor_m2r(var,reg) mmx_m2r (pxor, var, reg)
|
||||
#define pxor_r2r(regs,regd) mmx_r2r (pxor, regs, regd)
|
||||
|
||||
/* 3DNOW extensions */
|
||||
|
||||
#define pavgusb_m2r(var,reg) mmx_m2r (pavgusb, var, reg)
|
||||
#define pavgusb_r2r(regs,regd) mmx_r2r (pavgusb, regs, regd)
|
||||
|
||||
/* AMD MMX extensions - also available in intel SSE */
|
||||
|
||||
#define mmx_m2ri(op,mem,reg,imm) \
|
||||
__asm__ __volatile__ (#op " %1, %0, %%" #reg \
|
||||
: /* nothing */ \
|
||||
: "m" (mem), "i" (imm))
|
||||
#define mmx_r2ri(op,regs,regd,imm) \
|
||||
__asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \
|
||||
: /* nothing */ \
|
||||
: "i" (imm) )
|
||||
|
||||
#define mmx_fetch(mem,hint) \
|
||||
__asm__ __volatile__ ("prefetch" #hint " %0" \
|
||||
: /* nothing */ \
|
||||
: "m" (mem))
|
||||
|
||||
#define maskmovq(regs,maskreg) mmx_r2ri (maskmovq, regs, maskreg)
|
||||
|
||||
#define movntq_r2m(mmreg,var) mmx_r2m (movntq, mmreg, var)
|
||||
|
||||
#define pavgb_m2r(var,reg) mmx_m2r (pavgb, var, reg)
|
||||
#define pavgb_r2r(regs,regd) mmx_r2r (pavgb, regs, regd)
|
||||
#define pavgw_m2r(var,reg) mmx_m2r (pavgw, var, reg)
|
||||
#define pavgw_r2r(regs,regd) mmx_r2r (pavgw, regs, regd)
|
||||
|
||||
#define pextrw_r2r(mmreg,reg,imm) mmx_r2ri (pextrw, mmreg, reg, imm)
|
||||
|
||||
#define pinsrw_r2r(reg,mmreg,imm) mmx_r2ri (pinsrw, reg, mmreg, imm)
|
||||
|
||||
#define pmaxsw_m2r(var,reg) mmx_m2r (pmaxsw, var, reg)
|
||||
#define pmaxsw_r2r(regs,regd) mmx_r2r (pmaxsw, regs, regd)
|
||||
|
||||
#define pmaxub_m2r(var,reg) mmx_m2r (pmaxub, var, reg)
|
||||
#define pmaxub_r2r(regs,regd) mmx_r2r (pmaxub, regs, regd)
|
||||
|
||||
#define pminsw_m2r(var,reg) mmx_m2r (pminsw, var, reg)
|
||||
#define pminsw_r2r(regs,regd) mmx_r2r (pminsw, regs, regd)
|
||||
|
||||
#define pminub_m2r(var,reg) mmx_m2r (pminub, var, reg)
|
||||
#define pminub_r2r(regs,regd) mmx_r2r (pminub, regs, regd)
|
||||
|
||||
#define pmovmskb(mmreg,reg) \
|
||||
__asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg)
|
||||
|
||||
#define pmulhuw_m2r(var,reg) mmx_m2r (pmulhuw, var, reg)
|
||||
#define pmulhuw_r2r(regs,regd) mmx_r2r (pmulhuw, regs, regd)
|
||||
|
||||
#define prefetcht0(mem) mmx_fetch (mem, t0)
|
||||
#define prefetcht1(mem) mmx_fetch (mem, t1)
|
||||
#define prefetcht2(mem) mmx_fetch (mem, t2)
|
||||
#define prefetchnta(mem) mmx_fetch (mem, nta)
|
||||
|
||||
#define psadbw_m2r(var,reg) mmx_m2r (psadbw, var, reg)
|
||||
#define psadbw_r2r(regs,regd) mmx_r2r (psadbw, regs, regd)
|
||||
|
||||
#define pshufw_m2r(var,reg,imm) mmx_m2ri(pshufw, var, reg, imm)
|
||||
#define pshufw_r2r(regs,regd,imm) mmx_r2ri(pshufw, regs, regd, imm)
|
||||
|
||||
#define sfence() __asm__ __volatile__ ("sfence\n\t")
|
||||
|
||||
/* SSE2 */
|
||||
#define pshufhw_m2r(var,reg,imm) mmx_m2ri(pshufhw, var, reg, imm)
|
||||
#define pshufhw_r2r(regs,regd,imm) mmx_r2ri(pshufhw, regs, regd, imm)
|
||||
#define pshuflw_m2r(var,reg,imm) mmx_m2ri(pshuflw, var, reg, imm)
|
||||
#define pshuflw_r2r(regs,regd,imm) mmx_r2ri(pshuflw, regs, regd, imm)
|
||||
|
||||
#define pshufd_r2r(regs,regd,imm) mmx_r2ri(pshufd, regs, regd, imm)
|
||||
|
||||
#define movdqa_m2r(var,reg) mmx_m2r (movdqa, var, reg)
|
||||
#define movdqa_r2m(reg,var) mmx_r2m (movdqa, reg, var)
|
||||
#define movdqa_r2r(regs,regd) mmx_r2r (movdqa, regs, regd)
|
||||
#define movdqu_m2r(var,reg) mmx_m2r (movdqu, var, reg)
|
||||
#define movdqu_r2m(reg,var) mmx_r2m (movdqu, reg, var)
|
||||
#define movdqu_r2r(regs,regd) mmx_r2r (movdqu, regs, regd)
|
||||
|
||||
#define pmullw_r2m(reg,var) mmx_r2m (pmullw, reg, var)
|
||||
|
||||
#define pslldq_i2r(imm,reg) mmx_i2r (pslldq, imm, reg)
|
||||
#define psrldq_i2r(imm,reg) mmx_i2r (psrldq, imm, reg)
|
||||
|
||||
#define punpcklqdq_r2r(regs,regd) mmx_r2r (punpcklqdq, regs, regd)
|
||||
#define punpckhqdq_r2r(regs,regd) mmx_r2r (punpckhqdq, regs, regd)
|
||||
|
||||
#endif /* AVCODEC_I386MMX_H */
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* OSLEC - A line echo canceller. This code is being developed
|
||||
* against and partially complies with G168. Using code from SpanDSP
|
||||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
* and David Rowe <david_at_rowetel_dot_com>
|
||||
*
|
||||
* Copyright (C) 2001 Steve Underwood and 2007-2008 David Rowe
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __OSLEC_H
|
||||
#define __OSLEC_H
|
||||
|
||||
/* TODO: document interface */
|
||||
|
||||
/* Mask bits for the adaption mode */
|
||||
#define ECHO_CAN_USE_ADAPTION 0x01
|
||||
#define ECHO_CAN_USE_NLP 0x02
|
||||
#define ECHO_CAN_USE_CNG 0x04
|
||||
#define ECHO_CAN_USE_CLIP 0x08
|
||||
#define ECHO_CAN_USE_TX_HPF 0x10
|
||||
#define ECHO_CAN_USE_RX_HPF 0x20
|
||||
#define ECHO_CAN_DISABLE 0x40
|
||||
|
||||
/*!
|
||||
G.168 echo canceller descriptor. This defines the working state for a line
|
||||
echo canceller.
|
||||
*/
|
||||
struct oslec_state;
|
||||
|
||||
/*! Create a voice echo canceller context.
|
||||
\param len The length of the canceller, in samples.
|
||||
\return The new canceller context, or NULL if the canceller could not be created.
|
||||
*/
|
||||
struct oslec_state *oslec_create(int len, int adaption_mode);
|
||||
|
||||
/*! Free a voice echo canceller context.
|
||||
\param ec The echo canceller context.
|
||||
*/
|
||||
void oslec_free(struct oslec_state *ec);
|
||||
|
||||
/*! Flush (reinitialise) a voice echo canceller context.
|
||||
\param ec The echo canceller context.
|
||||
*/
|
||||
void oslec_flush(struct oslec_state *ec);
|
||||
|
||||
/*! Set the adaption mode of a voice echo canceller context.
|
||||
\param ec The echo canceller context.
|
||||
\param adapt The mode.
|
||||
*/
|
||||
void oslec_adaption_mode(struct oslec_state *ec, int adaption_mode);
|
||||
|
||||
void oslec_snapshot(struct oslec_state *ec);
|
||||
|
||||
/*! Process a sample through a voice echo canceller.
|
||||
\param ec The echo canceller context.
|
||||
\param tx The transmitted audio sample.
|
||||
\param rx The received audio sample.
|
||||
\return The clean (echo cancelled) received sample.
|
||||
*/
|
||||
int16_t oslec_update(struct oslec_state *ec, int16_t tx, int16_t rx);
|
||||
|
||||
/*! Process to high pass filter the tx signal.
|
||||
\param ec The echo canceller context.
|
||||
\param tx The transmitted auio sample.
|
||||
\return The HP filtered transmit sample, send this to your D/A.
|
||||
*/
|
||||
int16_t oslec_hpf_tx(struct oslec_state *ec, int16_t tx);
|
||||
|
||||
#endif /* __OSLEC_H */
|
102
Setup
102
Setup
|
@ -9,7 +9,9 @@
|
|||
# as published by the Free Software Foundation; either version
|
||||
# 2 of the License, or (at your option) any later version.
|
||||
# ----------------------------------------------------------------------------
|
||||
# Oct 29, 2009 Yannick Lam Added --no_woomera option (will not install woomera)
|
||||
# May 10, 2010 Yannick Lam Added support for OSLEC for DAHDI only (--with-oslec)
|
||||
# Apr 22, 2010 Yannick Lam Added support for dahdi-2.3 for various chunksize
|
||||
# Oct 29, 2009 Yannick Lam Added --no_woomera option (will not install woomera)
|
||||
# Jul 29, 2009 Konrad Hammel Added --with-asterisk option
|
||||
# Jul 27, 2009 Konrad Hammel Update to not compile unneeded utilities in
|
||||
# TDM_VOICE mode.
|
||||
|
@ -4796,6 +4798,10 @@ function install_ssmg_ss7()
|
|||
if [ $SSMG_SS7 != "YES" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ $NO_SMG_INSTALL -eq 1 ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
banner
|
||||
|
||||
|
@ -5731,12 +5737,64 @@ function tdmv_apply_zaptel_chunk_patch () {
|
|||
zaptel_modified=1
|
||||
fi
|
||||
|
||||
eval "cat Kbuild | sed 's/^obj-.*+=.*wctdm24xxp.*//g'>$TEMP 2>/dev/null "
|
||||
if [ $? -ne 0 ]; then
|
||||
echo " Failed to remove wctdm24xxp from Kbuild"
|
||||
exit 1
|
||||
|
||||
else
|
||||
eval "\mv -f $TEMP Kbuild"
|
||||
echo " wctdm24xxp module removed from Kbuild successfully"
|
||||
zaptel_modified=1
|
||||
fi
|
||||
|
||||
eval "cat Kbuild | sed 's/^obj-.*+=.*wcte12xp.*//g'>$TEMP 2>/dev/null "
|
||||
if [ $? -ne 0 ]; then
|
||||
echo " Failed to remove wcte12xp from Kbuild"
|
||||
exit 1
|
||||
|
||||
else
|
||||
eval "\mv -f $TEMP Kbuild"
|
||||
echo " wcte12xp module removed from Kbuild successfully"
|
||||
zaptel_modified=1
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
cd $lhome
|
||||
return 0;
|
||||
}
|
||||
|
||||
function tdmv_apply_oslec_patch ()
|
||||
{
|
||||
lhome_tmp=`pwd`
|
||||
cd ..
|
||||
lhome=`pwd`
|
||||
TEMP=tmp
|
||||
cd $ZAPTEL_SOURCE_DIR
|
||||
echo "Applying Zaptel/Dahdi OSLEC echocanceler..."
|
||||
echo " "
|
||||
|
||||
dhname="Zaptel"
|
||||
isdahdi="no"
|
||||
if [ -f $ZAPTEL_SOURCE_DIR/dahdi/kernel.h ]; then
|
||||
filetopatch="$ZAPTEL_SOURCE_DIR/dahdi/kernel.h"
|
||||
dhname="Dahdi"
|
||||
isdahdi="yes"
|
||||
|
||||
cd ..
|
||||
eval "mkdir drivers/staging"
|
||||
eval "cp -rf $lhome/OSLEC/echo drivers/staging "
|
||||
sed -i "s|#obj-m += dahdi_echocan_oslec.o|obj-m += dahdi_echocan_oslec.o|" drivers/dahdi/Kbuild
|
||||
echo 'obj-m += echo.o' > drivers/staging/echo/Kbuild
|
||||
make
|
||||
make install
|
||||
cd $lhome_tmp
|
||||
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function tdmv_apply_zaptel_echo_debug_patch ()
|
||||
{
|
||||
local rc
|
||||
|
@ -6761,7 +6819,7 @@ ENDOFTEXT
|
|||
if [ $? -eq 0 ]; then
|
||||
if [ $AFT_TE1_PROT != YES ]; then
|
||||
echo "Enabling the AFT TE1 Support"
|
||||
PROTOCOL_DEFINES="$PROTOCOL_DEFINES -DCONFIG_PRODUCT_WANPIPE_AFT -DCONFIG_PRODUCT_WANPIPE_AFT_CORE -DCONFIG_PRODUCT_WANPIPE_AFT_TE1 -DCONFIG_PRODUCT_WANPIPE_AFT_56K -DCONFIG_PRODUCT_WANPIPE_AFT_RM -DCONFIG_PRODUCT_WANPIPE_CODEC_SLINEAR_LAW -DCONFIG_PRODUCT_WANPIPE_AFT_BRI -DCONFIG_PRODUCT_WANPIPE_AFT_SERIAL -DCONFIG_PRODUCT_WANPIPE_AFT_A600 -DCONFIG_PRODUCT_WANPIPE_AFT_B601 "
|
||||
PROTOCOL_DEFINES="$PROTOCOL_DEFINES -DCONFIG_PRODUCT_WANPIPE_AFT -DCONFIG_PRODUCT_WANPIPE_AFT_CORE -DCONFIG_PRODUCT_WANPIPE_AFT_TE1 -DCONFIG_PRODUCT_WANPIPE_AFT_56K -DCONFIG_PRODUCT_WANPIPE_AFT_RM -DCONFIG_PRODUCT_WANPIPE_CODEC_SLINEAR_LAW -DCONFIG_PRODUCT_WANPIPE_AFT_BRI -DCONFIG_PRODUCT_WANPIPE_AFT_SERIAL -DCONFIG_PRODUCT_WANPIPE_AFT_A600 -DCONFIG_PRODUCT_WANPIPE_AFT_B601 -DCONFIG_PRODUCT_WANPIPE_AFT_B800 "
|
||||
if [ $REL != "3.4" ]; then
|
||||
PROTOCOL_DEFINES="$PROTOCOL_DEFINES -DCONFIG_PRODUCT_WANPIPE_AFT_A700 "
|
||||
fi
|
||||
|
@ -6949,6 +7007,11 @@ ENDOFTEXT
|
|||
tdmv_apply_zaptel_chunk_patch
|
||||
fi
|
||||
|
||||
if [ $OSLEC == "YES" ]; then
|
||||
tdmv_apply_oslec_patch
|
||||
fi
|
||||
|
||||
|
||||
####################################################################
|
||||
if [ $ENABLE_ECHO_DEBUG -eq 1 ]; then
|
||||
getyn "Compile Echo Debugging Support for Zaptel (not supported for Dahdi yet) ? "
|
||||
|
@ -7240,17 +7303,20 @@ or
|
|||
|
||||
commands:
|
||||
---------
|
||||
install : Install/Upgrade WANPIPE
|
||||
upgrade : Upgrade WANPIPE kernel device drivers
|
||||
and utilities. (Same as install!)
|
||||
install : Install/Upgrade General Wanpipe
|
||||
zaptel : Install Wanpipe for Zaptel
|
||||
dahdi : Install Wanpipe for Dahdi
|
||||
xmtp2_api : Install Wanpipe for MTP2 API mode
|
||||
|
||||
remove : Uninstall WANPIPE
|
||||
remove_init : Uninstall WANPIPE Boot Startup Scripts
|
||||
install_init : Install WANPIPE Boot Startup Scripts
|
||||
|
||||
drivers : Re-install and Re-compile
|
||||
WANPIPE kernel device drivers ONLY
|
||||
Wanpipe kernel device drivers only
|
||||
buildrpm : Build the custom WANPIPE RPM binary for the
|
||||
current system.
|
||||
For further help read README.rpm
|
||||
For further help read README.rpm
|
||||
helprpm : RPM build help information.
|
||||
builddeb : Build the custom WANPIPE Debian binary
|
||||
: package for current system.
|
||||
|
@ -7388,7 +7454,7 @@ KERNEL_UNAME=`uname -r`
|
|||
PKG_NAME=wanpipe
|
||||
DISTR_NAME="WANPIPE"
|
||||
PROD=wanrouter
|
||||
PROD_VER=3.5.11
|
||||
PROD_VER=3.5.12
|
||||
PROD_HOME=`pwd`
|
||||
META_CONF=$PROD_HOME/$PROD.rc
|
||||
WAN_INTR_DIR=$PROD_HOME/interfaces
|
||||
|
@ -7419,6 +7485,7 @@ ZAPTEL_PATH_OP="NO"
|
|||
ZAPTEL_COMPILE_DISABLE="NO"
|
||||
BRI_MODULE_TEST="NO"
|
||||
ZAP_CHUNK_OP="NO"
|
||||
OSLEC="NO"
|
||||
CMP_LOG=$PROD_HOME/setup_drv_compile.log
|
||||
CMP_BUILD=build.sh
|
||||
CMP_INSTALL=install.sh
|
||||
|
@ -7582,6 +7649,7 @@ USR_CC=
|
|||
KBUILD_VERBOSE=0
|
||||
KBUILD_DISABLE=0
|
||||
NO_AUTO_START=0
|
||||
NO_SMG_INSTALL=0
|
||||
PROTS=
|
||||
|
||||
ROOT=;
|
||||
|
@ -7664,6 +7732,12 @@ if [ "$setup_cmd" = "zaptel" ] || [ "$setup_cmd" = "dahdi" ] ; then
|
|||
#EXTRA_ARGS=" --protocol=TDM "
|
||||
fi
|
||||
|
||||
if [ "$setup_cmd" = "xmtp2_api" ]; then
|
||||
setup_cmd="install"
|
||||
NO_SMG_INSTALL=1
|
||||
PROTS="AFT_TE1-XMTP2"
|
||||
fi
|
||||
|
||||
if [ "$setup_cmd" = "bri" ]; then
|
||||
setup_cmd="install"
|
||||
zaptel_auto_install="YES"
|
||||
|
@ -7962,6 +8036,18 @@ if [ "$PKG_NAME" != "wanpipe-lite" ]; then
|
|||
fi
|
||||
fi
|
||||
;;
|
||||
|
||||
--with-oslec)
|
||||
echo "WARNING:"
|
||||
echo "You are going to use OSLEC as software echo canceler"
|
||||
echo "Note: If you want to use OSLEC, do not forget to turn off the hardware echo canceler in wanpipe configuration"
|
||||
getyn "Do you want to use OSLEC for Dahdi/Zaptel"
|
||||
if [ $? -eq 0 ]; then
|
||||
OSLEC="YES"
|
||||
else
|
||||
OSLEC="NO"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option $arg"
|
||||
exit 1;
|
||||
|
|
|
@ -14,10 +14,11 @@ all:
|
|||
make -C fr all APIINC=$(APIINC)
|
||||
make -C bitstrm all APIINC=$(APIINC)
|
||||
make -C bisync all APIINC=$(APIINC)
|
||||
make -C aft all APIINC=$(APIINC)
|
||||
|
||||
clean:
|
||||
make -C x25 clean
|
||||
make -C chdlc clean
|
||||
make -C fr clean
|
||||
make -C bitstrm clean
|
||||
make -C bisync clean
|
||||
make -C aft clean
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
./aft/aft_api: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped
|
|
@ -1,7 +1,7 @@
|
|||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 34
|
||||
/svn/libsangoma/!svn/ver/273/trunk
|
||||
/svn/libsangoma/!svn/ver/293/trunk
|
||||
END
|
||||
init-automake.sh
|
||||
K 25
|
||||
|
@ -25,7 +25,7 @@ sources
|
|||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 42
|
||||
/svn/libsangoma/!svn/ver/269/trunk/sources
|
||||
/svn/libsangoma/!svn/ver/286/trunk/sources
|
||||
END
|
||||
AUTHORS
|
||||
K 25
|
||||
|
@ -67,7 +67,7 @@ libsangoma.c
|
|||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 47
|
||||
/svn/libsangoma/!svn/ver/272/trunk/libsangoma.c
|
||||
/svn/libsangoma/!svn/ver/293/trunk/libsangoma.c
|
||||
END
|
||||
compile.bat
|
||||
K 25
|
||||
|
@ -85,13 +85,13 @@ libsangoma.h
|
|||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 47
|
||||
/svn/libsangoma/!svn/ver/273/trunk/libsangoma.h
|
||||
/svn/libsangoma/!svn/ver/293/trunk/libsangoma.h
|
||||
END
|
||||
libsangoma_hwec.c
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 52
|
||||
/svn/libsangoma/!svn/ver/271/trunk/libsangoma_hwec.c
|
||||
/svn/libsangoma/!svn/ver/279/trunk/libsangoma_hwec.c
|
||||
END
|
||||
g711.h
|
||||
K 25
|
||||
|
@ -229,7 +229,7 @@ libsangoma-pvt.h
|
|||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 51
|
||||
/svn/libsangoma/!svn/ver/222/trunk/libsangoma-pvt.h
|
||||
/svn/libsangoma/!svn/ver/276/trunk/libsangoma-pvt.h
|
||||
END
|
||||
install-sh
|
||||
K 25
|
||||
|
@ -241,5 +241,5 @@ libsangoma.vcproj
|
|||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 52
|
||||
/svn/libsangoma/!svn/ver/269/trunk/libsangoma.vcproj
|
||||
/svn/libsangoma/!svn/ver/286/trunk/libsangoma.vcproj
|
||||
END
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
8
|
||||
|
||||
dir
|
||||
273
|
||||
293
|
||||
https://www.sangomapbx.com/svn/libsangoma/trunk
|
||||
https://www.sangomapbx.com/svn/libsangoma
|
||||
|
||||
|
||||
|
||||
2010-04-09T17:11:09.447360Z
|
||||
273
|
||||
2010-06-21T23:50:48.868158Z
|
||||
293
|
||||
ncorbic
|
||||
has-props
|
||||
|
||||
|
@ -73,10 +73,10 @@ file
|
|||
|
||||
|
||||
|
||||
2010-03-23T16:14:34.000000Z
|
||||
261dbd98b6a866003ce00fddeb1867cf
|
||||
2010-03-15T20:12:36.300714Z
|
||||
269
|
||||
2010-06-14T16:38:14.000000Z
|
||||
2e406647b2e26265446b40f8fbfb411b
|
||||
2010-06-10T21:10:51.668331Z
|
||||
286
|
||||
davidr
|
||||
|
||||
AUTHORS
|
||||
|
@ -176,11 +176,11 @@ file
|
|||
|
||||
|
||||
|
||||
2010-04-09T15:03:14.000000Z
|
||||
a0ef759d6887cf41a79e164cde54b98c
|
||||
2010-04-01T17:47:10.550488Z
|
||||
272
|
||||
davidr
|
||||
2010-06-21T23:23:59.000000Z
|
||||
d0bb1eca5add6b5bb865bd85ec350af8
|
||||
2010-06-21T23:50:48.868158Z
|
||||
293
|
||||
ncorbic
|
||||
has-props
|
||||
|
||||
cleanup.sh
|
||||
|
@ -202,10 +202,10 @@ file
|
|||
|
||||
|
||||
|
||||
2010-04-09T15:03:14.000000Z
|
||||
d3f29adcf654b49568d4759e8dcb4c22
|
||||
2010-04-09T17:11:09.447360Z
|
||||
273
|
||||
2010-06-21T23:23:59.000000Z
|
||||
49584fbd77f3529c93cfb5a46fe3467d
|
||||
2010-06-21T23:50:48.868158Z
|
||||
293
|
||||
ncorbic
|
||||
has-props
|
||||
|
||||
|
@ -215,10 +215,10 @@ file
|
|||
|
||||
|
||||
|
||||
2010-03-23T16:14:34.000000Z
|
||||
912e0fe804db3423d7b7ddc34fedd8e4
|
||||
2010-03-17T22:36:18.066541Z
|
||||
271
|
||||
2010-06-04T16:18:07.000000Z
|
||||
59eb5313edc41327b1bcef36b70bb9d4
|
||||
2010-05-28T23:22:41.955986Z
|
||||
279
|
||||
davidr
|
||||
|
||||
g711.h
|
||||
|
@ -501,11 +501,11 @@ file
|
|||
|
||||
|
||||
|
||||
2009-08-25T20:44:41.000000Z
|
||||
f804894d319dde10f91daf4542b9003b
|
||||
2009-08-12T18:36:20.606028Z
|
||||
222
|
||||
ncorbic
|
||||
2010-05-18T21:27:49.000000Z
|
||||
ef10b7962e2dbe7feebcec6c47467ad7
|
||||
2010-05-06T20:18:08.960008Z
|
||||
276
|
||||
davidr
|
||||
has-props
|
||||
|
||||
examples
|
||||
|
@ -530,9 +530,9 @@ file
|
|||
|
||||
|
||||
|
||||
2010-03-23T16:14:34.000000Z
|
||||
1758fcb8a7c95432556823b5cb0355f1
|
||||
2010-03-15T20:12:36.300714Z
|
||||
269
|
||||
2010-06-14T16:38:14.000000Z
|
||||
3550ed370d5194be80c9098929f7dbc1
|
||||
2010-06-10T21:10:51.668331Z
|
||||
286
|
||||
davidr
|
||||
|
||||
|
|
|
@ -75,13 +75,6 @@ extern "C" { /* for C++ users */
|
|||
#define SANGOMA_OBJ_HAS_DEVICE(object) ((object)->object_type == SANGOMA_DEVICE_WAIT_OBJ \
|
||||
|| (object)->object_type == SANGOMA_DEVICE_WAIT_OBJ_SIG)
|
||||
|
||||
#define LIBSNG_NUMBER_OF_EVENT_OBJECTS 3 /* POLLIN, POLLOUT and POLLPRI */
|
||||
enum {
|
||||
LIBSNG_EVENT_INDEX_POLLIN=0,
|
||||
LIBSNG_EVENT_INDEX_POLLOUT,
|
||||
LIBSNG_EVENT_INDEX_POLLPRI
|
||||
};
|
||||
|
||||
#define LIBSNG_MAGIC_NO 0x90547419
|
||||
|
||||
/* libsangoma.h defines sangoma_wait_obj_t for the sake of clean prototype definitions, time to undefine it since from now on
|
||||
|
@ -114,10 +107,8 @@ typedef struct sangoma_wait_obj
|
|||
sangoma_wait_obj_type_t object_type;
|
||||
|
||||
#if defined(__WINDOWS__)
|
||||
/*! WINDOWS: api structure used by windows IoctlSetSharedEvent call */
|
||||
/*! to wait on events or data from the Sangoma device driver. */
|
||||
HANDLE sng_event_objects[LIBSNG_NUMBER_OF_EVENT_OBJECTS];
|
||||
HANDLE generic_event_object;
|
||||
/*! signallable object to wait on events or data from the Sangoma device driver or can be signalled by sangoma_wait_obj_signal(). */
|
||||
HANDLE signal_object;
|
||||
#else
|
||||
/*! LINUX: To be used by a pipe to asynchronously break a poll() */
|
||||
sng_fd_t signal_write_fd;
|
||||
|
|
|
@ -307,12 +307,11 @@ sangoma_status_t _LIBSNG_CALL sangoma_cdev_ctrl_cmd(sng_fd_t fd, wanpipe_tdm_api
|
|||
return handle_device_ioctl_result(bIoResult, __FUNCTION__);
|
||||
}
|
||||
|
||||
static sangoma_status_t init_sangoma_event_object(sangoma_wait_obj_t *sng_wait_obj, int flags_in, sng_fd_t fd)
|
||||
static sangoma_status_t init_sangoma_event_object(sangoma_wait_obj_t *sng_wait_obj, sng_fd_t fd)
|
||||
{
|
||||
int event_index = -1;
|
||||
wanpipe_tdm_api_cmd_t tdm_api_cmd;
|
||||
sangoma_status_t sng_status;
|
||||
char event_name[200], tmp_event_name[200];
|
||||
char event_name[200];
|
||||
|
||||
memset(&tdm_api_cmd, 0x00, sizeof(tdm_api_cmd));
|
||||
|
||||
|
@ -325,40 +324,18 @@ static sangoma_status_t init_sangoma_event_object(sangoma_wait_obj_t *sng_wait_o
|
|||
|
||||
DBG_EVNT("%s(): interface name: %s\n", __FUNCTION__, tdm_api_cmd.data);
|
||||
|
||||
if(flags_in & POLLIN){
|
||||
event_index = LIBSNG_EVENT_INDEX_POLLIN;
|
||||
/* Form the Event Name from Interface Name and Event Type (i.e. wanpipe1_if1_pollin). */
|
||||
_snprintf(tmp_event_name, sizeof(tmp_event_name), "%s_pollin", tdm_api_cmd.data);
|
||||
}
|
||||
|
||||
if(flags_in & POLLOUT){
|
||||
event_index = LIBSNG_EVENT_INDEX_POLLOUT;
|
||||
/* Form the Event Name from Interface Name and Event Type (i.e. wanpipe1_if1_pollout). */
|
||||
_snprintf(tmp_event_name, sizeof(tmp_event_name), "%s_pollout", tdm_api_cmd.data);
|
||||
}
|
||||
|
||||
if(flags_in & POLLPRI){
|
||||
event_index = LIBSNG_EVENT_INDEX_POLLPRI;
|
||||
/* Form the Event Name from Interface Name and Event Type (i.e. wanpipe1_if1_pollpri). */
|
||||
_snprintf(tmp_event_name, sizeof(tmp_event_name), "%s_pollpri", tdm_api_cmd.data);
|
||||
}
|
||||
|
||||
if(event_index == -1){
|
||||
/* invalid 'flags_in', this should be an assert */
|
||||
return SANG_STATUS_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
/* 1. The Sangoma Device Driver creates Notification Events in "\\BaseNamedObjects\\Global\\"
|
||||
* when first CreateFile() was called by a process. That means the Events will inherit
|
||||
* the security attributes of the calling process, so the calling process will have
|
||||
* the permissions to open the Events by calling OpenEvent(). Since Events are created
|
||||
* "Global" subdirectory, the calling process does NOT need Administrator priveleges.
|
||||
* The example name of the signaling object is: \\BaseNamedObjects\\Global\\wanpipe1_if1_signal.
|
||||
* 2. The Events are deleted when the last HANDLE for a device is closed by CloseHandle()
|
||||
* or automatically by the system when calling process exits. */
|
||||
_snprintf(event_name, sizeof(event_name), "Global\\%s", tmp_event_name);
|
||||
_snprintf(event_name, sizeof(event_name), "Global\\%s_signal", tdm_api_cmd.data);
|
||||
|
||||
sng_wait_obj->sng_event_objects[event_index] = OpenEvent(EVENT_ALL_ACCESS, TRUE, event_name);
|
||||
if(NULL == sng_wait_obj->sng_event_objects[event_index]){
|
||||
sng_wait_obj->signal_object = OpenEvent(EVENT_ALL_ACCESS, TRUE, event_name);
|
||||
if(NULL == sng_wait_obj->signal_object){
|
||||
/* error */
|
||||
LibSangomaDecodeLastError(__FUNCTION__);
|
||||
return SANG_STATUS_GENERAL_ERROR;
|
||||
|
@ -376,7 +353,7 @@ static sangoma_status_t sangoma_wait_obj_poll(sangoma_wait_obj_t *sangoma_wait_o
|
|||
|
||||
*flags_out = 0;
|
||||
|
||||
memset(&api_poll, 0x00, sizeof(API_POLL_STRUCT));
|
||||
memset(&api_poll, 0x00, sizeof(api_poll));
|
||||
api_poll.user_flags_bitmap = flags_in;
|
||||
|
||||
/* This call is non-blocking - it will return immediatly. */
|
||||
|
@ -399,13 +376,20 @@ static sangoma_status_t sangoma_wait_obj_poll(sangoma_wait_obj_t *sangoma_wait_o
|
|||
return err;
|
||||
}
|
||||
|
||||
static int check_number_of_wait_objects(uint32_t number_of_objects, const char *caller_function, int lineno)
|
||||
static int sangoma_check_number_of_wait_objects(uint32_t number_of_objects)
|
||||
{
|
||||
if(number_of_objects >= MAXIMUM_WAIT_OBJECTS){
|
||||
DBG_ERR("Caller: %s(): Line: %d: 'number_of_objects': %d is greater than the Maximum of: %d\n",
|
||||
caller_function, lineno, number_of_objects, MAXIMUM_WAIT_OBJECTS);
|
||||
if(number_of_objects > MAXIMUM_WAIT_OBJECTS){
|
||||
DBG_ERR("'number_of_objects': %d is greater than the Maximum of: %d\n",
|
||||
number_of_objects, MAXIMUM_WAIT_OBJECTS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(number_of_objects < 1){
|
||||
DBG_ERR("'number_of_objects': %d is less than the Minimum of: 1\n",
|
||||
number_of_objects);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -425,42 +409,36 @@ static sangoma_status_t get_out_flags(IN sangoma_wait_obj_t *sng_wait_objects[],
|
|||
|
||||
sangoma_wait_obj_t *sangoma_wait_object = sng_wait_objects[i];
|
||||
|
||||
if (!sangoma_wait_object->signal_object) {
|
||||
return SANG_STATUS_DEV_INIT_INCOMPLETE;
|
||||
}
|
||||
|
||||
if (!SANGOMA_OBJ_HAS_DEVICE(sangoma_wait_object)) {
|
||||
|
||||
/* This object does not has a device, but, may have been signaled via sangoma_wait_obj_signal()
|
||||
* test if the object is signaled, if it is, set SANG_WAIT_OBJ_IS_SIGNALED */
|
||||
|
||||
if((i == first_signaled_obj_index) || (WaitForSingleObject(sangoma_wait_object->generic_event_object, 0) == WAIT_OBJECT_0)) {
|
||||
/* !+! jpboily : Since WaitForMultipleObjects cleared the status
|
||||
* of the first signaled object, we make sure that the out_flag
|
||||
* for this object is set */
|
||||
if((i == first_signaled_obj_index) || /* !+! jpboily : Since WaitForMultipleObjects cleared the status
|
||||
* of the FIRST signaled object, we make sure that the out_flag
|
||||
* for this object is set.
|
||||
* !+! davidr: Status of all OTHER objects will be checked
|
||||
* by WaitForSingleObject(). */
|
||||
(WaitForSingleObject(sangoma_wait_object->signal_object, 0) == WAIT_OBJECT_0)) {
|
||||
out_flags[i] |= SANG_WAIT_OBJ_IS_SIGNALED;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
for(j = 0; j < LIBSNG_NUMBER_OF_EVENT_OBJECTS; j++){
|
||||
if(sangoma_wait_obj_poll(sangoma_wait_object, in_flags[i], &out_flags[i])){
|
||||
return SANG_STATUS_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
if(!sangoma_wait_object->sng_event_objects[j]) {
|
||||
continue;
|
||||
if (out_flags[i] & in_flags[i]) {
|
||||
if (at_least_one_poll_set_flags_out) {
|
||||
*at_least_one_poll_set_flags_out = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if(sangoma_wait_obj_poll(sangoma_wait_object, in_flags[i], &out_flags[i])){
|
||||
return SANG_STATUS_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
if( out_flags[i] & in_flags[i] ){
|
||||
if(at_least_one_poll_set_flags_out){
|
||||
*at_least_one_poll_set_flags_out = TRUE;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
/* Check if a device-related object was signalled, if it is, set SANG_WAIT_OBJ_IS_SIGNALED. */
|
||||
if (WaitForSingleObject(sangoma_wait_object->sng_event_objects[j], 0) == WAIT_OBJECT_0) {
|
||||
out_flags[i] |= SANG_WAIT_OBJ_IS_SIGNALED;
|
||||
}
|
||||
#endif
|
||||
}/* for(j = 0; j < LIBSNG_NUMBER_OF_EVENT_OBJECTS; j++) */
|
||||
}/* for(i = 0; i < number_of_sangoma_wait_objects; i++) */
|
||||
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
@ -1255,7 +1233,7 @@ sangoma_status_t _LIBSNG_CALL sangoma_wait_obj_create(sangoma_wait_obj_t **sango
|
|||
sangoma_wait_obj_t *sng_wait_obj = NULL;
|
||||
|
||||
if (!sangoma_wait_object) {
|
||||
return SANG_STATUS_INVALID_DEVICE;
|
||||
return SANG_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
*sangoma_wait_object = NULL;
|
||||
sng_wait_obj = malloc(sizeof(**sangoma_wait_object));
|
||||
|
@ -1271,40 +1249,19 @@ sangoma_status_t _LIBSNG_CALL sangoma_wait_obj_create(sangoma_wait_obj_t **sango
|
|||
sng_wait_obj->object_type = object_type;
|
||||
|
||||
#if defined(__WINDOWS__)
|
||||
DBG_INIT("%s(): sng_wait_obj ptr: 0x%p\n", __FUNCTION__, sng_wait_obj);
|
||||
DBG_INIT("%s(): fd: 0x%X, object_type: %s\n", __FUNCTION__, fd, DECODE_SANGOMA_WAIT_OBJECT_TYPE(object_type));
|
||||
DBG_INIT("%s(): sizeof(**sangoma_wait_object): %d\n", __FUNCTION__, sizeof(**sangoma_wait_object));
|
||||
|
||||
if (SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) {
|
||||
sng_wait_obj->generic_event_object = CreateEvent( NULL, FALSE, FALSE, NULL);
|
||||
if(!sng_wait_obj->generic_event_object){
|
||||
if (!SANGOMA_OBJ_HAS_DEVICE(sng_wait_obj)) {
|
||||
sng_wait_obj->signal_object = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if(!sng_wait_obj->signal_object){
|
||||
err = SANG_STATUS_GENERAL_ERROR;
|
||||
goto failed;
|
||||
}
|
||||
err = SANG_STATUS_SUCCESS;
|
||||
} else {
|
||||
err = init_sangoma_event_object(sng_wait_obj, fd);
|
||||
if(SANG_STATUS_SUCCESS != err){
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
if(SANGOMA_GENERIC_WAIT_OBJ == object_type){
|
||||
/* everything is done for the generic wait object */
|
||||
*sangoma_wait_object = sng_wait_obj;
|
||||
return SANG_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
err = init_sangoma_event_object(sng_wait_obj, POLLIN, fd);
|
||||
if(SANG_STATUS_SUCCESS != err){
|
||||
goto failed;
|
||||
}
|
||||
|
||||
err = init_sangoma_event_object(sng_wait_obj, POLLOUT, fd);
|
||||
if(SANG_STATUS_SUCCESS != err){
|
||||
goto failed;
|
||||
}
|
||||
|
||||
err = init_sangoma_event_object(sng_wait_obj, POLLPRI, fd);
|
||||
if(SANG_STATUS_SUCCESS != err) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
DBG_INIT("%s(): returning: %d", __FUNCTION__, err);
|
||||
#else
|
||||
int filedes[2];
|
||||
if (SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) {
|
||||
|
@ -1338,9 +1295,6 @@ failed:
|
|||
sangoma_status_t _LIBSNG_CALL sangoma_wait_obj_delete(sangoma_wait_obj_t **sangoma_wait_object)
|
||||
{
|
||||
sangoma_wait_obj_t *sng_wait_obj = *sangoma_wait_object;
|
||||
#if defined(__WINDOWS__)
|
||||
int index = 0;
|
||||
#endif
|
||||
|
||||
if(sng_wait_obj->init_flag != LIBSNG_MAGIC_NO){
|
||||
/* error. object was not initialized by sangoma_wait_obj_init() */
|
||||
|
@ -1348,13 +1302,9 @@ sangoma_status_t _LIBSNG_CALL sangoma_wait_obj_delete(sangoma_wait_obj_t **sango
|
|||
}
|
||||
|
||||
#if defined(__WINDOWS__)
|
||||
if (SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) {
|
||||
sangoma_close(&sng_wait_obj->generic_event_object);
|
||||
}
|
||||
if (SANGOMA_OBJ_HAS_DEVICE(sng_wait_obj)) {
|
||||
for(index = 0; index < LIBSNG_NUMBER_OF_EVENT_OBJECTS; index++){
|
||||
sangoma_close(&sng_wait_obj->sng_event_objects[index]);
|
||||
}
|
||||
if (sng_wait_obj->signal_object &&
|
||||
sng_wait_obj->signal_object != INVALID_HANDLE_VALUE) {
|
||||
sangoma_close(&sng_wait_obj->signal_object);
|
||||
}
|
||||
#else
|
||||
if (SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) {
|
||||
|
@ -1380,13 +1330,12 @@ int _LIBSNG_CALL sangoma_wait_obj_signal(sangoma_wait_obj_t *sng_wait_obj)
|
|||
if (!SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) {
|
||||
/* even when Windows objects are always signalable for the sake of providing
|
||||
* a consistent interface to the user we downgrade the capabilities of Windows
|
||||
* objects unless the sangoma wait object is explicitly initialized as signalable
|
||||
* */
|
||||
* objects unless the sangoma wait object is explicitly initialized as signalable */
|
||||
return SANG_STATUS_INVALID_DEVICE;
|
||||
}
|
||||
#if defined(__WINDOWS__)
|
||||
if(sng_wait_obj->generic_event_object){
|
||||
if (!SetEvent(sng_wait_obj->generic_event_object)) {
|
||||
if(sng_wait_obj->signal_object){
|
||||
if (!SetEvent(sng_wait_obj->signal_object)) {
|
||||
return SANG_STATUS_GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
@ -1449,58 +1398,44 @@ sangoma_status_t _LIBSNG_CALL sangoma_waitfor_many(sangoma_wait_obj_t *sng_wait_
|
|||
{
|
||||
#if defined(__WINDOWS__)
|
||||
HANDLE hEvents[MAXIMUM_WAIT_OBJECTS];
|
||||
uint32_t uiMapEventIndexToWaitObjectIndex[MAXIMUM_WAIT_OBJECTS];
|
||||
DWORD dwResult;
|
||||
int at_least_one_poll_set_flags_out, number_of_internal_signaling_objects, err;
|
||||
int at_least_one_poll_set_flags_out, err;
|
||||
sangoma_wait_obj_t *sangoma_wait_object;
|
||||
#endif
|
||||
uint32_t i = 0, j = 0;
|
||||
|
||||
memset(out_flags, 0x00, number_of_sangoma_wait_objects * sizeof(out_flags[0]));
|
||||
#if defined(__WINDOWS__)
|
||||
/* This loop will calculate 'number_of_internal_signaling_objects' and will initialize 'hEvents'
|
||||
* based on 'number_of_sangoma_wait_objects' and 'in_flags'. */
|
||||
number_of_internal_signaling_objects = 0;
|
||||
for(i = 0; i < number_of_sangoma_wait_objects; i++){
|
||||
sangoma_wait_obj_t *sangoma_wait_object = sng_wait_objects[i];
|
||||
|
||||
/* if SANGOMA_OBJ_IS_SIGNALABLE add the generic_event_object.hEvent to the hEvents */
|
||||
if(sangoma_wait_object->generic_event_object){
|
||||
if(check_number_of_wait_objects(number_of_internal_signaling_objects, __FUNCTION__, __LINE__)){
|
||||
return SANG_STATUS_NO_FREE_BUFFERS;
|
||||
}
|
||||
hEvents[number_of_internal_signaling_objects] = sangoma_wait_object->generic_event_object;
|
||||
uiMapEventIndexToWaitObjectIndex[number_of_internal_signaling_objects] = i;
|
||||
number_of_internal_signaling_objects++;
|
||||
}
|
||||
|
||||
for(j = 0; j < LIBSNG_NUMBER_OF_EVENT_OBJECTS; j++){
|
||||
if(sangoma_wait_object->sng_event_objects[j]){
|
||||
if( ((j == LIBSNG_EVENT_INDEX_POLLIN) && (in_flags[i] & POLLIN)) ||
|
||||
((j == LIBSNG_EVENT_INDEX_POLLOUT) && (in_flags[i] & POLLOUT)) ||
|
||||
((j == LIBSNG_EVENT_INDEX_POLLPRI) && (in_flags[i] & POLLPRI)) ){
|
||||
|
||||
if(check_number_of_wait_objects(number_of_internal_signaling_objects, __FUNCTION__, __LINE__)){
|
||||
return SANG_STATUS_NO_FREE_BUFFERS;
|
||||
}
|
||||
hEvents[number_of_internal_signaling_objects] = sangoma_wait_object->sng_event_objects[j];
|
||||
uiMapEventIndexToWaitObjectIndex[number_of_internal_signaling_objects] = i;
|
||||
number_of_internal_signaling_objects++;
|
||||
}
|
||||
}/* if () */
|
||||
}/* for() */
|
||||
}/* for() */
|
||||
|
||||
if(number_of_internal_signaling_objects < 1){
|
||||
DBG_ERR("'number_of_internal_signaling_objects': %d is less than the Minimum of: 1!\n",
|
||||
number_of_internal_signaling_objects);
|
||||
if(sangoma_check_number_of_wait_objects(number_of_sangoma_wait_objects)){
|
||||
/* error - most likely the user did not initialize sng_wait_objects[] */
|
||||
return SANG_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
for(i = 0; i < MAXIMUM_WAIT_OBJECTS; i++){
|
||||
hEvents[i] = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
/* This loop will initialize 'hEvents[]' based on
|
||||
* 'number_of_sangoma_wait_objects' and sng_wait_objects[]. */
|
||||
for(i = 0; i < number_of_sangoma_wait_objects; i++){
|
||||
|
||||
sangoma_wait_object = sng_wait_objects[i];
|
||||
|
||||
if(LIBSNG_MAGIC_NO != sangoma_wait_object->init_flag){
|
||||
return SANG_STATUS_DEV_INIT_INCOMPLETE;
|
||||
}
|
||||
|
||||
if(sangoma_wait_object->signal_object){
|
||||
hEvents[i] = sangoma_wait_object->signal_object;
|
||||
}
|
||||
|
||||
}/* for() */
|
||||
|
||||
at_least_one_poll_set_flags_out = FALSE;
|
||||
|
||||
/* It is important to get 'out flags' BEFORE the WaitForMultipleObjects()
|
||||
* because it allows to keep API driver's transmit queue full. */
|
||||
* because it allows to keep API driver's TRANSMIT queue full. */
|
||||
err = get_out_flags(sng_wait_objects, INVALID_INDEX, in_flags, out_flags, number_of_sangoma_wait_objects, &at_least_one_poll_set_flags_out);
|
||||
if(SANG_ERROR(err)){
|
||||
return err;
|
||||
|
@ -1511,19 +1446,19 @@ sangoma_status_t _LIBSNG_CALL sangoma_waitfor_many(sangoma_wait_obj_t *sng_wait_
|
|||
}
|
||||
|
||||
/* wait untill at least one of the events is signaled OR a 'system_wait_timeout' occured */
|
||||
dwResult = WaitForMultipleObjects(number_of_internal_signaling_objects, &hEvents[0], FALSE, system_wait_timeout);
|
||||
dwResult = WaitForMultipleObjects(number_of_sangoma_wait_objects, &hEvents[0], FALSE, system_wait_timeout);
|
||||
if (WAIT_TIMEOUT == dwResult){
|
||||
return SANG_STATUS_APIPOLL_TIMEOUT;
|
||||
}
|
||||
|
||||
if( dwResult >= (DWORD)number_of_internal_signaling_objects ) {
|
||||
if( dwResult >= (DWORD)number_of_sangoma_wait_objects ) {
|
||||
return SANG_STATUS_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
/* WaitForMultipleObjects() was waken by a Sangoma or by a non-Sangoma wait object. */
|
||||
err = get_out_flags(sng_wait_objects,
|
||||
uiMapEventIndexToWaitObjectIndex[dwResult],/* This is the index of first signaled object in
|
||||
* the original sng_wait_objects[] array, not in hEvents[] array. */
|
||||
dwResult, /* Array index of the signalled object with the smallest index
|
||||
* value of all the signalled objects, from array. */
|
||||
in_flags, out_flags, number_of_sangoma_wait_objects, NULL);
|
||||
if(SANG_ERROR(err)){
|
||||
return err;
|
||||
|
@ -1681,14 +1616,25 @@ int _LIBSNG_CALL sangoma_span_chan_fromif(char *interface_name, int *span, int *
|
|||
int ret = 0;
|
||||
char data[FNAME_LEN];
|
||||
|
||||
/* Windows: Accept WANPIPEx_IFy or wanpipex_ify
|
||||
* where x is the span and y is the chan. */
|
||||
|
||||
strncpy(data, interface_name, FNAME_LEN);
|
||||
if ((data[0])) {
|
||||
for (p = data; *p; p++) {
|
||||
#if defined(__WINDOWS__)
|
||||
if (sp && (*p == 'F'||*p == 'f')) {
|
||||
#else
|
||||
if (sp && *p == 'c') {
|
||||
#endif
|
||||
*p = '\0';
|
||||
ch = (p + 1);
|
||||
break;
|
||||
#if defined(__WINDOWS__)
|
||||
} else if (*p == 'E'||*p == 'e') {
|
||||
#else
|
||||
} else if (*p == 's') {
|
||||
#endif
|
||||
sp = (p + 1);
|
||||
}
|
||||
}
|
||||
|
@ -1791,6 +1737,7 @@ int _LIBSNG_CALL sangoma_get_open_cnt(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_OPEN_CNT;
|
||||
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -1897,8 +1844,11 @@ int _LIBSNG_CALL sangoma_readmsg(sng_fd_t fd, void *hdrbuf, int hdrlen, void *da
|
|||
rx_hdr->operation_status = SANG_STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
break;
|
||||
case SANG_STATUS_NO_DATA_AVAILABLE:
|
||||
/* Note that SANG_STATUS_NO_DATA_AVAILABLE is NOT an error becase
|
||||
* read() is non-blocking and can be called at any time (by some polling code)*/
|
||||
return 1; /* return positive value to indicate success, user must check 'rx_hdr->operation_status' */
|
||||
default:
|
||||
/* note that SANG_STATUS_NO_DATA_AVAILABLE is NOT an error! */
|
||||
if(libsng_dbg_level)DBG_ERR("Operation Status: %s(%d)\n",
|
||||
SDLA_DECODE_SANG_STATUS(rx_hdr->operation_status), rx_hdr->operation_status);
|
||||
return -5;
|
||||
|
@ -2039,6 +1989,7 @@ int _LIBSNG_CALL sangoma_get_full_cfg(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_FULL_CFG;
|
||||
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2092,6 +2043,7 @@ int _LIBSNG_CALL sangoma_get_full_cfg(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_tdm_set_codec(sng_fd_t fd, wanpipe_api_t *tdm_api, int codec)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_CODEC;
|
||||
tdm_api->wp_cmd.tdm_codec = codec;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2114,6 +2066,7 @@ int _LIBSNG_CALL sangoma_tdm_get_codec(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_CODEC;
|
||||
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2134,6 +2087,7 @@ int _LIBSNG_CALL sangoma_tdm_get_codec(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_tdm_set_usr_period(sng_fd_t fd, wanpipe_api_t *tdm_api, int period)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_USR_PERIOD;
|
||||
tdm_api->wp_cmd.usr_period = period;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2151,6 +2105,7 @@ int _LIBSNG_CALL sangoma_tdm_get_usr_period(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_USR_PERIOD;
|
||||
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2172,6 +2127,7 @@ int _LIBSNG_CALL sangoma_get_hw_coding(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_CODING;
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
if (err){
|
||||
|
@ -2192,6 +2148,7 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_dtmf(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_DTMF;
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
if (err){
|
||||
|
@ -2201,9 +2158,9 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_dtmf(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
}
|
||||
|
||||
/*========================================================
|
||||
* GET Current User Hardware EC Enabled/Disabled
|
||||
* GET status of echo canceler chip.
|
||||
*
|
||||
* Will return true if HW EC is enabled
|
||||
* Will return true if HW EC is available
|
||||
*/
|
||||
|
||||
int _LIBSNG_CALL sangoma_tdm_get_hw_ec(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
|
@ -2211,6 +2168,7 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_ec(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_EC;
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
if (err){
|
||||
|
@ -2220,6 +2178,31 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_ec(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef WP_API_FEATURE_EC_CHAN_STAT
|
||||
/*========================================================
|
||||
* GET status of the echo canceler for current channel.
|
||||
*
|
||||
* Will return true if HW EC is enabled
|
||||
*/
|
||||
|
||||
int _LIBSNG_CALL sangoma_tdm_get_hwec_chan_status(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_EC_CHAN;
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
if (err){
|
||||
return err;
|
||||
}
|
||||
return tdm_api->wp_cmd.hw_ec;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*========================================================
|
||||
* GET Current User MTU/MRU values in bytes.
|
||||
*
|
||||
|
@ -2231,6 +2214,7 @@ int _LIBSNG_CALL sangoma_tdm_get_usr_mtu_mru(sng_fd_t fd, wanpipe_api_t *tdm_api
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_USR_MTU_MRU;
|
||||
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2250,6 +2234,7 @@ int _LIBSNG_CALL sangoma_tdm_get_usr_mtu_mru(sng_fd_t fd, wanpipe_api_t *tdm_api
|
|||
int _LIBSNG_CALL sangoma_tdm_set_power_level(sng_fd_t fd, wanpipe_api_t *tdm_api, int power)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_POWER_LEVEL;
|
||||
tdm_api->wp_cmd.power_level = power;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2266,6 +2251,7 @@ int _LIBSNG_CALL sangoma_tdm_get_power_level(sng_fd_t fd, wanpipe_api_t *tdm_api
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_POWER_LEVEL;
|
||||
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2279,6 +2265,7 @@ int _LIBSNG_CALL sangoma_tdm_get_power_level(sng_fd_t fd, wanpipe_api_t *tdm_api
|
|||
int _LIBSNG_CALL sangoma_flush_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_FLUSH_BUFFERS;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
}
|
||||
|
@ -2286,6 +2273,7 @@ int _LIBSNG_CALL sangoma_flush_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_flush_rx_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_FLUSH_RX_BUFFERS;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
}
|
||||
|
@ -2293,6 +2281,7 @@ int _LIBSNG_CALL sangoma_flush_rx_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_flush_tx_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_FLUSH_TX_BUFFERS;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
}
|
||||
|
@ -2300,6 +2289,7 @@ int _LIBSNG_CALL sangoma_flush_tx_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_flush_event_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_FLUSH_EVENT_BUFFERS;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
}
|
||||
|
@ -2307,6 +2297,7 @@ int _LIBSNG_CALL sangoma_flush_event_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_tdm_enable_rbs_events(sng_fd_t fd, wanpipe_api_t *tdm_api, int poll_in_sec)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_ENABLE_RBS_EVENTS;
|
||||
tdm_api->wp_cmd.rbs_poll = poll_in_sec;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2315,6 +2306,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_rbs_events(sng_fd_t fd, wanpipe_api_t *tdm_a
|
|||
int _LIBSNG_CALL sangoma_tdm_disable_rbs_events(sng_fd_t fd, wanpipe_api_t *tdm_api) {
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_DISABLE_RBS_EVENTS;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
}
|
||||
|
@ -2322,6 +2314,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_rbs_events(sng_fd_t fd, wanpipe_api_t *tdm_
|
|||
int _LIBSNG_CALL sangoma_tdm_write_rbs(sng_fd_t fd, wanpipe_api_t *tdm_api, int channel, unsigned char rbs)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, channel);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_WRITE_RBS_BITS;
|
||||
tdm_api->wp_cmd.rbs_tx_bits=rbs;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2331,6 +2324,7 @@ int _LIBSNG_CALL sangoma_tdm_read_rbs(sng_fd_t fd, wanpipe_api_t *tdm_api, int c
|
|||
{
|
||||
int err;
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, channel);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_READ_RBS_BITS;
|
||||
tdm_api->wp_cmd.rbs_tx_bits=0;
|
||||
|
||||
|
@ -2341,7 +2335,29 @@ int _LIBSNG_CALL sangoma_tdm_read_rbs(sng_fd_t fd, wanpipe_api_t *tdm_api, int c
|
|||
|
||||
*rbs=(unsigned char)tdm_api->wp_cmd.rbs_rx_bits;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WP_API_FEATURE_BUFFER_MULT
|
||||
|
||||
int _LIBSNG_CALL sangoma_tdm_set_buffer_multiplier(sng_fd_t fd, wanpipe_api_t *tdm_api, unsigned int multiplier)
|
||||
{
|
||||
|
||||
int err;
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_BUFFER_MULTIPLIER;
|
||||
*((unsigned int*)&tdm_api->wp_cmd.data[0]) = multiplier;
|
||||
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
if (err){
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
int _LIBSNG_CALL sangoma_read_event(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
|
@ -2351,6 +2367,7 @@ int _LIBSNG_CALL sangoma_read_event(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_READ_EVENT;
|
||||
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2360,6 +2377,7 @@ int _LIBSNG_CALL sangoma_read_event(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
|
||||
rx_event = &tdm_api->wp_cmd.event;
|
||||
|
||||
#ifdef WP_API_DEPRECATED_FEATURE_READ_CALLBACK_FUNCTIONS
|
||||
/*
|
||||
The use of callbacks here is purely optional and is left
|
||||
here for backward compatibility purposes. By default user
|
||||
|
@ -2439,6 +2457,9 @@ int _LIBSNG_CALL sangoma_read_event(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
return 0;
|
||||
#else
|
||||
|
@ -2516,6 +2537,7 @@ sangoma_status_t _LIBSNG_CALL sangoma_logger_set_logger_level(sng_fd_t fd, wp_lo
|
|||
int _LIBSNG_CALL sangoma_tdm_enable_fax_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_FAX_DETECT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2525,6 +2547,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_fax_events(sng_fd_t fd, wanpipe_api_t *tdm_a
|
|||
int _LIBSNG_CALL sangoma_tdm_disable_fax_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_FAX_DETECT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
|
||||
|
@ -2535,6 +2558,7 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_fax(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
{
|
||||
int err;
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_FAX_DETECT;
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
if (err){
|
||||
|
@ -2548,6 +2572,7 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_fax(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_tdm_enable_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_DTMF;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2557,6 +2582,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_
|
|||
int _LIBSNG_CALL sangoma_tdm_disable_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_DTMF;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
|
||||
|
@ -2566,6 +2592,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm
|
|||
int _LIBSNG_CALL sangoma_tdm_enable_rm_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RM_DTMF;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2575,6 +2602,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_rm_dtmf_events(sng_fd_t fd, wanpipe_api_t *t
|
|||
int _LIBSNG_CALL sangoma_tdm_disable_rm_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RM_DTMF;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
|
||||
|
@ -2584,6 +2612,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_rm_dtmf_events(sng_fd_t fd, wanpipe_api_t *
|
|||
int _LIBSNG_CALL sangoma_tdm_enable_rxhook_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RXHOOK;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2593,6 +2622,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_rxhook_events(sng_fd_t fd, wanpipe_api_t *td
|
|||
int _LIBSNG_CALL sangoma_tdm_disable_rxhook_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RXHOOK;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
|
||||
|
@ -2602,6 +2632,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_rxhook_events(sng_fd_t fd, wanpipe_api_t *t
|
|||
int _LIBSNG_CALL sangoma_tdm_enable_ring_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2611,6 +2642,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_ring_events(sng_fd_t fd, wanpipe_api_t *tdm_
|
|||
int _LIBSNG_CALL sangoma_tdm_disable_ring_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
|
||||
|
@ -2620,6 +2652,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_ring_events(sng_fd_t fd, wanpipe_api_t *tdm
|
|||
int _LIBSNG_CALL sangoma_tdm_enable_ring_detect_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING_DETECT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2629,6 +2662,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_ring_detect_events(sng_fd_t fd, wanpipe_api_
|
|||
int _LIBSNG_CALL sangoma_tdm_disable_ring_detect_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING_DETECT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
|
||||
|
@ -2638,6 +2672,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_ring_detect_events(sng_fd_t fd, wanpipe_api
|
|||
int _LIBSNG_CALL sangoma_tdm_enable_ring_trip_detect_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING_TRIP_DETECT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2647,6 +2682,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_ring_trip_detect_events(sng_fd_t fd, wanpipe
|
|||
int _LIBSNG_CALL sangoma_tdm_disable_ring_trip_detect_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING_TRIP_DETECT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
|
||||
|
@ -2656,6 +2692,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_ring_trip_detect_events(sng_fd_t fd, wanpip
|
|||
int _LIBSNG_CALL sangoma_tdm_txsig_kewl(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TXSIG_KEWL;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2665,6 +2702,7 @@ int _LIBSNG_CALL sangoma_tdm_txsig_kewl(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_tdm_txsig_start(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TXSIG_START;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2674,6 +2712,7 @@ int _LIBSNG_CALL sangoma_tdm_txsig_start(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_tdm_txsig_onhook(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TXSIG_ONHOOK;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2683,6 +2722,7 @@ int _LIBSNG_CALL sangoma_tdm_txsig_onhook(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_tdm_txsig_offhook(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TXSIG_OFFHOOK;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2692,6 +2732,7 @@ int _LIBSNG_CALL sangoma_tdm_txsig_offhook(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_tdm_enable_tone_events(sng_fd_t fd, wanpipe_api_t *tdm_api, uint16_t tone_id)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TONE;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2702,6 +2743,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_tone_events(sng_fd_t fd, wanpipe_api_t *tdm_
|
|||
int _LIBSNG_CALL sangoma_tdm_disable_tone_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TONE;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
|
||||
|
@ -2713,6 +2755,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_tone_events(sng_fd_t fd, wanpipe_api_t *tdm
|
|||
int _LIBSNG_CALL sangoma_tdm_enable_hwec(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_ENABLE_HWEC;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
}
|
||||
|
@ -2720,6 +2763,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_hwec(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_tdm_disable_hwec(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_DISABLE_HWEC;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
}
|
||||
|
@ -2735,6 +2779,7 @@ int _LIBSNG_CALL sangoma_tdm_get_fe_alarms(sng_fd_t fd, wanpipe_api_t *tdm_api,
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_FE_ALARMS;
|
||||
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2753,6 +2798,7 @@ int _LIBSNG_CALL sangoma_get_fe_status(sng_fd_t fd, wanpipe_api_t *tdm_api, unsi
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_FE_STATUS;
|
||||
err = sangoma_cmd_exec(fd, tdm_api);
|
||||
*current_status = tdm_api->wp_cmd.fe_status;
|
||||
|
@ -2768,6 +2814,7 @@ int _LIBSNG_CALL sangoma_get_link_status(sng_fd_t fd, wanpipe_api_t *tdm_api, un
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_FE_STATUS;
|
||||
err = sangoma_cmd_exec(fd, tdm_api);
|
||||
*current_status = tdm_api->wp_cmd.fe_status;
|
||||
|
@ -2779,6 +2826,7 @@ int _LIBSNG_CALL sangoma_get_link_status(sng_fd_t fd, wanpipe_api_t *tdm_api, un
|
|||
int _LIBSNG_CALL sangoma_set_fe_status(sng_fd_t fd, wanpipe_api_t *tdm_api, unsigned char new_status)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_FE_STATUS;
|
||||
tdm_api->wp_cmd.fe_status = new_status;
|
||||
return sangoma_cmd_exec(fd, tdm_api);
|
||||
|
@ -2788,6 +2836,7 @@ int _LIBSNG_CALL sangoma_set_fe_status(sng_fd_t fd, wanpipe_api_t *tdm_api, unsi
|
|||
int _LIBSNG_CALL sangoma_disable_bri_bchan_loopback(sng_fd_t fd, wanpipe_api_t *tdm_api, int channel)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.channel = (unsigned char)channel;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_BRI_CHAN_LOOPBACK;
|
||||
|
@ -2798,6 +2847,7 @@ int _LIBSNG_CALL sangoma_disable_bri_bchan_loopback(sng_fd_t fd, wanpipe_api_t *
|
|||
int _LIBSNG_CALL sangoma_enable_bri_bchan_loopback(sng_fd_t fd, wanpipe_api_t *tdm_api, int channel)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.channel = (unsigned char)channel;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_BRI_CHAN_LOOPBACK;
|
||||
|
@ -2810,6 +2860,7 @@ int _LIBSNG_CALL sangoma_get_tx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_TX_Q_SIZE;
|
||||
tdm_api->wp_cmd.tx_queue_sz = 0;
|
||||
|
||||
|
@ -2827,6 +2878,7 @@ int _LIBSNG_CALL sangoma_set_tx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api, in
|
|||
return -1;
|
||||
}
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_TX_Q_SIZE;
|
||||
tdm_api->wp_cmd.tx_queue_sz = size;
|
||||
return sangoma_cmd_exec(fd, tdm_api);
|
||||
|
@ -2837,6 +2889,7 @@ int _LIBSNG_CALL sangoma_get_rx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_RX_Q_SIZE;
|
||||
tdm_api->wp_cmd.rx_queue_sz = 0;
|
||||
|
||||
|
@ -2856,6 +2909,7 @@ int _LIBSNG_CALL sangoma_set_rx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api, in
|
|||
}
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_RX_Q_SIZE;
|
||||
tdm_api->wp_cmd.rx_queue_sz = size;
|
||||
return sangoma_cmd_exec(fd, tdm_api);
|
||||
|
@ -2866,6 +2920,7 @@ int _LIBSNG_CALL sangoma_get_driver_version(sng_fd_t fd, wanpipe_api_t *tdm_api,
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_DRIVER_VERSION;
|
||||
|
||||
err = sangoma_cmd_exec(fd, tdm_api);
|
||||
|
@ -2887,6 +2942,7 @@ int _LIBSNG_CALL sangoma_get_firmware_version(sng_fd_t fd, wanpipe_api_t *tdm_ap
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_FIRMWARE_VERSION;
|
||||
|
||||
err = sangoma_cmd_exec(fd, tdm_api);
|
||||
|
@ -2906,6 +2962,7 @@ int _LIBSNG_CALL sangoma_get_cpld_version(sng_fd_t fd, wanpipe_api_t *tdm_api, u
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_CPLD_VERSION;
|
||||
|
||||
err = sangoma_cmd_exec(fd, tdm_api);
|
||||
|
@ -2925,6 +2982,7 @@ int _LIBSNG_CALL sangoma_get_stats(sng_fd_t fd, wanpipe_api_t *tdm_api, wanpipe_
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_STATS;
|
||||
|
||||
err = sangoma_cmd_exec(fd, tdm_api);
|
||||
|
@ -2940,6 +2998,7 @@ int _LIBSNG_CALL sangoma_get_stats(sng_fd_t fd, wanpipe_api_t *tdm_api, wanpipe_
|
|||
int _LIBSNG_CALL sangoma_flush_stats(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_RESET_STATS;
|
||||
return sangoma_cmd_exec(fd, tdm_api);
|
||||
}
|
||||
|
@ -2947,6 +3006,7 @@ int _LIBSNG_CALL sangoma_flush_stats(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_set_rm_rxflashtime(sng_fd_t fd, wanpipe_api_t *tdm_api, int rxflashtime)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_RM_RXFLASHTIME;
|
||||
tdm_api->wp_cmd.rxflashtime=rxflashtime;
|
||||
return sangoma_cmd_exec(fd, tdm_api);
|
||||
|
@ -2956,6 +3016,7 @@ int _LIBSNG_CALL sangoma_set_rm_rxflashtime(sng_fd_t fd, wanpipe_api_t *tdm_api,
|
|||
int _LIBSNG_CALL sangoma_set_rm_tx_gain(sng_fd_t fd, wanpipe_api_t *tdm_api, int value)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_SET_RM_TX_GAIN;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2966,6 +3027,7 @@ int _LIBSNG_CALL sangoma_set_rm_tx_gain(sng_fd_t fd, wanpipe_api_t *tdm_api, int
|
|||
int _LIBSNG_CALL sangoma_set_rm_rx_gain(sng_fd_t fd, wanpipe_api_t *tdm_api, int value)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_SET_RM_RX_GAIN;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2979,6 +3041,7 @@ int _LIBSNG_CALL sangoma_tdm_set_polarity(sng_fd_t fd, wanpipe_api_t *tdm_api, i
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_SETPOLARITY;
|
||||
tdm_api->wp_cmd.event.wp_api_event_polarity = polarity;
|
||||
|
@ -2991,6 +3054,7 @@ int _LIBSNG_CALL sangoma_tdm_set_polarity(sng_fd_t fd, wanpipe_api_t *tdm_api, i
|
|||
int _LIBSNG_CALL sangoma_tdm_txsig_onhooktransfer(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_ONHOOKTRANSFER;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -3004,6 +3068,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_loop(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_ENABLE_LOOP;
|
||||
err = sangoma_cmd_exec(fd, tdm_api);
|
||||
return err;
|
||||
|
@ -3014,6 +3079,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_loop(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_DISABLE_LOOP;
|
||||
err = sangoma_cmd_exec(fd, tdm_api);
|
||||
return err;
|
||||
|
@ -3139,6 +3205,7 @@ int _LIBSNG_CALL sangoma_mgmt_cmd(sng_fd_t fd, wan_udp_hdr_t* wan_udp)
|
|||
int _LIBSNG_CALL sangoma_driver_port_start(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no)
|
||||
{
|
||||
int err;
|
||||
port_mgmnt->operation_status = SANG_STATUS_GENERAL_ERROR;
|
||||
port_mgmnt->command_code = START_PORT_VOLATILE_CONFIG;
|
||||
port_mgmnt->port_no = port_no;
|
||||
|
||||
|
@ -3154,6 +3221,7 @@ int _LIBSNG_CALL sangoma_driver_port_start(sng_fd_t fd, port_management_struct_t
|
|||
int _LIBSNG_CALL sangoma_driver_port_stop(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no)
|
||||
{
|
||||
int err;
|
||||
port_mgmnt->operation_status = SANG_STATUS_GENERAL_ERROR;
|
||||
port_mgmnt->command_code = STOP_PORT;
|
||||
port_mgmnt->port_no = port_no;
|
||||
|
||||
|
@ -3182,6 +3250,7 @@ int _LIBSNG_CALL sangoma_driver_port_stop(sng_fd_t fd, port_management_struct_t
|
|||
int _LIBSNG_CALL sangoma_driver_get_hw_info(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no)
|
||||
{
|
||||
int err;
|
||||
port_mgmnt->operation_status = SANG_STATUS_GENERAL_ERROR;
|
||||
port_mgmnt->command_code = GET_HARDWARE_INFO;
|
||||
port_mgmnt->port_no = port_no;
|
||||
|
||||
|
@ -3193,8 +3262,23 @@ int _LIBSNG_CALL sangoma_driver_get_hw_info(sng_fd_t fd, port_management_struct_
|
|||
return port_mgmnt->operation_status;
|
||||
}
|
||||
|
||||
int _LIBSNG_CALL sangoma_driver_get_version(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no)
|
||||
{
|
||||
int err;
|
||||
port_mgmnt->command_code = GET_DRIVER_VERSION;
|
||||
port_mgmnt->port_no = port_no;
|
||||
|
||||
err = sangoma_port_mgmnt_ioctl(fd, port_mgmnt);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return port_mgmnt->operation_status;
|
||||
}
|
||||
|
||||
int _LIBSNG_CALL sangoma_driver_port_set_config(sng_fd_t fd, port_cfg_t *port_cfg, unsigned short port_no)
|
||||
{
|
||||
port_cfg->operation_status = SANG_STATUS_GENERAL_ERROR;
|
||||
port_cfg->command_code = SET_PORT_VOLATILE_CONFIG;
|
||||
port_cfg->port_no = port_no;
|
||||
|
||||
|
@ -3203,6 +3287,7 @@ int _LIBSNG_CALL sangoma_driver_port_set_config(sng_fd_t fd, port_cfg_t *port_cf
|
|||
|
||||
int _LIBSNG_CALL sangoma_driver_port_get_config(sng_fd_t fd, port_cfg_t *port_cfg, unsigned short port_no)
|
||||
{
|
||||
port_cfg->operation_status = SANG_STATUS_GENERAL_ERROR;
|
||||
port_cfg->command_code = GET_PORT_VOLATILE_CONFIG;
|
||||
port_cfg->port_no = port_no;
|
||||
return sangoma_port_cfg_ioctl(fd, port_cfg);
|
||||
|
|
|
@ -89,12 +89,19 @@ struct sangoma_wait_obj;
|
|||
\brief Instantiate/Declare a tdm api cmd strucure
|
||||
\def SANGOMA_INIT_TDM_API_CMD
|
||||
\brief Initialize the tdm api cmd structure. Set to 0.
|
||||
\def SANGOMA_INIT_TDM_API_CMD_RESULT
|
||||
\brief Initialize the 'result' in wanpipe_api_t to SANG_STATUS_GENERAL_ERROR.
|
||||
\def SANGOMA_DECLARE_INIT_TDM_API_CMD
|
||||
\brief Declare and initialize the tdm api cmd structure.
|
||||
*/
|
||||
#define SANGOMA_DECLARE_TDM_API_CMD(_name_) wanpipe_api_t _name_
|
||||
#define SANGOMA_INIT_TDM_API_CMD(_name_) memset(&_name_,0,sizeof(_name_))
|
||||
#define SANGOMA_DECLARE_INIT_TDM_API_CMD(_name_) wanpipe_tdm_api_t _name_; SANGOMA_INIT_TDM_API_CMD(_name_)
|
||||
|
||||
#define SANGOMA_INIT_TDM_API_CMD(_name_) memset(&_name_,0,sizeof(_name_)); \
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(_name_)
|
||||
|
||||
#define SANGOMA_INIT_TDM_API_CMD_RESULT(_name_) (_name_).wp_cmd.result = SANG_STATUS_GENERAL_ERROR
|
||||
|
||||
#define SANGOMA_DECLARE_INIT_TDM_API_CMD(_name_) wanpipe_tdm_api_t _name_; SANGOMA_INIT_TDM_API_CMD(_name_);
|
||||
|
||||
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
|
@ -106,6 +113,7 @@ struct sangoma_wait_obj;
|
|||
#include <conio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
/*!
|
||||
\def _LIBSNG_CALL
|
||||
|
@ -114,8 +122,14 @@ struct sangoma_wait_obj;
|
|||
#ifdef __COMPILING_LIBSANGOMA__
|
||||
# define _LIBSNG_CALL __declspec(dllexport) __cdecl
|
||||
#else
|
||||
# define _LIBSNG_CALL __declspec(dllimport) __cdecl
|
||||
#endif
|
||||
# ifdef __LIBSANGOMA_IS_STATIC_LIB__
|
||||
/* libsangoma is static lib OR 'compiled in' */
|
||||
# define _LIBSNG_CALL __cdecl
|
||||
# else
|
||||
/* compiling an application which will use libsangoma.dll */
|
||||
# define _LIBSNG_CALL __declspec(dllimport) __cdecl
|
||||
# endif
|
||||
#endif /* __COMPILING_LIBSANGOMA__ */
|
||||
|
||||
/*!
|
||||
\def SANGOMA_INFINITE_API_POLL_WAIT (deprecated, use SANGOMA_WAIT_INFINITE instead)
|
||||
|
@ -251,10 +265,12 @@ typedef unsigned char * PUCHAR;
|
|||
typedef void * PVOID;
|
||||
typedef void * LPTHREAD_START_ROUTINE;
|
||||
typedef pthread_mutex_t CRITICAL_SECTION;
|
||||
typedef unsigned int UINT;
|
||||
|
||||
#define EnterCriticalSection(arg) pthread_mutex_lock(arg)
|
||||
#define TryEnterCriticalSection(arg) pthread_mutex_trylock(arg)
|
||||
#define LeaveCriticalSection(arg) pthread_mutex_unlock(arg)
|
||||
#define InitializeCriticalSection(arg) pthread_mutex_init(arg, NULL);
|
||||
#define InitializeCriticalSection(arg) pthread_mutex_init(arg, NULL);
|
||||
|
||||
typedef struct tm SYSTEMTIME;
|
||||
typedef char * LPCTSTR;
|
||||
|
@ -355,9 +371,9 @@ typedef enum _sangoma_wait_obj_type
|
|||
* Users are encouraged to use this flags instead of the system ones
|
||||
*/
|
||||
typedef enum _sangoma_wait_obj_flags {
|
||||
SANG_WAIT_OBJ_HAS_INPUT = POLLIN,
|
||||
SANG_WAIT_OBJ_HAS_OUTPUT = POLLOUT,
|
||||
SANG_WAIT_OBJ_HAS_EVENTS = POLLPRI,
|
||||
SANG_WAIT_OBJ_HAS_INPUT = WP_POLLIN,
|
||||
SANG_WAIT_OBJ_HAS_OUTPUT = WP_POLLOUT,
|
||||
SANG_WAIT_OBJ_HAS_EVENTS = WP_POLLPRI,
|
||||
SANG_WAIT_OBJ_IS_SIGNALED = 0x400 /* matches GNU extension POLLMSG */
|
||||
} sangoma_wait_obj_flags_t;
|
||||
|
||||
|
@ -1045,6 +1061,21 @@ int _LIBSNG_CALL sangoma_get_link_status(sng_fd_t fd, wanpipe_api_t *tdm_api, un
|
|||
int _LIBSNG_CALL sangoma_set_fe_status(sng_fd_t fd, wanpipe_api_t *tdm_api, unsigned char new_status);
|
||||
|
||||
|
||||
|
||||
#ifdef WP_API_FEATURE_BUFFER_MULT
|
||||
/*!
|
||||
\fn int sangoma_tdm_set_buffer_multiplier(sng_fd_t fd, wanpipe_api_t *tdm_api, unsigned int multiplier)
|
||||
\brief Set voice tx/rx buffer multiplier.
|
||||
\param fd device file descriptor
|
||||
\param tdm_api tdm api command structure
|
||||
\param multiplier buffer multiplier value 0-disable or 1 to TDMAPI_MAX_BUFFER_MULTIPLIER
|
||||
\return non-zero: error, 0: ok
|
||||
*/
|
||||
int _LIBSNG_CALL sangoma_tdm_set_buffer_multiplier(sng_fd_t fd, wanpipe_api_t *tdm_api, unsigned int multiplier);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
\fn int _LIBSNG_CALL sangoma_enable_bri_bchan_loopback(sng_fd_t fd, wanpipe_api_t *tdm_api, int channel)
|
||||
\brief Enable BRI Bchannel loopback - used when debugging bri device
|
||||
|
@ -1121,10 +1152,7 @@ int _LIBSNG_CALL sangoma_set_rx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api, in
|
|||
\brief Get HW Voice Coding (ulaw/alaw)
|
||||
\param fd device file descriptor
|
||||
\param tdm_api tdm api command structure
|
||||
\return non-zero: error, 0: ok
|
||||
|
||||
This function will return the low level voice coding
|
||||
depending on configuration. (ulaw or alaw)
|
||||
\return the low level voice coding, depending on configuration. (WP_MULAW or WP_ALAW)
|
||||
*/
|
||||
int _LIBSNG_CALL sangoma_get_hw_coding(sng_fd_t fd, wanpipe_api_t *tdm_api);
|
||||
|
||||
|
@ -1153,12 +1181,29 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_dtmf(sng_fd_t fd, wanpipe_api_t *tdm_api);
|
|||
\brief Check if hw echo cancelation support is available
|
||||
\param fd device file descriptor
|
||||
\param tdm_api tdm api command structure
|
||||
\return non-zero: error, 0: ok
|
||||
\return non-zero: error, 0: disable, >0:enabled
|
||||
|
||||
This function will check if hw supports HW EC.
|
||||
*/
|
||||
int _LIBSNG_CALL sangoma_tdm_get_hw_ec(sng_fd_t fd, wanpipe_api_t *tdm_api);
|
||||
|
||||
|
||||
#ifdef WP_API_FEATURE_EC_CHAN_STAT
|
||||
/*!
|
||||
\fn int sangoma_tdm_get_hwec_chan_status(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
\brief Check if hw echo cancelation is enabled on current timeslot
|
||||
\param fd device file descriptor
|
||||
\param tdm_api tdm api command structure
|
||||
\return non-zero: error, 0: disabled, >0: enabled
|
||||
|
||||
This function will check if hw echo cancelation is enable
|
||||
on current timeslot.
|
||||
*/
|
||||
|
||||
int _LIBSNG_CALL sangoma_tdm_get_hwec_chan_status(sng_fd_t fd, wanpipe_api_t *tdm_api);
|
||||
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\fn int sangoma_span_chan_toif(int span, int chan, char *interface_name)
|
||||
\brief Convert Span & Chan to interface name
|
||||
|
@ -1497,6 +1542,22 @@ int _LIBSNG_CALL sangoma_driver_port_get_config(sng_fd_t fd, port_cfg_t *port_cf
|
|||
int _LIBSNG_CALL sangoma_driver_get_hw_info(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no);
|
||||
|
||||
|
||||
/*!
|
||||
\fn int sangoma_driver_get_version(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no)
|
||||
\brief Retrieve Driver Version BEFORE any communication interface is configured and sangoma_get_driver_version()
|
||||
can not be called.
|
||||
\param[in] fd Port Device file descriptor
|
||||
\param[out] port_mgmnt pointer to port_management_struct_t structure which will contain wan_driver_version_t at
|
||||
it's "data" field, when this function returns.
|
||||
\param[in] port_no please see comment of sangoma_driver_port_set_config()
|
||||
\return non-zero: system error. Call OS specific code to find cause of the error.
|
||||
Linux example: strerror(errno)
|
||||
Windows example: combination of GetLastError()/FormatMessage()
|
||||
zero: no system error. Check port_mgmt->operation_status.
|
||||
*/
|
||||
int _LIBSNG_CALL sangoma_driver_get_version(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no);
|
||||
|
||||
|
||||
/*!
|
||||
\fn int sangoma_write_port_config_on_persistent_storage(hardware_info_t *hardware_info, port_cfg_t *port_cfg)
|
||||
\brief Write Port's configuration on the hard disk.
|
||||
|
@ -1635,18 +1696,34 @@ int _LIBSNG_CALL sangoma_tdm_get_power_level(sng_fd_t fd, wanpipe_api_t *tdm_api
|
|||
|
||||
|
||||
#ifdef WP_API_FEATURE_LIBSNG_HWEC
|
||||
/*!
|
||||
\fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name)
|
||||
|
||||
\brief Load Firmware image onto EC chip.
|
||||
/*!
|
||||
\fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name, wan_custom_param_t custom_params[], unsigned int number_of_custom_params)
|
||||
|
||||
\brief Load Firmware image onto EC chip. All chip-wide configuration paramters, if any,
|
||||
must be specified at the time of chip initialization.
|
||||
|
||||
\param device_name Sangoma API device name.
|
||||
Windows: wanpipe1_if1, wanpipe2_if1...
|
||||
Linux: wanpipe1, wanpipe2...
|
||||
|
||||
\param custom_params[] - (optional) array of custom paramter structures.
|
||||
|
||||
This is list of Echo Cancellation chip parameters:
|
||||
|
||||
Chip parameter Chip parameter value
|
||||
================= =======================
|
||||
WANEC_TailDisplacement 0-896
|
||||
WANEC_MaxPlayoutBuffers 0-4678
|
||||
WANEC_EnableExtToneDetection TRUE | FALSE
|
||||
WANEC_EnableAcousticEcho TRUE | FALSE
|
||||
|
||||
\param number_of_custom_params - (optional) number of structures in custom_params[]. Minimum value is 1, maximum is 4,
|
||||
if any other value the custom_params[] will be ignored.
|
||||
|
||||
\return SANG_STATUS_SUCCESS: success, or error status
|
||||
*/
|
||||
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name);
|
||||
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name, wan_custom_param_t custom_params[], unsigned int number_of_custom_params);
|
||||
|
||||
/*!
|
||||
\fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_release(char *device_name)
|
||||
|
@ -1769,9 +1846,16 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_enable(char *device_name, unsigned i
|
|||
sangoma_status_t _LIBSNG_CALL sangoma_hwec_disable(char *device_name, unsigned int fe_chan_map);
|
||||
|
||||
/*!
|
||||
\fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameters(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map)
|
||||
\fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameter(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map)
|
||||
|
||||
\brief Modify channel configuration parameters.
|
||||
|
||||
\param device_name Sangoma API device name.
|
||||
Windows: wanpipe1_if1, wanpipe2_if1...
|
||||
Linux: wanpipe1, wanpipe2...
|
||||
|
||||
\param parameter Echo Cancellation channel parameter
|
||||
|
||||
This is list of Echo Cancellation channel parameters:
|
||||
|
||||
Channel parameter Channel parameter value
|
||||
|
@ -1800,7 +1884,7 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_disable(char *device_name, unsigned i
|
|||
|
||||
\return SANG_STATUS_SUCCESS: success, or error status
|
||||
*/
|
||||
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameters(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map);
|
||||
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameter(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map);
|
||||
|
||||
/*!
|
||||
\fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_tone_detection(char *device_name, int tone_id, int enable, unsigned int fe_chan_map, unsigned char port_map)
|
||||
|
@ -1917,6 +2001,19 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_audio_buffer_playout(char *device_nam
|
|||
*/
|
||||
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_verbosity(int verbosity_level);
|
||||
|
||||
/*!
|
||||
\fn void _LIBSNG_CALL sangoma_hwec_initialize_custom_parameter_structure(wan_custom_param_t *custom_param, char *parameter_name, char *parameter_value)
|
||||
|
||||
\brief Initialize Custom Paramter structure.
|
||||
|
||||
\param parameter_name Parameter Name
|
||||
|
||||
\param parameter_value Parameter Value
|
||||
|
||||
\return None
|
||||
*/
|
||||
void _LIBSNG_CALL sangoma_hwec_initialize_custom_parameter_structure(wan_custom_param_t *custom_param, char *parameter_name, char *parameter_value);
|
||||
|
||||
#endif /* WP_API_FEATURE_LIBSNG_HWEC */
|
||||
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@
|
|||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=".;include\api;include\debug;include\octasic;include\pnp;..\libpri"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;__WINDOWS__;__COMPILING_LIBSANGOMA__;WANPIPE_TDM_API;_CRT_SECURE_NO_DEPRECATE;WP_API_FEATURE_DTMF_EVENTS;WP_API_FEATURE_EVENTS;WP_API_FEATURE_RM_GAIN;WP_API_FEATURE_LINK_STATUS;WP_API_FEATURE_FE_ALARM;WP_API_FEATURE_FAX_EVENTS;WP_API_FEATURE_LOGGER;WP_API_FEATURE_LIBSNG_HWEC"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;__WINDOWS__;__COMPILING_LIBSANGOMA__;WANPIPE_TDM_API;_CRT_SECURE_NO_DEPRECATE;WP_API_FEATURE_DTMF_EVENTS;WP_API_FEATURE_EVENTS;WP_API_FEATURE_RM_GAIN;WP_API_FEATURE_LINK_STATUS;WP_API_FEATURE_FE_ALARM;WP_API_FEATURE_FAX_EVENTS;WP_API_FEATURE_LOGGER;WP_API_FEATURE_LIBSNG_HWEC;WP_PREVENT_WINSOCK_NAME_CONFLICT"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
|
|
|
@ -44,12 +44,7 @@
|
|||
# pragma comment( lib, "waneclib" ) /* import functions from waneclib.dll */
|
||||
#endif/* __WINDOWS__) */
|
||||
|
||||
/* Fast sequence of commands to HWEC may cause the chip
|
||||
* enter fatal error state, the workaround is to have
|
||||
* a guaranteed delay after eache command. */
|
||||
#define HWEC_CMD_DELAY() wp_usleep(20000) /* 20ms */
|
||||
|
||||
static int libsng_hwec_verbosity_level = 0;
|
||||
static int libsng_hwec_verbosity_level = 0x00;
|
||||
|
||||
/************************************************************//**
|
||||
* Private Functions. (Not exported)
|
||||
|
@ -67,54 +62,145 @@ static sangoma_status_t sangoma_hwec_bypass(char *device_name, int enable, unsig
|
|||
|
||||
/* WAN_EC_API_CMD_HWEC_ENABLE/WAN_EC_API_CMD_HWEC_DISABLE - Controls the "bypass" mode.)*/
|
||||
rc = wanec_api_hwec(device_name, libsng_hwec_verbosity_level, &hwec);
|
||||
if( rc ) {
|
||||
return rc;
|
||||
}
|
||||
HWEC_CMD_DELAY();
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int sangoma_hwec_is_numeric_parameter(char *parameter)
|
||||
{
|
||||
int i;
|
||||
static char *WANEC_numeric_params[] = {
|
||||
"WANEC_TailDisplacement",
|
||||
"WANEC_MaxPlayoutBuffers",
|
||||
"WANEC_MaxConfBridges",
|
||||
"WANEC_EchoOperationMode",
|
||||
"WANEC_ComfortNoiseMode",
|
||||
"WANEC_NonLinearityBehaviorA",
|
||||
"WANEC_NonLinearityBehaviorB",
|
||||
"WANEC_DoubleTalkBehavior",
|
||||
"WANEC_RinLevelControlGainDb",
|
||||
"WANEC_SoutLevelControlGainDb",
|
||||
"WANEC_RinAutomaticLevelControlTargetDb",
|
||||
"WANEC_SoutAutomaticLevelControlTargetDb",
|
||||
"WANEC_RinHighLevelCompensationThresholdDb",
|
||||
"WANEC_AnrSnrEnhancementDb",
|
||||
NULL
|
||||
};
|
||||
|
||||
/************************************************************//**
|
||||
i = 0;
|
||||
while(WANEC_numeric_params[i]){
|
||||
if (!wp_strncasecmp(parameter, WANEC_numeric_params[i], strlen(parameter))) {
|
||||
return 1;/* this IS a numeric parameter */
|
||||
}
|
||||
i++;
|
||||
};
|
||||
|
||||
return 0;/* NOT a numeric parameter */
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
* Public Functions. (Exported)
|
||||
***************************************************************/
|
||||
|
||||
/*!
|
||||
\fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name)
|
||||
\fn void _LIBSNG_CALL sangoma_hwec_initialize_custom_parameter_structure(wan_custom_param_t *custom_param, char *parameter_name, char *parameter_value)
|
||||
|
||||
\brief Load Firmware image onto EC chip.
|
||||
\brief Initialize Custom Paramter structure.
|
||||
|
||||
\param parameter_name Parameter Name
|
||||
|
||||
\param parameter_value Parameter Value
|
||||
|
||||
\return None
|
||||
*/
|
||||
void _LIBSNG_CALL sangoma_hwec_initialize_custom_parameter_structure(wan_custom_param_t *custom_param, char *parameter_name, char *parameter_value)
|
||||
{
|
||||
memset(custom_param, 0x00, sizeof(*custom_param));
|
||||
|
||||
strncpy( custom_param->name, parameter_name, sizeof(custom_param->name) );
|
||||
|
||||
if (sangoma_hwec_is_numeric_parameter(parameter_name)) {
|
||||
custom_param->dValue = atoi(parameter_value);
|
||||
} else {
|
||||
strncpy(custom_param->sValue, parameter_value, sizeof(custom_param->sValue));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name, wan_custom_param_t custom_params[], unsigned int number_of_custom_params)
|
||||
|
||||
\brief Load Firmware image onto EC chip. All chip-wide configuration paramters, if any,
|
||||
must be specified at the time of chip initialization.
|
||||
|
||||
\param device_name Sangoma API device name.
|
||||
Windows: wanpipe1_if1, wanpipe2_if1...
|
||||
Linux: wanpipe1, wanpipe2...
|
||||
|
||||
\param custom_params[] - (optional) array of custom paramter structures.
|
||||
|
||||
This is list of Echo Cancellation chip parameters:
|
||||
|
||||
Chip parameter Chip parameter value
|
||||
================= =======================
|
||||
WANEC_TailDisplacement 0-896
|
||||
WANEC_MaxPlayoutBuffers 0-4678
|
||||
WANEC_EnableExtToneDetection TRUE | FALSE
|
||||
WANEC_EnableAcousticEcho TRUE | FALSE
|
||||
|
||||
\param number_of_custom_params - (optional) number of structures in custom_params[]. Minimum value is 1, maximum is 4,
|
||||
if any other value the custom_params[] will be ignored.
|
||||
|
||||
\return SANG_STATUS_SUCCESS: success, or error status
|
||||
*/
|
||||
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name)
|
||||
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name, wan_custom_param_t custom_params[], unsigned int number_of_custom_params)
|
||||
{
|
||||
sangoma_status_t rc;
|
||||
wan_custom_param_t custom_parms;
|
||||
sangoma_status_t rc = SANG_STATUS_SUCCESS;
|
||||
wanec_api_config_t config;
|
||||
|
||||
memset(&config, 0x00, sizeof(config));
|
||||
memset(&custom_parms, 0x0, sizeof(custom_parms));
|
||||
|
||||
#if 1
|
||||
/* enable acoustic echo cancellation by default */
|
||||
strcpy( custom_parms.name, "WANEC_EnableAcousticEcho" );
|
||||
strcpy( custom_parms.sValue, "TRUE" );
|
||||
|
||||
config.conf.param_no = 1;
|
||||
config.conf.params = &custom_parms;
|
||||
#endif
|
||||
if (number_of_custom_params >= 1 && number_of_custom_params <= 4) {
|
||||
|
||||
/* Load firmware on EC chip */
|
||||
wan_custom_param_t *custom_parms_ptr;
|
||||
unsigned int i, custom_params_memory_size;
|
||||
|
||||
custom_params_memory_size = sizeof(wan_custom_param_t) * number_of_custom_params;
|
||||
|
||||
/* Do NOT change memory at custom_params[] (it belongs to the caller).
|
||||
* Instead allocate temporary buffer, and use information in custom_params[]
|
||||
* for proper initialization the temproary buffer and
|
||||
* and send if down to API driver. */
|
||||
custom_parms_ptr = malloc(custom_params_memory_size);
|
||||
if (!custom_parms_ptr) {
|
||||
return SANG_STATUS_FAILED_ALLOCATE_MEMORY;
|
||||
}
|
||||
|
||||
memset(custom_parms_ptr, 0x00, custom_params_memory_size);
|
||||
|
||||
for (i = 0; i < number_of_custom_params; i++) {
|
||||
|
||||
strcpy( custom_parms_ptr[i].name, custom_params[i].name );
|
||||
|
||||
if (sangoma_hwec_is_numeric_parameter(custom_params[i].name)) {
|
||||
custom_parms_ptr[i].dValue = atoi(custom_params[i].sValue);
|
||||
} else {
|
||||
strcpy(custom_parms_ptr[i].sValue, custom_params[i].sValue);
|
||||
}
|
||||
} /* for() */
|
||||
|
||||
config.conf.param_no = number_of_custom_params;
|
||||
config.conf.params = custom_parms_ptr;
|
||||
|
||||
}/* if() */
|
||||
|
||||
/* Load firmware on EC chip AND apply configuration, if any. */
|
||||
rc = wanec_api_config( device_name, libsng_hwec_verbosity_level, &config );
|
||||
if( rc ) {
|
||||
return rc;
|
||||
|
||||
if (config.conf.params) {
|
||||
free(config.conf.params);
|
||||
}
|
||||
HWEC_CMD_DELAY();
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
@ -137,14 +223,10 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_release(char *device_name)
|
|||
memset(&release, 0, sizeof(wanec_api_release_t));
|
||||
|
||||
rc = wanec_api_release( device_name, libsng_hwec_verbosity_level, &release );
|
||||
if( rc ) {
|
||||
return rc;
|
||||
}
|
||||
HWEC_CMD_DELAY();
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Modify channel operation mode.
|
||||
*/
|
||||
|
@ -167,11 +249,8 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_operation_mode(char *device_na
|
|||
WANEC_API_OPMODE_SPEECH_RECOGNITION.
|
||||
*/
|
||||
rc = wanec_api_opmode(device_name, libsng_hwec_verbosity_level, &opmode);
|
||||
if( rc ) {
|
||||
return rc;
|
||||
}
|
||||
HWEC_CMD_DELAY();
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -229,7 +308,7 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_power_off(char *device_name,
|
|||
This command is recommened for fast enabling of Echo Cancellation.
|
||||
Note 1: Chip must be configured and in POWER ON state for echo
|
||||
Chancellation to take place.
|
||||
Note 2: sangoma_tdm_enable_hwec() function can be use to achive
|
||||
Note 2: sangoma_tdm_enable_hwec() function can be used to achive
|
||||
the same funcitnality based on file descriptor versus
|
||||
channel map.
|
||||
|
||||
|
@ -275,10 +354,17 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_disable(char *device_name, unsigned i
|
|||
}
|
||||
|
||||
/*!
|
||||
\fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameters(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map)
|
||||
\fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameter(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map)
|
||||
|
||||
\brief Modify channel configuration parameters.
|
||||
This is list of Echo Cancellation channel parameters:
|
||||
|
||||
\param device_name Sangoma API device name.
|
||||
Windows: wanpipe1_if1, wanpipe2_if1...
|
||||
Linux: wanpipe1, wanpipe2...
|
||||
|
||||
\param parameter Echo Cancellation channel parameter
|
||||
|
||||
This channel parameters are listed under "Channel parameter":
|
||||
|
||||
Channel parameter Channel parameter value
|
||||
================= =======================
|
||||
|
@ -301,33 +387,30 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_disable(char *device_name, unsigned i
|
|||
WANEC_DoubleTalkBehavior DT_BEH_NORMAL
|
||||
DT_BEH_LESS_AGGRESSIVE
|
||||
|
||||
\param parameter_value channel parameter value, listed under "Channel parameter value"
|
||||
|
||||
\param fe_chan_map Bitmap of channels (timeslots for Digital, lines for Analog) where
|
||||
the call will take effect.
|
||||
|
||||
\return SANG_STATUS_SUCCESS: success, or error status
|
||||
*/
|
||||
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameters(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map)
|
||||
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameter(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map)
|
||||
{
|
||||
sangoma_status_t rc;
|
||||
wanec_api_modify_t channelModify;
|
||||
wan_custom_param_t aParms;
|
||||
wan_custom_param_t custom_param;
|
||||
|
||||
memset(&channelModify, 0x00, sizeof(channelModify));
|
||||
memset(&aParms, 0x00, sizeof(aParms));
|
||||
|
||||
sangoma_hwec_initialize_custom_parameter_structure(&custom_param, parameter, parameter_value);
|
||||
|
||||
channelModify.fe_chan_map = channel_map;
|
||||
channelModify.conf.param_no = 1;
|
||||
channelModify.conf.params = &aParms;
|
||||
|
||||
strcpy( aParms.name, parameter);
|
||||
strcpy( aParms.sValue, parameter_value);
|
||||
channelModify.conf.params = &custom_param;
|
||||
|
||||
rc = wanec_api_modify( device_name, libsng_hwec_verbosity_level, &channelModify );
|
||||
if( rc ){
|
||||
return rc;
|
||||
}
|
||||
HWEC_CMD_DELAY();
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -366,11 +449,8 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_tone_detection(char *device_na
|
|||
tone.type_map = WAN_EC_TONE_PRESENT | WAN_EC_TONE_STOP;
|
||||
|
||||
rc = wanec_api_tone( device_name, libsng_hwec_verbosity_level, &tone );
|
||||
if( rc ) {
|
||||
return rc;
|
||||
}
|
||||
HWEC_CMD_DELAY();
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -401,11 +481,8 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_print_statistics(char *device_name, i
|
|||
stats.reset = 0; /* do not reset */
|
||||
|
||||
rc = wanec_api_stats( device_name, libsng_hwec_verbosity_level, &stats );
|
||||
if( rc ) {
|
||||
return rc;
|
||||
}
|
||||
HWEC_CMD_DELAY();
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -443,7 +520,6 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_audio_buffer_load(char *device_name,
|
|||
|
||||
*out_buffer_id = bufferload.buffer_id;
|
||||
|
||||
HWEC_CMD_DELAY();
|
||||
return SANG_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -468,11 +544,8 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_audio_buffer_unload(char *device_name
|
|||
bufferunload.buffer_id = (unsigned int)in_buffer_id;
|
||||
|
||||
rc = wanec_api_buffer_unload( device_name, libsng_hwec_verbosity_level, &bufferunload);
|
||||
if( rc ) {
|
||||
return rc;
|
||||
}
|
||||
HWEC_CMD_DELAY();
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -518,18 +591,17 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_audio_buffer_playout(char *device_nam
|
|||
playout.duration = (duration) ? duration : 5000; /* default is 5s */
|
||||
|
||||
rc = wanec_api_playout( device_name, libsng_hwec_verbosity_level, &playout);
|
||||
if( rc ) {
|
||||
return rc;
|
||||
}
|
||||
HWEC_CMD_DELAY();
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn void _LIBSNG_CALL sangoma_hwec_config_verbosity(int verbosity_level)
|
||||
|
||||
\brief Set Verbosity level of EC API. The level controls amount of data
|
||||
printed to stdout and wanpipelog.txt for diagnostic purposes.
|
||||
\brief Set Verbosity level of EC API Driver and Library.
|
||||
The level controls amount of data
|
||||
printed to stdout and to wanpipelog.txt (Windows) or
|
||||
/var/log/messages (Linux) for diagnostic purposes.
|
||||
|
||||
\param verbosity_level Valid values are from 0 to 3.
|
||||
|
||||
|
@ -539,6 +611,7 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_verbosity(int verbosity_level)
|
|||
{
|
||||
if (verbosity_level >= 0 || verbosity_level <= 3) {
|
||||
libsng_hwec_verbosity_level = verbosity_level;
|
||||
wanec_api_set_lib_verbosity(verbosity_level);
|
||||
return SANG_STATUS_SUCCESS;
|
||||
}
|
||||
return SANG_STATUS_INVALID_PARAMETER;
|
||||
|
|
|
@ -11,7 +11,7 @@ USE_LIBCMT=1
|
|||
DLLDEF=libsangoma.def
|
||||
|
||||
############################################################################################
|
||||
C_DEFINES=$(C_DEFINES) /D__WINDOWS__ /D__COMPILING_LIBSANGOMA__
|
||||
C_DEFINES=$(C_DEFINES) /D__WINDOWS__ /D__COMPILING_LIBSANGOMA__ /DWP_PREVENT_WINSOCK_NAME_CONFLICT
|
||||
############################################################################################
|
||||
|
||||
INCLUDES=$(SDK_INC_PATH);\
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
8
|
||||
|
||||
dir
|
||||
273
|
||||
293
|
||||
https://www.sangomapbx.com/svn/libsangoma/trunk/docs
|
||||
https://www.sangomapbx.com/svn/libsangoma
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
8
|
||||
|
||||
dir
|
||||
273
|
||||
293
|
||||
https://www.sangomapbx.com/svn/libsangoma/trunk/docs/doxygen
|
||||
https://www.sangomapbx.com/svn/libsangoma
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
8
|
||||
|
||||
dir
|
||||
273
|
||||
293
|
||||
https://www.sangomapbx.com/svn/libsangoma/trunk/examples
|
||||
https://www.sangomapbx.com/svn/libsangoma
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
8
|
||||
|
||||
dir
|
||||
273
|
||||
293
|
||||
https://www.sangomapbx.com/svn/libsangoma/trunk/examples/hptdm_api
|
||||
https://www.sangomapbx.com/svn/libsangoma
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
8
|
||||
|
||||
dir
|
||||
273
|
||||
293
|
||||
https://www.sangomapbx.com/svn/libsangoma/trunk/examples/hptdm_api/docs
|
||||
https://www.sangomapbx.com/svn/libsangoma
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
8
|
||||
|
||||
dir
|
||||
273
|
||||
293
|
||||
https://www.sangomapbx.com/svn/libsangoma/trunk/examples/hptdm_api/docs/doxygen
|
||||
https://www.sangomapbx.com/svn/libsangoma
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
8
|
||||
|
||||
dir
|
||||
273
|
||||
293
|
||||
https://www.sangomapbx.com/svn/libsangoma/trunk/examples/priserver
|
||||
https://www.sangomapbx.com/svn/libsangoma
|
||||
|
||||
|
|
|
@ -75,13 +75,6 @@ extern "C" { /* for C++ users */
|
|||
#define SANGOMA_OBJ_HAS_DEVICE(object) ((object)->object_type == SANGOMA_DEVICE_WAIT_OBJ \
|
||||
|| (object)->object_type == SANGOMA_DEVICE_WAIT_OBJ_SIG)
|
||||
|
||||
#define LIBSNG_NUMBER_OF_EVENT_OBJECTS 3 /* POLLIN, POLLOUT and POLLPRI */
|
||||
enum {
|
||||
LIBSNG_EVENT_INDEX_POLLIN=0,
|
||||
LIBSNG_EVENT_INDEX_POLLOUT,
|
||||
LIBSNG_EVENT_INDEX_POLLPRI
|
||||
};
|
||||
|
||||
#define LIBSNG_MAGIC_NO 0x90547419
|
||||
|
||||
/* libsangoma.h defines sangoma_wait_obj_t for the sake of clean prototype definitions, time to undefine it since from now on
|
||||
|
@ -114,10 +107,8 @@ typedef struct sangoma_wait_obj
|
|||
sangoma_wait_obj_type_t object_type;
|
||||
|
||||
#if defined(__WINDOWS__)
|
||||
/*! WINDOWS: api structure used by windows IoctlSetSharedEvent call */
|
||||
/*! to wait on events or data from the Sangoma device driver. */
|
||||
HANDLE sng_event_objects[LIBSNG_NUMBER_OF_EVENT_OBJECTS];
|
||||
HANDLE generic_event_object;
|
||||
/*! signallable object to wait on events or data from the Sangoma device driver or can be signalled by sangoma_wait_obj_signal(). */
|
||||
HANDLE signal_object;
|
||||
#else
|
||||
/*! LINUX: To be used by a pipe to asynchronously break a poll() */
|
||||
sng_fd_t signal_write_fd;
|
||||
|
|
|
@ -307,12 +307,11 @@ sangoma_status_t _LIBSNG_CALL sangoma_cdev_ctrl_cmd(sng_fd_t fd, wanpipe_tdm_api
|
|||
return handle_device_ioctl_result(bIoResult, __FUNCTION__);
|
||||
}
|
||||
|
||||
static sangoma_status_t init_sangoma_event_object(sangoma_wait_obj_t *sng_wait_obj, int flags_in, sng_fd_t fd)
|
||||
static sangoma_status_t init_sangoma_event_object(sangoma_wait_obj_t *sng_wait_obj, sng_fd_t fd)
|
||||
{
|
||||
int event_index = -1;
|
||||
wanpipe_tdm_api_cmd_t tdm_api_cmd;
|
||||
sangoma_status_t sng_status;
|
||||
char event_name[200], tmp_event_name[200];
|
||||
char event_name[200];
|
||||
|
||||
memset(&tdm_api_cmd, 0x00, sizeof(tdm_api_cmd));
|
||||
|
||||
|
@ -325,40 +324,18 @@ static sangoma_status_t init_sangoma_event_object(sangoma_wait_obj_t *sng_wait_o
|
|||
|
||||
DBG_EVNT("%s(): interface name: %s\n", __FUNCTION__, tdm_api_cmd.data);
|
||||
|
||||
if(flags_in & POLLIN){
|
||||
event_index = LIBSNG_EVENT_INDEX_POLLIN;
|
||||
/* Form the Event Name from Interface Name and Event Type (i.e. wanpipe1_if1_pollin). */
|
||||
_snprintf(tmp_event_name, sizeof(tmp_event_name), "%s_pollin", tdm_api_cmd.data);
|
||||
}
|
||||
|
||||
if(flags_in & POLLOUT){
|
||||
event_index = LIBSNG_EVENT_INDEX_POLLOUT;
|
||||
/* Form the Event Name from Interface Name and Event Type (i.e. wanpipe1_if1_pollout). */
|
||||
_snprintf(tmp_event_name, sizeof(tmp_event_name), "%s_pollout", tdm_api_cmd.data);
|
||||
}
|
||||
|
||||
if(flags_in & POLLPRI){
|
||||
event_index = LIBSNG_EVENT_INDEX_POLLPRI;
|
||||
/* Form the Event Name from Interface Name and Event Type (i.e. wanpipe1_if1_pollpri). */
|
||||
_snprintf(tmp_event_name, sizeof(tmp_event_name), "%s_pollpri", tdm_api_cmd.data);
|
||||
}
|
||||
|
||||
if(event_index == -1){
|
||||
/* invalid 'flags_in', this should be an assert */
|
||||
return SANG_STATUS_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
/* 1. The Sangoma Device Driver creates Notification Events in "\\BaseNamedObjects\\Global\\"
|
||||
* when first CreateFile() was called by a process. That means the Events will inherit
|
||||
* the security attributes of the calling process, so the calling process will have
|
||||
* the permissions to open the Events by calling OpenEvent(). Since Events are created
|
||||
* "Global" subdirectory, the calling process does NOT need Administrator priveleges.
|
||||
* The example name of the signaling object is: \\BaseNamedObjects\\Global\\wanpipe1_if1_signal.
|
||||
* 2. The Events are deleted when the last HANDLE for a device is closed by CloseHandle()
|
||||
* or automatically by the system when calling process exits. */
|
||||
_snprintf(event_name, sizeof(event_name), "Global\\%s", tmp_event_name);
|
||||
_snprintf(event_name, sizeof(event_name), "Global\\%s_signal", tdm_api_cmd.data);
|
||||
|
||||
sng_wait_obj->sng_event_objects[event_index] = OpenEvent(EVENT_ALL_ACCESS, TRUE, event_name);
|
||||
if(NULL == sng_wait_obj->sng_event_objects[event_index]){
|
||||
sng_wait_obj->signal_object = OpenEvent(EVENT_ALL_ACCESS, TRUE, event_name);
|
||||
if(NULL == sng_wait_obj->signal_object){
|
||||
/* error */
|
||||
LibSangomaDecodeLastError(__FUNCTION__);
|
||||
return SANG_STATUS_GENERAL_ERROR;
|
||||
|
@ -376,7 +353,7 @@ static sangoma_status_t sangoma_wait_obj_poll(sangoma_wait_obj_t *sangoma_wait_o
|
|||
|
||||
*flags_out = 0;
|
||||
|
||||
memset(&api_poll, 0x00, sizeof(API_POLL_STRUCT));
|
||||
memset(&api_poll, 0x00, sizeof(api_poll));
|
||||
api_poll.user_flags_bitmap = flags_in;
|
||||
|
||||
/* This call is non-blocking - it will return immediatly. */
|
||||
|
@ -399,13 +376,20 @@ static sangoma_status_t sangoma_wait_obj_poll(sangoma_wait_obj_t *sangoma_wait_o
|
|||
return err;
|
||||
}
|
||||
|
||||
static int check_number_of_wait_objects(uint32_t number_of_objects, const char *caller_function, int lineno)
|
||||
static int sangoma_check_number_of_wait_objects(uint32_t number_of_objects)
|
||||
{
|
||||
if(number_of_objects >= MAXIMUM_WAIT_OBJECTS){
|
||||
DBG_ERR("Caller: %s(): Line: %d: 'number_of_objects': %d is greater than the Maximum of: %d\n",
|
||||
caller_function, lineno, number_of_objects, MAXIMUM_WAIT_OBJECTS);
|
||||
if(number_of_objects > MAXIMUM_WAIT_OBJECTS){
|
||||
DBG_ERR("'number_of_objects': %d is greater than the Maximum of: %d\n",
|
||||
number_of_objects, MAXIMUM_WAIT_OBJECTS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(number_of_objects < 1){
|
||||
DBG_ERR("'number_of_objects': %d is less than the Minimum of: 1\n",
|
||||
number_of_objects);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -425,42 +409,36 @@ static sangoma_status_t get_out_flags(IN sangoma_wait_obj_t *sng_wait_objects[],
|
|||
|
||||
sangoma_wait_obj_t *sangoma_wait_object = sng_wait_objects[i];
|
||||
|
||||
if (!sangoma_wait_object->signal_object) {
|
||||
return SANG_STATUS_DEV_INIT_INCOMPLETE;
|
||||
}
|
||||
|
||||
if (!SANGOMA_OBJ_HAS_DEVICE(sangoma_wait_object)) {
|
||||
|
||||
/* This object does not has a device, but, may have been signaled via sangoma_wait_obj_signal()
|
||||
* test if the object is signaled, if it is, set SANG_WAIT_OBJ_IS_SIGNALED */
|
||||
|
||||
if((i == first_signaled_obj_index) || (WaitForSingleObject(sangoma_wait_object->generic_event_object, 0) == WAIT_OBJECT_0)) {
|
||||
/* !+! jpboily : Since WaitForMultipleObjects cleared the status
|
||||
* of the first signaled object, we make sure that the out_flag
|
||||
* for this object is set */
|
||||
if((i == first_signaled_obj_index) || /* !+! jpboily : Since WaitForMultipleObjects cleared the status
|
||||
* of the FIRST signaled object, we make sure that the out_flag
|
||||
* for this object is set.
|
||||
* !+! davidr: Status of all OTHER objects will be checked
|
||||
* by WaitForSingleObject(). */
|
||||
(WaitForSingleObject(sangoma_wait_object->signal_object, 0) == WAIT_OBJECT_0)) {
|
||||
out_flags[i] |= SANG_WAIT_OBJ_IS_SIGNALED;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
for(j = 0; j < LIBSNG_NUMBER_OF_EVENT_OBJECTS; j++){
|
||||
if(sangoma_wait_obj_poll(sangoma_wait_object, in_flags[i], &out_flags[i])){
|
||||
return SANG_STATUS_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
if(!sangoma_wait_object->sng_event_objects[j]) {
|
||||
continue;
|
||||
if (out_flags[i] & in_flags[i]) {
|
||||
if (at_least_one_poll_set_flags_out) {
|
||||
*at_least_one_poll_set_flags_out = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if(sangoma_wait_obj_poll(sangoma_wait_object, in_flags[i], &out_flags[i])){
|
||||
return SANG_STATUS_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
if( out_flags[i] & in_flags[i] ){
|
||||
if(at_least_one_poll_set_flags_out){
|
||||
*at_least_one_poll_set_flags_out = TRUE;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
/* Check if a device-related object was signalled, if it is, set SANG_WAIT_OBJ_IS_SIGNALED. */
|
||||
if (WaitForSingleObject(sangoma_wait_object->sng_event_objects[j], 0) == WAIT_OBJECT_0) {
|
||||
out_flags[i] |= SANG_WAIT_OBJ_IS_SIGNALED;
|
||||
}
|
||||
#endif
|
||||
}/* for(j = 0; j < LIBSNG_NUMBER_OF_EVENT_OBJECTS; j++) */
|
||||
}/* for(i = 0; i < number_of_sangoma_wait_objects; i++) */
|
||||
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
@ -1255,7 +1233,7 @@ sangoma_status_t _LIBSNG_CALL sangoma_wait_obj_create(sangoma_wait_obj_t **sango
|
|||
sangoma_wait_obj_t *sng_wait_obj = NULL;
|
||||
|
||||
if (!sangoma_wait_object) {
|
||||
return SANG_STATUS_INVALID_DEVICE;
|
||||
return SANG_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
*sangoma_wait_object = NULL;
|
||||
sng_wait_obj = malloc(sizeof(**sangoma_wait_object));
|
||||
|
@ -1271,40 +1249,19 @@ sangoma_status_t _LIBSNG_CALL sangoma_wait_obj_create(sangoma_wait_obj_t **sango
|
|||
sng_wait_obj->object_type = object_type;
|
||||
|
||||
#if defined(__WINDOWS__)
|
||||
DBG_INIT("%s(): sng_wait_obj ptr: 0x%p\n", __FUNCTION__, sng_wait_obj);
|
||||
DBG_INIT("%s(): fd: 0x%X, object_type: %s\n", __FUNCTION__, fd, DECODE_SANGOMA_WAIT_OBJECT_TYPE(object_type));
|
||||
DBG_INIT("%s(): sizeof(**sangoma_wait_object): %d\n", __FUNCTION__, sizeof(**sangoma_wait_object));
|
||||
|
||||
if (SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) {
|
||||
sng_wait_obj->generic_event_object = CreateEvent( NULL, FALSE, FALSE, NULL);
|
||||
if(!sng_wait_obj->generic_event_object){
|
||||
if (!SANGOMA_OBJ_HAS_DEVICE(sng_wait_obj)) {
|
||||
sng_wait_obj->signal_object = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if(!sng_wait_obj->signal_object){
|
||||
err = SANG_STATUS_GENERAL_ERROR;
|
||||
goto failed;
|
||||
}
|
||||
err = SANG_STATUS_SUCCESS;
|
||||
} else {
|
||||
err = init_sangoma_event_object(sng_wait_obj, fd);
|
||||
if(SANG_STATUS_SUCCESS != err){
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
if(SANGOMA_GENERIC_WAIT_OBJ == object_type){
|
||||
/* everything is done for the generic wait object */
|
||||
*sangoma_wait_object = sng_wait_obj;
|
||||
return SANG_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
err = init_sangoma_event_object(sng_wait_obj, POLLIN, fd);
|
||||
if(SANG_STATUS_SUCCESS != err){
|
||||
goto failed;
|
||||
}
|
||||
|
||||
err = init_sangoma_event_object(sng_wait_obj, POLLOUT, fd);
|
||||
if(SANG_STATUS_SUCCESS != err){
|
||||
goto failed;
|
||||
}
|
||||
|
||||
err = init_sangoma_event_object(sng_wait_obj, POLLPRI, fd);
|
||||
if(SANG_STATUS_SUCCESS != err) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
DBG_INIT("%s(): returning: %d", __FUNCTION__, err);
|
||||
#else
|
||||
int filedes[2];
|
||||
if (SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) {
|
||||
|
@ -1338,9 +1295,6 @@ failed:
|
|||
sangoma_status_t _LIBSNG_CALL sangoma_wait_obj_delete(sangoma_wait_obj_t **sangoma_wait_object)
|
||||
{
|
||||
sangoma_wait_obj_t *sng_wait_obj = *sangoma_wait_object;
|
||||
#if defined(__WINDOWS__)
|
||||
int index = 0;
|
||||
#endif
|
||||
|
||||
if(sng_wait_obj->init_flag != LIBSNG_MAGIC_NO){
|
||||
/* error. object was not initialized by sangoma_wait_obj_init() */
|
||||
|
@ -1348,13 +1302,9 @@ sangoma_status_t _LIBSNG_CALL sangoma_wait_obj_delete(sangoma_wait_obj_t **sango
|
|||
}
|
||||
|
||||
#if defined(__WINDOWS__)
|
||||
if (SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) {
|
||||
sangoma_close(&sng_wait_obj->generic_event_object);
|
||||
}
|
||||
if (SANGOMA_OBJ_HAS_DEVICE(sng_wait_obj)) {
|
||||
for(index = 0; index < LIBSNG_NUMBER_OF_EVENT_OBJECTS; index++){
|
||||
sangoma_close(&sng_wait_obj->sng_event_objects[index]);
|
||||
}
|
||||
if (sng_wait_obj->signal_object &&
|
||||
sng_wait_obj->signal_object != INVALID_HANDLE_VALUE) {
|
||||
sangoma_close(&sng_wait_obj->signal_object);
|
||||
}
|
||||
#else
|
||||
if (SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) {
|
||||
|
@ -1380,13 +1330,12 @@ int _LIBSNG_CALL sangoma_wait_obj_signal(sangoma_wait_obj_t *sng_wait_obj)
|
|||
if (!SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) {
|
||||
/* even when Windows objects are always signalable for the sake of providing
|
||||
* a consistent interface to the user we downgrade the capabilities of Windows
|
||||
* objects unless the sangoma wait object is explicitly initialized as signalable
|
||||
* */
|
||||
* objects unless the sangoma wait object is explicitly initialized as signalable */
|
||||
return SANG_STATUS_INVALID_DEVICE;
|
||||
}
|
||||
#if defined(__WINDOWS__)
|
||||
if(sng_wait_obj->generic_event_object){
|
||||
if (!SetEvent(sng_wait_obj->generic_event_object)) {
|
||||
if(sng_wait_obj->signal_object){
|
||||
if (!SetEvent(sng_wait_obj->signal_object)) {
|
||||
return SANG_STATUS_GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
@ -1449,58 +1398,44 @@ sangoma_status_t _LIBSNG_CALL sangoma_waitfor_many(sangoma_wait_obj_t *sng_wait_
|
|||
{
|
||||
#if defined(__WINDOWS__)
|
||||
HANDLE hEvents[MAXIMUM_WAIT_OBJECTS];
|
||||
uint32_t uiMapEventIndexToWaitObjectIndex[MAXIMUM_WAIT_OBJECTS];
|
||||
DWORD dwResult;
|
||||
int at_least_one_poll_set_flags_out, number_of_internal_signaling_objects, err;
|
||||
int at_least_one_poll_set_flags_out, err;
|
||||
sangoma_wait_obj_t *sangoma_wait_object;
|
||||
#endif
|
||||
uint32_t i = 0, j = 0;
|
||||
|
||||
memset(out_flags, 0x00, number_of_sangoma_wait_objects * sizeof(out_flags[0]));
|
||||
#if defined(__WINDOWS__)
|
||||
/* This loop will calculate 'number_of_internal_signaling_objects' and will initialize 'hEvents'
|
||||
* based on 'number_of_sangoma_wait_objects' and 'in_flags'. */
|
||||
number_of_internal_signaling_objects = 0;
|
||||
for(i = 0; i < number_of_sangoma_wait_objects; i++){
|
||||
sangoma_wait_obj_t *sangoma_wait_object = sng_wait_objects[i];
|
||||
|
||||
/* if SANGOMA_OBJ_IS_SIGNALABLE add the generic_event_object.hEvent to the hEvents */
|
||||
if(sangoma_wait_object->generic_event_object){
|
||||
if(check_number_of_wait_objects(number_of_internal_signaling_objects, __FUNCTION__, __LINE__)){
|
||||
return SANG_STATUS_NO_FREE_BUFFERS;
|
||||
}
|
||||
hEvents[number_of_internal_signaling_objects] = sangoma_wait_object->generic_event_object;
|
||||
uiMapEventIndexToWaitObjectIndex[number_of_internal_signaling_objects] = i;
|
||||
number_of_internal_signaling_objects++;
|
||||
}
|
||||
|
||||
for(j = 0; j < LIBSNG_NUMBER_OF_EVENT_OBJECTS; j++){
|
||||
if(sangoma_wait_object->sng_event_objects[j]){
|
||||
if( ((j == LIBSNG_EVENT_INDEX_POLLIN) && (in_flags[i] & POLLIN)) ||
|
||||
((j == LIBSNG_EVENT_INDEX_POLLOUT) && (in_flags[i] & POLLOUT)) ||
|
||||
((j == LIBSNG_EVENT_INDEX_POLLPRI) && (in_flags[i] & POLLPRI)) ){
|
||||
|
||||
if(check_number_of_wait_objects(number_of_internal_signaling_objects, __FUNCTION__, __LINE__)){
|
||||
return SANG_STATUS_NO_FREE_BUFFERS;
|
||||
}
|
||||
hEvents[number_of_internal_signaling_objects] = sangoma_wait_object->sng_event_objects[j];
|
||||
uiMapEventIndexToWaitObjectIndex[number_of_internal_signaling_objects] = i;
|
||||
number_of_internal_signaling_objects++;
|
||||
}
|
||||
}/* if () */
|
||||
}/* for() */
|
||||
}/* for() */
|
||||
|
||||
if(number_of_internal_signaling_objects < 1){
|
||||
DBG_ERR("'number_of_internal_signaling_objects': %d is less than the Minimum of: 1!\n",
|
||||
number_of_internal_signaling_objects);
|
||||
if(sangoma_check_number_of_wait_objects(number_of_sangoma_wait_objects)){
|
||||
/* error - most likely the user did not initialize sng_wait_objects[] */
|
||||
return SANG_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
for(i = 0; i < MAXIMUM_WAIT_OBJECTS; i++){
|
||||
hEvents[i] = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
/* This loop will initialize 'hEvents[]' based on
|
||||
* 'number_of_sangoma_wait_objects' and sng_wait_objects[]. */
|
||||
for(i = 0; i < number_of_sangoma_wait_objects; i++){
|
||||
|
||||
sangoma_wait_object = sng_wait_objects[i];
|
||||
|
||||
if(LIBSNG_MAGIC_NO != sangoma_wait_object->init_flag){
|
||||
return SANG_STATUS_DEV_INIT_INCOMPLETE;
|
||||
}
|
||||
|
||||
if(sangoma_wait_object->signal_object){
|
||||
hEvents[i] = sangoma_wait_object->signal_object;
|
||||
}
|
||||
|
||||
}/* for() */
|
||||
|
||||
at_least_one_poll_set_flags_out = FALSE;
|
||||
|
||||
/* It is important to get 'out flags' BEFORE the WaitForMultipleObjects()
|
||||
* because it allows to keep API driver's transmit queue full. */
|
||||
* because it allows to keep API driver's TRANSMIT queue full. */
|
||||
err = get_out_flags(sng_wait_objects, INVALID_INDEX, in_flags, out_flags, number_of_sangoma_wait_objects, &at_least_one_poll_set_flags_out);
|
||||
if(SANG_ERROR(err)){
|
||||
return err;
|
||||
|
@ -1511,19 +1446,19 @@ sangoma_status_t _LIBSNG_CALL sangoma_waitfor_many(sangoma_wait_obj_t *sng_wait_
|
|||
}
|
||||
|
||||
/* wait untill at least one of the events is signaled OR a 'system_wait_timeout' occured */
|
||||
dwResult = WaitForMultipleObjects(number_of_internal_signaling_objects, &hEvents[0], FALSE, system_wait_timeout);
|
||||
dwResult = WaitForMultipleObjects(number_of_sangoma_wait_objects, &hEvents[0], FALSE, system_wait_timeout);
|
||||
if (WAIT_TIMEOUT == dwResult){
|
||||
return SANG_STATUS_APIPOLL_TIMEOUT;
|
||||
}
|
||||
|
||||
if( dwResult >= (DWORD)number_of_internal_signaling_objects ) {
|
||||
if( dwResult >= (DWORD)number_of_sangoma_wait_objects ) {
|
||||
return SANG_STATUS_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
/* WaitForMultipleObjects() was waken by a Sangoma or by a non-Sangoma wait object. */
|
||||
err = get_out_flags(sng_wait_objects,
|
||||
uiMapEventIndexToWaitObjectIndex[dwResult],/* This is the index of first signaled object in
|
||||
* the original sng_wait_objects[] array, not in hEvents[] array. */
|
||||
dwResult, /* Array index of the signalled object with the smallest index
|
||||
* value of all the signalled objects, from array. */
|
||||
in_flags, out_flags, number_of_sangoma_wait_objects, NULL);
|
||||
if(SANG_ERROR(err)){
|
||||
return err;
|
||||
|
@ -1681,14 +1616,25 @@ int _LIBSNG_CALL sangoma_span_chan_fromif(char *interface_name, int *span, int *
|
|||
int ret = 0;
|
||||
char data[FNAME_LEN];
|
||||
|
||||
/* Windows: Accept WANPIPEx_IFy or wanpipex_ify
|
||||
* where x is the span and y is the chan. */
|
||||
|
||||
strncpy(data, interface_name, FNAME_LEN);
|
||||
if ((data[0])) {
|
||||
for (p = data; *p; p++) {
|
||||
#if defined(__WINDOWS__)
|
||||
if (sp && (*p == 'F'||*p == 'f')) {
|
||||
#else
|
||||
if (sp && *p == 'c') {
|
||||
#endif
|
||||
*p = '\0';
|
||||
ch = (p + 1);
|
||||
break;
|
||||
#if defined(__WINDOWS__)
|
||||
} else if (*p == 'E'||*p == 'e') {
|
||||
#else
|
||||
} else if (*p == 's') {
|
||||
#endif
|
||||
sp = (p + 1);
|
||||
}
|
||||
}
|
||||
|
@ -1791,6 +1737,7 @@ int _LIBSNG_CALL sangoma_get_open_cnt(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_OPEN_CNT;
|
||||
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -1897,8 +1844,11 @@ int _LIBSNG_CALL sangoma_readmsg(sng_fd_t fd, void *hdrbuf, int hdrlen, void *da
|
|||
rx_hdr->operation_status = SANG_STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
break;
|
||||
case SANG_STATUS_NO_DATA_AVAILABLE:
|
||||
/* Note that SANG_STATUS_NO_DATA_AVAILABLE is NOT an error becase
|
||||
* read() is non-blocking and can be called at any time (by some polling code)*/
|
||||
return 1; /* return positive value to indicate success, user must check 'rx_hdr->operation_status' */
|
||||
default:
|
||||
/* note that SANG_STATUS_NO_DATA_AVAILABLE is NOT an error! */
|
||||
if(libsng_dbg_level)DBG_ERR("Operation Status: %s(%d)\n",
|
||||
SDLA_DECODE_SANG_STATUS(rx_hdr->operation_status), rx_hdr->operation_status);
|
||||
return -5;
|
||||
|
@ -2039,6 +1989,7 @@ int _LIBSNG_CALL sangoma_get_full_cfg(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_FULL_CFG;
|
||||
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2092,6 +2043,7 @@ int _LIBSNG_CALL sangoma_get_full_cfg(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_tdm_set_codec(sng_fd_t fd, wanpipe_api_t *tdm_api, int codec)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_CODEC;
|
||||
tdm_api->wp_cmd.tdm_codec = codec;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2114,6 +2066,7 @@ int _LIBSNG_CALL sangoma_tdm_get_codec(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_CODEC;
|
||||
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2134,6 +2087,7 @@ int _LIBSNG_CALL sangoma_tdm_get_codec(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_tdm_set_usr_period(sng_fd_t fd, wanpipe_api_t *tdm_api, int period)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_USR_PERIOD;
|
||||
tdm_api->wp_cmd.usr_period = period;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2151,6 +2105,7 @@ int _LIBSNG_CALL sangoma_tdm_get_usr_period(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_USR_PERIOD;
|
||||
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2172,6 +2127,7 @@ int _LIBSNG_CALL sangoma_get_hw_coding(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_CODING;
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
if (err){
|
||||
|
@ -2192,6 +2148,7 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_dtmf(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_DTMF;
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
if (err){
|
||||
|
@ -2201,9 +2158,9 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_dtmf(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
}
|
||||
|
||||
/*========================================================
|
||||
* GET Current User Hardware EC Enabled/Disabled
|
||||
* GET status of echo canceler chip.
|
||||
*
|
||||
* Will return true if HW EC is enabled
|
||||
* Will return true if HW EC is available
|
||||
*/
|
||||
|
||||
int _LIBSNG_CALL sangoma_tdm_get_hw_ec(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
|
@ -2211,6 +2168,7 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_ec(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_EC;
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
if (err){
|
||||
|
@ -2220,6 +2178,31 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_ec(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef WP_API_FEATURE_EC_CHAN_STAT
|
||||
/*========================================================
|
||||
* GET status of the echo canceler for current channel.
|
||||
*
|
||||
* Will return true if HW EC is enabled
|
||||
*/
|
||||
|
||||
int _LIBSNG_CALL sangoma_tdm_get_hwec_chan_status(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_EC_CHAN;
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
if (err){
|
||||
return err;
|
||||
}
|
||||
return tdm_api->wp_cmd.hw_ec;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*========================================================
|
||||
* GET Current User MTU/MRU values in bytes.
|
||||
*
|
||||
|
@ -2231,6 +2214,7 @@ int _LIBSNG_CALL sangoma_tdm_get_usr_mtu_mru(sng_fd_t fd, wanpipe_api_t *tdm_api
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_USR_MTU_MRU;
|
||||
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2250,6 +2234,7 @@ int _LIBSNG_CALL sangoma_tdm_get_usr_mtu_mru(sng_fd_t fd, wanpipe_api_t *tdm_api
|
|||
int _LIBSNG_CALL sangoma_tdm_set_power_level(sng_fd_t fd, wanpipe_api_t *tdm_api, int power)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_POWER_LEVEL;
|
||||
tdm_api->wp_cmd.power_level = power;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2266,6 +2251,7 @@ int _LIBSNG_CALL sangoma_tdm_get_power_level(sng_fd_t fd, wanpipe_api_t *tdm_api
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_POWER_LEVEL;
|
||||
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2279,6 +2265,7 @@ int _LIBSNG_CALL sangoma_tdm_get_power_level(sng_fd_t fd, wanpipe_api_t *tdm_api
|
|||
int _LIBSNG_CALL sangoma_flush_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_FLUSH_BUFFERS;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
}
|
||||
|
@ -2286,6 +2273,7 @@ int _LIBSNG_CALL sangoma_flush_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_flush_rx_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_FLUSH_RX_BUFFERS;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
}
|
||||
|
@ -2293,6 +2281,7 @@ int _LIBSNG_CALL sangoma_flush_rx_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_flush_tx_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_FLUSH_TX_BUFFERS;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
}
|
||||
|
@ -2300,6 +2289,7 @@ int _LIBSNG_CALL sangoma_flush_tx_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_flush_event_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_FLUSH_EVENT_BUFFERS;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
}
|
||||
|
@ -2307,6 +2297,7 @@ int _LIBSNG_CALL sangoma_flush_event_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_tdm_enable_rbs_events(sng_fd_t fd, wanpipe_api_t *tdm_api, int poll_in_sec)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_ENABLE_RBS_EVENTS;
|
||||
tdm_api->wp_cmd.rbs_poll = poll_in_sec;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2315,6 +2306,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_rbs_events(sng_fd_t fd, wanpipe_api_t *tdm_a
|
|||
int _LIBSNG_CALL sangoma_tdm_disable_rbs_events(sng_fd_t fd, wanpipe_api_t *tdm_api) {
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_DISABLE_RBS_EVENTS;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
}
|
||||
|
@ -2322,6 +2314,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_rbs_events(sng_fd_t fd, wanpipe_api_t *tdm_
|
|||
int _LIBSNG_CALL sangoma_tdm_write_rbs(sng_fd_t fd, wanpipe_api_t *tdm_api, int channel, unsigned char rbs)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, channel);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_WRITE_RBS_BITS;
|
||||
tdm_api->wp_cmd.rbs_tx_bits=rbs;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2331,6 +2324,7 @@ int _LIBSNG_CALL sangoma_tdm_read_rbs(sng_fd_t fd, wanpipe_api_t *tdm_api, int c
|
|||
{
|
||||
int err;
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, channel);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_READ_RBS_BITS;
|
||||
tdm_api->wp_cmd.rbs_tx_bits=0;
|
||||
|
||||
|
@ -2341,7 +2335,29 @@ int _LIBSNG_CALL sangoma_tdm_read_rbs(sng_fd_t fd, wanpipe_api_t *tdm_api, int c
|
|||
|
||||
*rbs=(unsigned char)tdm_api->wp_cmd.rbs_rx_bits;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WP_API_FEATURE_BUFFER_MULT
|
||||
|
||||
int _LIBSNG_CALL sangoma_tdm_set_buffer_multiplier(sng_fd_t fd, wanpipe_api_t *tdm_api, unsigned int multiplier)
|
||||
{
|
||||
|
||||
int err;
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_BUFFER_MULTIPLIER;
|
||||
*((unsigned int*)&tdm_api->wp_cmd.data[0]) = multiplier;
|
||||
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
if (err){
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
int _LIBSNG_CALL sangoma_read_event(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
|
@ -2351,6 +2367,7 @@ int _LIBSNG_CALL sangoma_read_event(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_READ_EVENT;
|
||||
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2360,6 +2377,7 @@ int _LIBSNG_CALL sangoma_read_event(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
|
||||
rx_event = &tdm_api->wp_cmd.event;
|
||||
|
||||
#ifdef WP_API_DEPRECATED_FEATURE_READ_CALLBACK_FUNCTIONS
|
||||
/*
|
||||
The use of callbacks here is purely optional and is left
|
||||
here for backward compatibility purposes. By default user
|
||||
|
@ -2439,6 +2457,9 @@ int _LIBSNG_CALL sangoma_read_event(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
return 0;
|
||||
#else
|
||||
|
@ -2516,6 +2537,7 @@ sangoma_status_t _LIBSNG_CALL sangoma_logger_set_logger_level(sng_fd_t fd, wp_lo
|
|||
int _LIBSNG_CALL sangoma_tdm_enable_fax_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_FAX_DETECT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2525,6 +2547,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_fax_events(sng_fd_t fd, wanpipe_api_t *tdm_a
|
|||
int _LIBSNG_CALL sangoma_tdm_disable_fax_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_FAX_DETECT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
|
||||
|
@ -2535,6 +2558,7 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_fax(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
{
|
||||
int err;
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_FAX_DETECT;
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
if (err){
|
||||
|
@ -2548,6 +2572,7 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_fax(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_tdm_enable_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_DTMF;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2557,6 +2582,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_
|
|||
int _LIBSNG_CALL sangoma_tdm_disable_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_DTMF;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
|
||||
|
@ -2566,6 +2592,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm
|
|||
int _LIBSNG_CALL sangoma_tdm_enable_rm_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RM_DTMF;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2575,6 +2602,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_rm_dtmf_events(sng_fd_t fd, wanpipe_api_t *t
|
|||
int _LIBSNG_CALL sangoma_tdm_disable_rm_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RM_DTMF;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
|
||||
|
@ -2584,6 +2612,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_rm_dtmf_events(sng_fd_t fd, wanpipe_api_t *
|
|||
int _LIBSNG_CALL sangoma_tdm_enable_rxhook_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RXHOOK;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2593,6 +2622,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_rxhook_events(sng_fd_t fd, wanpipe_api_t *td
|
|||
int _LIBSNG_CALL sangoma_tdm_disable_rxhook_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RXHOOK;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
|
||||
|
@ -2602,6 +2632,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_rxhook_events(sng_fd_t fd, wanpipe_api_t *t
|
|||
int _LIBSNG_CALL sangoma_tdm_enable_ring_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2611,6 +2642,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_ring_events(sng_fd_t fd, wanpipe_api_t *tdm_
|
|||
int _LIBSNG_CALL sangoma_tdm_disable_ring_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
|
||||
|
@ -2620,6 +2652,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_ring_events(sng_fd_t fd, wanpipe_api_t *tdm
|
|||
int _LIBSNG_CALL sangoma_tdm_enable_ring_detect_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING_DETECT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2629,6 +2662,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_ring_detect_events(sng_fd_t fd, wanpipe_api_
|
|||
int _LIBSNG_CALL sangoma_tdm_disable_ring_detect_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING_DETECT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
|
||||
|
@ -2638,6 +2672,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_ring_detect_events(sng_fd_t fd, wanpipe_api
|
|||
int _LIBSNG_CALL sangoma_tdm_enable_ring_trip_detect_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING_TRIP_DETECT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2647,6 +2682,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_ring_trip_detect_events(sng_fd_t fd, wanpipe
|
|||
int _LIBSNG_CALL sangoma_tdm_disable_ring_trip_detect_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING_TRIP_DETECT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
|
||||
|
@ -2656,6 +2692,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_ring_trip_detect_events(sng_fd_t fd, wanpip
|
|||
int _LIBSNG_CALL sangoma_tdm_txsig_kewl(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TXSIG_KEWL;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2665,6 +2702,7 @@ int _LIBSNG_CALL sangoma_tdm_txsig_kewl(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_tdm_txsig_start(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TXSIG_START;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2674,6 +2712,7 @@ int _LIBSNG_CALL sangoma_tdm_txsig_start(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_tdm_txsig_onhook(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TXSIG_ONHOOK;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2683,6 +2722,7 @@ int _LIBSNG_CALL sangoma_tdm_txsig_onhook(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_tdm_txsig_offhook(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TXSIG_OFFHOOK;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2692,6 +2732,7 @@ int _LIBSNG_CALL sangoma_tdm_txsig_offhook(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_tdm_enable_tone_events(sng_fd_t fd, wanpipe_api_t *tdm_api, uint16_t tone_id)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TONE;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2702,6 +2743,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_tone_events(sng_fd_t fd, wanpipe_api_t *tdm_
|
|||
int _LIBSNG_CALL sangoma_tdm_disable_tone_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TONE;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
|
||||
|
@ -2713,6 +2755,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_tone_events(sng_fd_t fd, wanpipe_api_t *tdm
|
|||
int _LIBSNG_CALL sangoma_tdm_enable_hwec(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_ENABLE_HWEC;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
}
|
||||
|
@ -2720,6 +2763,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_hwec(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_tdm_disable_hwec(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_DISABLE_HWEC;
|
||||
return sangoma_cmd_exec(fd,tdm_api);
|
||||
}
|
||||
|
@ -2735,6 +2779,7 @@ int _LIBSNG_CALL sangoma_tdm_get_fe_alarms(sng_fd_t fd, wanpipe_api_t *tdm_api,
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_FE_ALARMS;
|
||||
|
||||
err=sangoma_cmd_exec(fd,tdm_api);
|
||||
|
@ -2753,6 +2798,7 @@ int _LIBSNG_CALL sangoma_get_fe_status(sng_fd_t fd, wanpipe_api_t *tdm_api, unsi
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_FE_STATUS;
|
||||
err = sangoma_cmd_exec(fd, tdm_api);
|
||||
*current_status = tdm_api->wp_cmd.fe_status;
|
||||
|
@ -2768,6 +2814,7 @@ int _LIBSNG_CALL sangoma_get_link_status(sng_fd_t fd, wanpipe_api_t *tdm_api, un
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_FE_STATUS;
|
||||
err = sangoma_cmd_exec(fd, tdm_api);
|
||||
*current_status = tdm_api->wp_cmd.fe_status;
|
||||
|
@ -2779,6 +2826,7 @@ int _LIBSNG_CALL sangoma_get_link_status(sng_fd_t fd, wanpipe_api_t *tdm_api, un
|
|||
int _LIBSNG_CALL sangoma_set_fe_status(sng_fd_t fd, wanpipe_api_t *tdm_api, unsigned char new_status)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_FE_STATUS;
|
||||
tdm_api->wp_cmd.fe_status = new_status;
|
||||
return sangoma_cmd_exec(fd, tdm_api);
|
||||
|
@ -2788,6 +2836,7 @@ int _LIBSNG_CALL sangoma_set_fe_status(sng_fd_t fd, wanpipe_api_t *tdm_api, unsi
|
|||
int _LIBSNG_CALL sangoma_disable_bri_bchan_loopback(sng_fd_t fd, wanpipe_api_t *tdm_api, int channel)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.channel = (unsigned char)channel;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_BRI_CHAN_LOOPBACK;
|
||||
|
@ -2798,6 +2847,7 @@ int _LIBSNG_CALL sangoma_disable_bri_bchan_loopback(sng_fd_t fd, wanpipe_api_t *
|
|||
int _LIBSNG_CALL sangoma_enable_bri_bchan_loopback(sng_fd_t fd, wanpipe_api_t *tdm_api, int channel)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.channel = (unsigned char)channel;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_BRI_CHAN_LOOPBACK;
|
||||
|
@ -2810,6 +2860,7 @@ int _LIBSNG_CALL sangoma_get_tx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_TX_Q_SIZE;
|
||||
tdm_api->wp_cmd.tx_queue_sz = 0;
|
||||
|
||||
|
@ -2827,6 +2878,7 @@ int _LIBSNG_CALL sangoma_set_tx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api, in
|
|||
return -1;
|
||||
}
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_TX_Q_SIZE;
|
||||
tdm_api->wp_cmd.tx_queue_sz = size;
|
||||
return sangoma_cmd_exec(fd, tdm_api);
|
||||
|
@ -2837,6 +2889,7 @@ int _LIBSNG_CALL sangoma_get_rx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_RX_Q_SIZE;
|
||||
tdm_api->wp_cmd.rx_queue_sz = 0;
|
||||
|
||||
|
@ -2856,6 +2909,7 @@ int _LIBSNG_CALL sangoma_set_rx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api, in
|
|||
}
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_RX_Q_SIZE;
|
||||
tdm_api->wp_cmd.rx_queue_sz = size;
|
||||
return sangoma_cmd_exec(fd, tdm_api);
|
||||
|
@ -2866,6 +2920,7 @@ int _LIBSNG_CALL sangoma_get_driver_version(sng_fd_t fd, wanpipe_api_t *tdm_api,
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_DRIVER_VERSION;
|
||||
|
||||
err = sangoma_cmd_exec(fd, tdm_api);
|
||||
|
@ -2887,6 +2942,7 @@ int _LIBSNG_CALL sangoma_get_firmware_version(sng_fd_t fd, wanpipe_api_t *tdm_ap
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_FIRMWARE_VERSION;
|
||||
|
||||
err = sangoma_cmd_exec(fd, tdm_api);
|
||||
|
@ -2906,6 +2962,7 @@ int _LIBSNG_CALL sangoma_get_cpld_version(sng_fd_t fd, wanpipe_api_t *tdm_api, u
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_CPLD_VERSION;
|
||||
|
||||
err = sangoma_cmd_exec(fd, tdm_api);
|
||||
|
@ -2925,6 +2982,7 @@ int _LIBSNG_CALL sangoma_get_stats(sng_fd_t fd, wanpipe_api_t *tdm_api, wanpipe_
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_STATS;
|
||||
|
||||
err = sangoma_cmd_exec(fd, tdm_api);
|
||||
|
@ -2940,6 +2998,7 @@ int _LIBSNG_CALL sangoma_get_stats(sng_fd_t fd, wanpipe_api_t *tdm_api, wanpipe_
|
|||
int _LIBSNG_CALL sangoma_flush_stats(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_RESET_STATS;
|
||||
return sangoma_cmd_exec(fd, tdm_api);
|
||||
}
|
||||
|
@ -2947,6 +3006,7 @@ int _LIBSNG_CALL sangoma_flush_stats(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int _LIBSNG_CALL sangoma_set_rm_rxflashtime(sng_fd_t fd, wanpipe_api_t *tdm_api, int rxflashtime)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_RM_RXFLASHTIME;
|
||||
tdm_api->wp_cmd.rxflashtime=rxflashtime;
|
||||
return sangoma_cmd_exec(fd, tdm_api);
|
||||
|
@ -2956,6 +3016,7 @@ int _LIBSNG_CALL sangoma_set_rm_rxflashtime(sng_fd_t fd, wanpipe_api_t *tdm_api,
|
|||
int _LIBSNG_CALL sangoma_set_rm_tx_gain(sng_fd_t fd, wanpipe_api_t *tdm_api, int value)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_SET_RM_TX_GAIN;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2966,6 +3027,7 @@ int _LIBSNG_CALL sangoma_set_rm_tx_gain(sng_fd_t fd, wanpipe_api_t *tdm_api, int
|
|||
int _LIBSNG_CALL sangoma_set_rm_rx_gain(sng_fd_t fd, wanpipe_api_t *tdm_api, int value)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_SET_RM_RX_GAIN;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -2979,6 +3041,7 @@ int _LIBSNG_CALL sangoma_tdm_set_polarity(sng_fd_t fd, wanpipe_api_t *tdm_api, i
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_SETPOLARITY;
|
||||
tdm_api->wp_cmd.event.wp_api_event_polarity = polarity;
|
||||
|
@ -2991,6 +3054,7 @@ int _LIBSNG_CALL sangoma_tdm_set_polarity(sng_fd_t fd, wanpipe_api_t *tdm_api, i
|
|||
int _LIBSNG_CALL sangoma_tdm_txsig_onhooktransfer(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
{
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
|
||||
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_ONHOOKTRANSFER;
|
||||
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
|
||||
|
@ -3004,6 +3068,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_loop(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_ENABLE_LOOP;
|
||||
err = sangoma_cmd_exec(fd, tdm_api);
|
||||
return err;
|
||||
|
@ -3014,6 +3079,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_loop(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
|||
int err;
|
||||
|
||||
WANPIPE_API_INIT_CHAN(tdm_api, 0);
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api);
|
||||
tdm_api->wp_cmd.cmd = WP_API_CMD_DISABLE_LOOP;
|
||||
err = sangoma_cmd_exec(fd, tdm_api);
|
||||
return err;
|
||||
|
@ -3139,6 +3205,7 @@ int _LIBSNG_CALL sangoma_mgmt_cmd(sng_fd_t fd, wan_udp_hdr_t* wan_udp)
|
|||
int _LIBSNG_CALL sangoma_driver_port_start(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no)
|
||||
{
|
||||
int err;
|
||||
port_mgmnt->operation_status = SANG_STATUS_GENERAL_ERROR;
|
||||
port_mgmnt->command_code = START_PORT_VOLATILE_CONFIG;
|
||||
port_mgmnt->port_no = port_no;
|
||||
|
||||
|
@ -3154,6 +3221,7 @@ int _LIBSNG_CALL sangoma_driver_port_start(sng_fd_t fd, port_management_struct_t
|
|||
int _LIBSNG_CALL sangoma_driver_port_stop(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no)
|
||||
{
|
||||
int err;
|
||||
port_mgmnt->operation_status = SANG_STATUS_GENERAL_ERROR;
|
||||
port_mgmnt->command_code = STOP_PORT;
|
||||
port_mgmnt->port_no = port_no;
|
||||
|
||||
|
@ -3182,6 +3250,7 @@ int _LIBSNG_CALL sangoma_driver_port_stop(sng_fd_t fd, port_management_struct_t
|
|||
int _LIBSNG_CALL sangoma_driver_get_hw_info(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no)
|
||||
{
|
||||
int err;
|
||||
port_mgmnt->operation_status = SANG_STATUS_GENERAL_ERROR;
|
||||
port_mgmnt->command_code = GET_HARDWARE_INFO;
|
||||
port_mgmnt->port_no = port_no;
|
||||
|
||||
|
@ -3193,8 +3262,23 @@ int _LIBSNG_CALL sangoma_driver_get_hw_info(sng_fd_t fd, port_management_struct_
|
|||
return port_mgmnt->operation_status;
|
||||
}
|
||||
|
||||
int _LIBSNG_CALL sangoma_driver_get_version(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no)
|
||||
{
|
||||
int err;
|
||||
port_mgmnt->command_code = GET_DRIVER_VERSION;
|
||||
port_mgmnt->port_no = port_no;
|
||||
|
||||
err = sangoma_port_mgmnt_ioctl(fd, port_mgmnt);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return port_mgmnt->operation_status;
|
||||
}
|
||||
|
||||
int _LIBSNG_CALL sangoma_driver_port_set_config(sng_fd_t fd, port_cfg_t *port_cfg, unsigned short port_no)
|
||||
{
|
||||
port_cfg->operation_status = SANG_STATUS_GENERAL_ERROR;
|
||||
port_cfg->command_code = SET_PORT_VOLATILE_CONFIG;
|
||||
port_cfg->port_no = port_no;
|
||||
|
||||
|
@ -3203,6 +3287,7 @@ int _LIBSNG_CALL sangoma_driver_port_set_config(sng_fd_t fd, port_cfg_t *port_cf
|
|||
|
||||
int _LIBSNG_CALL sangoma_driver_port_get_config(sng_fd_t fd, port_cfg_t *port_cfg, unsigned short port_no)
|
||||
{
|
||||
port_cfg->operation_status = SANG_STATUS_GENERAL_ERROR;
|
||||
port_cfg->command_code = GET_PORT_VOLATILE_CONFIG;
|
||||
port_cfg->port_no = port_no;
|
||||
return sangoma_port_cfg_ioctl(fd, port_cfg);
|
||||
|
|
|
@ -89,12 +89,19 @@ struct sangoma_wait_obj;
|
|||
\brief Instantiate/Declare a tdm api cmd strucure
|
||||
\def SANGOMA_INIT_TDM_API_CMD
|
||||
\brief Initialize the tdm api cmd structure. Set to 0.
|
||||
\def SANGOMA_INIT_TDM_API_CMD_RESULT
|
||||
\brief Initialize the 'result' in wanpipe_api_t to SANG_STATUS_GENERAL_ERROR.
|
||||
\def SANGOMA_DECLARE_INIT_TDM_API_CMD
|
||||
\brief Declare and initialize the tdm api cmd structure.
|
||||
*/
|
||||
#define SANGOMA_DECLARE_TDM_API_CMD(_name_) wanpipe_api_t _name_
|
||||
#define SANGOMA_INIT_TDM_API_CMD(_name_) memset(&_name_,0,sizeof(_name_))
|
||||
#define SANGOMA_DECLARE_INIT_TDM_API_CMD(_name_) wanpipe_tdm_api_t _name_; SANGOMA_INIT_TDM_API_CMD(_name_)
|
||||
|
||||
#define SANGOMA_INIT_TDM_API_CMD(_name_) memset(&_name_,0,sizeof(_name_)); \
|
||||
SANGOMA_INIT_TDM_API_CMD_RESULT(_name_)
|
||||
|
||||
#define SANGOMA_INIT_TDM_API_CMD_RESULT(_name_) (_name_).wp_cmd.result = SANG_STATUS_GENERAL_ERROR
|
||||
|
||||
#define SANGOMA_DECLARE_INIT_TDM_API_CMD(_name_) wanpipe_tdm_api_t _name_; SANGOMA_INIT_TDM_API_CMD(_name_);
|
||||
|
||||
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
|
@ -106,6 +113,7 @@ struct sangoma_wait_obj;
|
|||
#include <conio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
/*!
|
||||
\def _LIBSNG_CALL
|
||||
|
@ -114,8 +122,14 @@ struct sangoma_wait_obj;
|
|||
#ifdef __COMPILING_LIBSANGOMA__
|
||||
# define _LIBSNG_CALL __declspec(dllexport) __cdecl
|
||||
#else
|
||||
# define _LIBSNG_CALL __declspec(dllimport) __cdecl
|
||||
#endif
|
||||
# ifdef __LIBSANGOMA_IS_STATIC_LIB__
|
||||
/* libsangoma is static lib OR 'compiled in' */
|
||||
# define _LIBSNG_CALL __cdecl
|
||||
# else
|
||||
/* compiling an application which will use libsangoma.dll */
|
||||
# define _LIBSNG_CALL __declspec(dllimport) __cdecl
|
||||
# endif
|
||||
#endif /* __COMPILING_LIBSANGOMA__ */
|
||||
|
||||
/*!
|
||||
\def SANGOMA_INFINITE_API_POLL_WAIT (deprecated, use SANGOMA_WAIT_INFINITE instead)
|
||||
|
@ -251,10 +265,12 @@ typedef unsigned char * PUCHAR;
|
|||
typedef void * PVOID;
|
||||
typedef void * LPTHREAD_START_ROUTINE;
|
||||
typedef pthread_mutex_t CRITICAL_SECTION;
|
||||
typedef unsigned int UINT;
|
||||
|
||||
#define EnterCriticalSection(arg) pthread_mutex_lock(arg)
|
||||
#define TryEnterCriticalSection(arg) pthread_mutex_trylock(arg)
|
||||
#define LeaveCriticalSection(arg) pthread_mutex_unlock(arg)
|
||||
#define InitializeCriticalSection(arg) pthread_mutex_init(arg, NULL);
|
||||
#define InitializeCriticalSection(arg) pthread_mutex_init(arg, NULL);
|
||||
|
||||
typedef struct tm SYSTEMTIME;
|
||||
typedef char * LPCTSTR;
|
||||
|
@ -355,9 +371,9 @@ typedef enum _sangoma_wait_obj_type
|
|||
* Users are encouraged to use this flags instead of the system ones
|
||||
*/
|
||||
typedef enum _sangoma_wait_obj_flags {
|
||||
SANG_WAIT_OBJ_HAS_INPUT = POLLIN,
|
||||
SANG_WAIT_OBJ_HAS_OUTPUT = POLLOUT,
|
||||
SANG_WAIT_OBJ_HAS_EVENTS = POLLPRI,
|
||||
SANG_WAIT_OBJ_HAS_INPUT = WP_POLLIN,
|
||||
SANG_WAIT_OBJ_HAS_OUTPUT = WP_POLLOUT,
|
||||
SANG_WAIT_OBJ_HAS_EVENTS = WP_POLLPRI,
|
||||
SANG_WAIT_OBJ_IS_SIGNALED = 0x400 /* matches GNU extension POLLMSG */
|
||||
} sangoma_wait_obj_flags_t;
|
||||
|
||||
|
@ -1045,6 +1061,21 @@ int _LIBSNG_CALL sangoma_get_link_status(sng_fd_t fd, wanpipe_api_t *tdm_api, un
|
|||
int _LIBSNG_CALL sangoma_set_fe_status(sng_fd_t fd, wanpipe_api_t *tdm_api, unsigned char new_status);
|
||||
|
||||
|
||||
|
||||
#ifdef WP_API_FEATURE_BUFFER_MULT
|
||||
/*!
|
||||
\fn int sangoma_tdm_set_buffer_multiplier(sng_fd_t fd, wanpipe_api_t *tdm_api, unsigned int multiplier)
|
||||
\brief Set voice tx/rx buffer multiplier.
|
||||
\param fd device file descriptor
|
||||
\param tdm_api tdm api command structure
|
||||
\param multiplier buffer multiplier value 0-disable or 1 to TDMAPI_MAX_BUFFER_MULTIPLIER
|
||||
\return non-zero: error, 0: ok
|
||||
*/
|
||||
int _LIBSNG_CALL sangoma_tdm_set_buffer_multiplier(sng_fd_t fd, wanpipe_api_t *tdm_api, unsigned int multiplier);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
\fn int _LIBSNG_CALL sangoma_enable_bri_bchan_loopback(sng_fd_t fd, wanpipe_api_t *tdm_api, int channel)
|
||||
\brief Enable BRI Bchannel loopback - used when debugging bri device
|
||||
|
@ -1121,10 +1152,7 @@ int _LIBSNG_CALL sangoma_set_rx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api, in
|
|||
\brief Get HW Voice Coding (ulaw/alaw)
|
||||
\param fd device file descriptor
|
||||
\param tdm_api tdm api command structure
|
||||
\return non-zero: error, 0: ok
|
||||
|
||||
This function will return the low level voice coding
|
||||
depending on configuration. (ulaw or alaw)
|
||||
\return the low level voice coding, depending on configuration. (WP_MULAW or WP_ALAW)
|
||||
*/
|
||||
int _LIBSNG_CALL sangoma_get_hw_coding(sng_fd_t fd, wanpipe_api_t *tdm_api);
|
||||
|
||||
|
@ -1153,12 +1181,29 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_dtmf(sng_fd_t fd, wanpipe_api_t *tdm_api);
|
|||
\brief Check if hw echo cancelation support is available
|
||||
\param fd device file descriptor
|
||||
\param tdm_api tdm api command structure
|
||||
\return non-zero: error, 0: ok
|
||||
\return non-zero: error, 0: disable, >0:enabled
|
||||
|
||||
This function will check if hw supports HW EC.
|
||||
*/
|
||||
int _LIBSNG_CALL sangoma_tdm_get_hw_ec(sng_fd_t fd, wanpipe_api_t *tdm_api);
|
||||
|
||||
|
||||
#ifdef WP_API_FEATURE_EC_CHAN_STAT
|
||||
/*!
|
||||
\fn int sangoma_tdm_get_hwec_chan_status(sng_fd_t fd, wanpipe_api_t *tdm_api)
|
||||
\brief Check if hw echo cancelation is enabled on current timeslot
|
||||
\param fd device file descriptor
|
||||
\param tdm_api tdm api command structure
|
||||
\return non-zero: error, 0: disabled, >0: enabled
|
||||
|
||||
This function will check if hw echo cancelation is enable
|
||||
on current timeslot.
|
||||
*/
|
||||
|
||||
int _LIBSNG_CALL sangoma_tdm_get_hwec_chan_status(sng_fd_t fd, wanpipe_api_t *tdm_api);
|
||||
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\fn int sangoma_span_chan_toif(int span, int chan, char *interface_name)
|
||||
\brief Convert Span & Chan to interface name
|
||||
|
@ -1497,6 +1542,22 @@ int _LIBSNG_CALL sangoma_driver_port_get_config(sng_fd_t fd, port_cfg_t *port_cf
|
|||
int _LIBSNG_CALL sangoma_driver_get_hw_info(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no);
|
||||
|
||||
|
||||
/*!
|
||||
\fn int sangoma_driver_get_version(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no)
|
||||
\brief Retrieve Driver Version BEFORE any communication interface is configured and sangoma_get_driver_version()
|
||||
can not be called.
|
||||
\param[in] fd Port Device file descriptor
|
||||
\param[out] port_mgmnt pointer to port_management_struct_t structure which will contain wan_driver_version_t at
|
||||
it's "data" field, when this function returns.
|
||||
\param[in] port_no please see comment of sangoma_driver_port_set_config()
|
||||
\return non-zero: system error. Call OS specific code to find cause of the error.
|
||||
Linux example: strerror(errno)
|
||||
Windows example: combination of GetLastError()/FormatMessage()
|
||||
zero: no system error. Check port_mgmt->operation_status.
|
||||
*/
|
||||
int _LIBSNG_CALL sangoma_driver_get_version(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no);
|
||||
|
||||
|
||||
/*!
|
||||
\fn int sangoma_write_port_config_on_persistent_storage(hardware_info_t *hardware_info, port_cfg_t *port_cfg)
|
||||
\brief Write Port's configuration on the hard disk.
|
||||
|
@ -1635,18 +1696,34 @@ int _LIBSNG_CALL sangoma_tdm_get_power_level(sng_fd_t fd, wanpipe_api_t *tdm_api
|
|||
|
||||
|
||||
#ifdef WP_API_FEATURE_LIBSNG_HWEC
|
||||
/*!
|
||||
\fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name)
|
||||
|
||||
\brief Load Firmware image onto EC chip.
|
||||
/*!
|
||||
\fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name, wan_custom_param_t custom_params[], unsigned int number_of_custom_params)
|
||||
|
||||
\brief Load Firmware image onto EC chip. All chip-wide configuration paramters, if any,
|
||||
must be specified at the time of chip initialization.
|
||||
|
||||
\param device_name Sangoma API device name.
|
||||
Windows: wanpipe1_if1, wanpipe2_if1...
|
||||
Linux: wanpipe1, wanpipe2...
|
||||
|
||||
\param custom_params[] - (optional) array of custom paramter structures.
|
||||
|
||||
This is list of Echo Cancellation chip parameters:
|
||||
|
||||
Chip parameter Chip parameter value
|
||||
================= =======================
|
||||
WANEC_TailDisplacement 0-896
|
||||
WANEC_MaxPlayoutBuffers 0-4678
|
||||
WANEC_EnableExtToneDetection TRUE | FALSE
|
||||
WANEC_EnableAcousticEcho TRUE | FALSE
|
||||
|
||||
\param number_of_custom_params - (optional) number of structures in custom_params[]. Minimum value is 1, maximum is 4,
|
||||
if any other value the custom_params[] will be ignored.
|
||||
|
||||
\return SANG_STATUS_SUCCESS: success, or error status
|
||||
*/
|
||||
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name);
|
||||
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name, wan_custom_param_t custom_params[], unsigned int number_of_custom_params);
|
||||
|
||||
/*!
|
||||
\fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_release(char *device_name)
|
||||
|
@ -1769,9 +1846,16 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_enable(char *device_name, unsigned i
|
|||
sangoma_status_t _LIBSNG_CALL sangoma_hwec_disable(char *device_name, unsigned int fe_chan_map);
|
||||
|
||||
/*!
|
||||
\fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameters(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map)
|
||||
\fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameter(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map)
|
||||
|
||||
\brief Modify channel configuration parameters.
|
||||
|
||||
\param device_name Sangoma API device name.
|
||||
Windows: wanpipe1_if1, wanpipe2_if1...
|
||||
Linux: wanpipe1, wanpipe2...
|
||||
|
||||
\param parameter Echo Cancellation channel parameter
|
||||
|
||||
This is list of Echo Cancellation channel parameters:
|
||||
|
||||
Channel parameter Channel parameter value
|
||||
|
@ -1800,7 +1884,7 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_disable(char *device_name, unsigned i
|
|||
|
||||
\return SANG_STATUS_SUCCESS: success, or error status
|
||||
*/
|
||||
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameters(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map);
|
||||
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameter(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map);
|
||||
|
||||
/*!
|
||||
\fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_tone_detection(char *device_name, int tone_id, int enable, unsigned int fe_chan_map, unsigned char port_map)
|
||||
|
@ -1917,6 +2001,19 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_audio_buffer_playout(char *device_nam
|
|||
*/
|
||||
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_verbosity(int verbosity_level);
|
||||
|
||||
/*!
|
||||
\fn void _LIBSNG_CALL sangoma_hwec_initialize_custom_parameter_structure(wan_custom_param_t *custom_param, char *parameter_name, char *parameter_value)
|
||||
|
||||
\brief Initialize Custom Paramter structure.
|
||||
|
||||
\param parameter_name Parameter Name
|
||||
|
||||
\param parameter_value Parameter Value
|
||||
|
||||
\return None
|
||||
*/
|
||||
void _LIBSNG_CALL sangoma_hwec_initialize_custom_parameter_structure(wan_custom_param_t *custom_param, char *parameter_name, char *parameter_value);
|
||||
|
||||
#endif /* WP_API_FEATURE_LIBSNG_HWEC */
|
||||
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@
|
|||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=".;include\api;include\debug;include\octasic;include\pnp;..\libpri"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;__WINDOWS__;__COMPILING_LIBSANGOMA__;WANPIPE_TDM_API;_CRT_SECURE_NO_DEPRECATE;WP_API_FEATURE_DTMF_EVENTS;WP_API_FEATURE_EVENTS;WP_API_FEATURE_RM_GAIN;WP_API_FEATURE_LINK_STATUS;WP_API_FEATURE_FE_ALARM;WP_API_FEATURE_FAX_EVENTS;WP_API_FEATURE_LOGGER;WP_API_FEATURE_LIBSNG_HWEC"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;__WINDOWS__;__COMPILING_LIBSANGOMA__;WANPIPE_TDM_API;_CRT_SECURE_NO_DEPRECATE;WP_API_FEATURE_DTMF_EVENTS;WP_API_FEATURE_EVENTS;WP_API_FEATURE_RM_GAIN;WP_API_FEATURE_LINK_STATUS;WP_API_FEATURE_FE_ALARM;WP_API_FEATURE_FAX_EVENTS;WP_API_FEATURE_LOGGER;WP_API_FEATURE_LIBSNG_HWEC;WP_PREVENT_WINSOCK_NAME_CONFLICT"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
|
|
|
@ -44,12 +44,7 @@
|
|||
# pragma comment( lib, "waneclib" ) /* import functions from waneclib.dll */
|
||||
#endif/* __WINDOWS__) */
|
||||
|
||||
/* Fast sequence of commands to HWEC may cause the chip
|
||||
* enter fatal error state, the workaround is to have
|
||||
* a guaranteed delay after eache command. */
|
||||
#define HWEC_CMD_DELAY() wp_usleep(20000) /* 20ms */
|
||||
|
||||
static int libsng_hwec_verbosity_level = 0;
|
||||
static int libsng_hwec_verbosity_level = 0x00;
|
||||
|
||||
/************************************************************//**
|
||||
* Private Functions. (Not exported)
|
||||
|
@ -67,54 +62,145 @@ static sangoma_status_t sangoma_hwec_bypass(char *device_name, int enable, unsig
|
|||
|
||||
/* WAN_EC_API_CMD_HWEC_ENABLE/WAN_EC_API_CMD_HWEC_DISABLE - Controls the "bypass" mode.)*/
|
||||
rc = wanec_api_hwec(device_name, libsng_hwec_verbosity_level, &hwec);
|
||||
if( rc ) {
|
||||
return rc;
|
||||
}
|
||||
HWEC_CMD_DELAY();
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int sangoma_hwec_is_numeric_parameter(char *parameter)
|
||||
{
|
||||
int i;
|
||||
static char *WANEC_numeric_params[] = {
|
||||
"WANEC_TailDisplacement",
|
||||
"WANEC_MaxPlayoutBuffers",
|
||||
"WANEC_MaxConfBridges",
|
||||
"WANEC_EchoOperationMode",
|
||||
"WANEC_ComfortNoiseMode",
|
||||
"WANEC_NonLinearityBehaviorA",
|
||||
"WANEC_NonLinearityBehaviorB",
|
||||
"WANEC_DoubleTalkBehavior",
|
||||
"WANEC_RinLevelControlGainDb",
|
||||
"WANEC_SoutLevelControlGainDb",
|
||||
"WANEC_RinAutomaticLevelControlTargetDb",
|
||||
"WANEC_SoutAutomaticLevelControlTargetDb",
|
||||
"WANEC_RinHighLevelCompensationThresholdDb",
|
||||
"WANEC_AnrSnrEnhancementDb",
|
||||
NULL
|
||||
};
|
||||
|
||||
/************************************************************//**
|
||||
i = 0;
|
||||
while(WANEC_numeric_params[i]){
|
||||
if (!wp_strncasecmp(parameter, WANEC_numeric_params[i], strlen(parameter))) {
|
||||
return 1;/* this IS a numeric parameter */
|
||||
}
|
||||
i++;
|
||||
};
|
||||
|
||||
return 0;/* NOT a numeric parameter */
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
* Public Functions. (Exported)
|
||||
***************************************************************/
|
||||
|
||||
/*!
|
||||
\fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name)
|
||||
\fn void _LIBSNG_CALL sangoma_hwec_initialize_custom_parameter_structure(wan_custom_param_t *custom_param, char *parameter_name, char *parameter_value)
|
||||
|
||||
\brief Load Firmware image onto EC chip.
|
||||
\brief Initialize Custom Paramter structure.
|
||||
|
||||
\param parameter_name Parameter Name
|
||||
|
||||
\param parameter_value Parameter Value
|
||||
|
||||
\return None
|
||||
*/
|
||||
void _LIBSNG_CALL sangoma_hwec_initialize_custom_parameter_structure(wan_custom_param_t *custom_param, char *parameter_name, char *parameter_value)
|
||||
{
|
||||
memset(custom_param, 0x00, sizeof(*custom_param));
|
||||
|
||||
strncpy( custom_param->name, parameter_name, sizeof(custom_param->name) );
|
||||
|
||||
if (sangoma_hwec_is_numeric_parameter(parameter_name)) {
|
||||
custom_param->dValue = atoi(parameter_value);
|
||||
} else {
|
||||
strncpy(custom_param->sValue, parameter_value, sizeof(custom_param->sValue));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name, wan_custom_param_t custom_params[], unsigned int number_of_custom_params)
|
||||
|
||||
\brief Load Firmware image onto EC chip. All chip-wide configuration paramters, if any,
|
||||
must be specified at the time of chip initialization.
|
||||
|
||||
\param device_name Sangoma API device name.
|
||||
Windows: wanpipe1_if1, wanpipe2_if1...
|
||||
Linux: wanpipe1, wanpipe2...
|
||||
|
||||
\param custom_params[] - (optional) array of custom paramter structures.
|
||||
|
||||
This is list of Echo Cancellation chip parameters:
|
||||
|
||||
Chip parameter Chip parameter value
|
||||
================= =======================
|
||||
WANEC_TailDisplacement 0-896
|
||||
WANEC_MaxPlayoutBuffers 0-4678
|
||||
WANEC_EnableExtToneDetection TRUE | FALSE
|
||||
WANEC_EnableAcousticEcho TRUE | FALSE
|
||||
|
||||
\param number_of_custom_params - (optional) number of structures in custom_params[]. Minimum value is 1, maximum is 4,
|
||||
if any other value the custom_params[] will be ignored.
|
||||
|
||||
\return SANG_STATUS_SUCCESS: success, or error status
|
||||
*/
|
||||
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name)
|
||||
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name, wan_custom_param_t custom_params[], unsigned int number_of_custom_params)
|
||||
{
|
||||
sangoma_status_t rc;
|
||||
wan_custom_param_t custom_parms;
|
||||
sangoma_status_t rc = SANG_STATUS_SUCCESS;
|
||||
wanec_api_config_t config;
|
||||
|
||||
memset(&config, 0x00, sizeof(config));
|
||||
memset(&custom_parms, 0x0, sizeof(custom_parms));
|
||||
|
||||
#if 1
|
||||
/* enable acoustic echo cancellation by default */
|
||||
strcpy( custom_parms.name, "WANEC_EnableAcousticEcho" );
|
||||
strcpy( custom_parms.sValue, "TRUE" );
|
||||
|
||||
config.conf.param_no = 1;
|
||||
config.conf.params = &custom_parms;
|
||||
#endif
|
||||
if (number_of_custom_params >= 1 && number_of_custom_params <= 4) {
|
||||
|
||||
/* Load firmware on EC chip */
|
||||
wan_custom_param_t *custom_parms_ptr;
|
||||
unsigned int i, custom_params_memory_size;
|
||||
|
||||
custom_params_memory_size = sizeof(wan_custom_param_t) * number_of_custom_params;
|
||||
|
||||
/* Do NOT change memory at custom_params[] (it belongs to the caller).
|
||||
* Instead allocate temporary buffer, and use information in custom_params[]
|
||||
* for proper initialization the temproary buffer and
|
||||
* and send if down to API driver. */
|
||||
custom_parms_ptr = malloc(custom_params_memory_size);
|
||||
if (!custom_parms_ptr) {
|
||||
return SANG_STATUS_FAILED_ALLOCATE_MEMORY;
|
||||
}
|
||||
|
||||
memset(custom_parms_ptr, 0x00, custom_params_memory_size);
|
||||
|
||||
for (i = 0; i < number_of_custom_params; i++) {
|
||||
|
||||
strcpy( custom_parms_ptr[i].name, custom_params[i].name );
|
||||
|
||||
if (sangoma_hwec_is_numeric_parameter(custom_params[i].name)) {
|
||||
custom_parms_ptr[i].dValue = atoi(custom_params[i].sValue);
|
||||
} else {
|
||||
strcpy(custom_parms_ptr[i].sValue, custom_params[i].sValue);
|
||||
}
|
||||
} /* for() */
|
||||
|
||||
config.conf.param_no = number_of_custom_params;
|
||||
config.conf.params = custom_parms_ptr;
|
||||
|
||||
}/* if() */
|
||||
|
||||
/* Load firmware on EC chip AND apply configuration, if any. */
|
||||
rc = wanec_api_config( device_name, libsng_hwec_verbosity_level, &config );
|
||||
if( rc ) {
|
||||
return rc;
|
||||
|
||||
if (config.conf.params) {
|
||||
free(config.conf.params);
|
||||
}
|
||||
HWEC_CMD_DELAY();
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
@ -137,14 +223,10 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_release(char *device_name)
|
|||
memset(&release, 0, sizeof(wanec_api_release_t));
|
||||
|
||||
rc = wanec_api_release( device_name, libsng_hwec_verbosity_level, &release );
|
||||
if( rc ) {
|
||||
return rc;
|
||||
}
|
||||
HWEC_CMD_DELAY();
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Modify channel operation mode.
|
||||
*/
|
||||
|
@ -167,11 +249,8 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_operation_mode(char *device_na
|
|||
WANEC_API_OPMODE_SPEECH_RECOGNITION.
|
||||
*/
|
||||
rc = wanec_api_opmode(device_name, libsng_hwec_verbosity_level, &opmode);
|
||||
if( rc ) {
|
||||
return rc;
|
||||
}
|
||||
HWEC_CMD_DELAY();
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -229,7 +308,7 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_power_off(char *device_name,
|
|||
This command is recommened for fast enabling of Echo Cancellation.
|
||||
Note 1: Chip must be configured and in POWER ON state for echo
|
||||
Chancellation to take place.
|
||||
Note 2: sangoma_tdm_enable_hwec() function can be use to achive
|
||||
Note 2: sangoma_tdm_enable_hwec() function can be used to achive
|
||||
the same funcitnality based on file descriptor versus
|
||||
channel map.
|
||||
|
||||
|
@ -275,10 +354,17 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_disable(char *device_name, unsigned i
|
|||
}
|
||||
|
||||
/*!
|
||||
\fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameters(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map)
|
||||
\fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameter(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map)
|
||||
|
||||
\brief Modify channel configuration parameters.
|
||||
This is list of Echo Cancellation channel parameters:
|
||||
|
||||
\param device_name Sangoma API device name.
|
||||
Windows: wanpipe1_if1, wanpipe2_if1...
|
||||
Linux: wanpipe1, wanpipe2...
|
||||
|
||||
\param parameter Echo Cancellation channel parameter
|
||||
|
||||
This channel parameters are listed under "Channel parameter":
|
||||
|
||||
Channel parameter Channel parameter value
|
||||
================= =======================
|
||||
|
@ -301,33 +387,30 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_disable(char *device_name, unsigned i
|
|||
WANEC_DoubleTalkBehavior DT_BEH_NORMAL
|
||||
DT_BEH_LESS_AGGRESSIVE
|
||||
|
||||
\param parameter_value channel parameter value, listed under "Channel parameter value"
|
||||
|
||||
\param fe_chan_map Bitmap of channels (timeslots for Digital, lines for Analog) where
|
||||
the call will take effect.
|
||||
|
||||
\return SANG_STATUS_SUCCESS: success, or error status
|
||||
*/
|
||||
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameters(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map)
|
||||
sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameter(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map)
|
||||
{
|
||||
sangoma_status_t rc;
|
||||
wanec_api_modify_t channelModify;
|
||||
wan_custom_param_t aParms;
|
||||
wan_custom_param_t custom_param;
|
||||
|
||||
memset(&channelModify, 0x00, sizeof(channelModify));
|
||||
memset(&aParms, 0x00, sizeof(aParms));
|
||||
|
||||
sangoma_hwec_initialize_custom_parameter_structure(&custom_param, parameter, parameter_value);
|
||||
|
||||
channelModify.fe_chan_map = channel_map;
|
||||
channelModify.conf.param_no = 1;
|
||||
channelModify.conf.params = &aParms;
|
||||
|
||||
strcpy( aParms.name, parameter);
|
||||
strcpy( aParms.sValue, parameter_value);
|
||||
channelModify.conf.params = &custom_param;
|
||||
|
||||
rc = wanec_api_modify( device_name, libsng_hwec_verbosity_level, &channelModify );
|
||||
if( rc ){
|
||||
return rc;
|
||||
}
|
||||
HWEC_CMD_DELAY();
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -366,11 +449,8 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_tone_detection(char *device_na
|
|||
tone.type_map = WAN_EC_TONE_PRESENT | WAN_EC_TONE_STOP;
|
||||
|
||||
rc = wanec_api_tone( device_name, libsng_hwec_verbosity_level, &tone );
|
||||
if( rc ) {
|
||||
return rc;
|
||||
}
|
||||
HWEC_CMD_DELAY();
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -401,11 +481,8 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_print_statistics(char *device_name, i
|
|||
stats.reset = 0; /* do not reset */
|
||||
|
||||
rc = wanec_api_stats( device_name, libsng_hwec_verbosity_level, &stats );
|
||||
if( rc ) {
|
||||
return rc;
|
||||
}
|
||||
HWEC_CMD_DELAY();
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -443,7 +520,6 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_audio_buffer_load(char *device_name,
|
|||
|
||||
*out_buffer_id = bufferload.buffer_id;
|
||||
|
||||
HWEC_CMD_DELAY();
|
||||
return SANG_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -468,11 +544,8 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_audio_buffer_unload(char *device_name
|
|||
bufferunload.buffer_id = (unsigned int)in_buffer_id;
|
||||
|
||||
rc = wanec_api_buffer_unload( device_name, libsng_hwec_verbosity_level, &bufferunload);
|
||||
if( rc ) {
|
||||
return rc;
|
||||
}
|
||||
HWEC_CMD_DELAY();
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -518,18 +591,17 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_audio_buffer_playout(char *device_nam
|
|||
playout.duration = (duration) ? duration : 5000; /* default is 5s */
|
||||
|
||||
rc = wanec_api_playout( device_name, libsng_hwec_verbosity_level, &playout);
|
||||
if( rc ) {
|
||||
return rc;
|
||||
}
|
||||
HWEC_CMD_DELAY();
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn void _LIBSNG_CALL sangoma_hwec_config_verbosity(int verbosity_level)
|
||||
|
||||
\brief Set Verbosity level of EC API. The level controls amount of data
|
||||
printed to stdout and wanpipelog.txt for diagnostic purposes.
|
||||
\brief Set Verbosity level of EC API Driver and Library.
|
||||
The level controls amount of data
|
||||
printed to stdout and to wanpipelog.txt (Windows) or
|
||||
/var/log/messages (Linux) for diagnostic purposes.
|
||||
|
||||
\param verbosity_level Valid values are from 0 to 3.
|
||||
|
||||
|
@ -539,6 +611,7 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_verbosity(int verbosity_level)
|
|||
{
|
||||
if (verbosity_level >= 0 || verbosity_level <= 3) {
|
||||
libsng_hwec_verbosity_level = verbosity_level;
|
||||
wanec_api_set_lib_verbosity(verbosity_level);
|
||||
return SANG_STATUS_SUCCESS;
|
||||
}
|
||||
return SANG_STATUS_INVALID_PARAMETER;
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 43
|
||||
/svn/libsangoma/!svn/ver/248/trunk/sample_c
|
||||
/svn/libsangoma/!svn/ver/292/trunk/sample_c
|
||||
END
|
||||
lib_api.c
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 53
|
||||
/svn/libsangoma/!svn/ver/139/trunk/sample_c/lib_api.c
|
||||
/svn/libsangoma/!svn/ver/289/trunk/sample_c/lib_api.c
|
||||
END
|
||||
sample-doxygen.config
|
||||
K 25
|
||||
|
@ -19,7 +19,7 @@ sample.c
|
|||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 52
|
||||
/svn/libsangoma/!svn/ver/234/trunk/sample_c/sample.c
|
||||
/svn/libsangoma/!svn/ver/292/trunk/sample_c/sample.c
|
||||
END
|
||||
sources
|
||||
K 25
|
||||
|
@ -31,7 +31,7 @@ lib_api.h
|
|||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 53
|
||||
/svn/libsangoma/!svn/ver/139/trunk/sample_c/lib_api.h
|
||||
/svn/libsangoma/!svn/ver/289/trunk/sample_c/lib_api.h
|
||||
END
|
||||
Makefile.Linux
|
||||
K 25
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
8
|
||||
|
||||
dir
|
||||
273
|
||||
293
|
||||
https://www.sangomapbx.com/svn/libsangoma/trunk/sample_c
|
||||
https://www.sangomapbx.com/svn/libsangoma
|
||||
|
||||
|
||||
|
||||
2010-01-22T21:30:47.609627Z
|
||||
248
|
||||
davidr
|
||||
2010-06-17T18:02:18.733671Z
|
||||
292
|
||||
ncorbic
|
||||
has-props
|
||||
|
||||
svn:special svn:externals svn:needs-lock
|
||||
|
@ -32,10 +32,10 @@ file
|
|||
|
||||
|
||||
|
||||
2009-08-25T20:44:41.000000Z
|
||||
df0de3e86155c3e69e9d289a7d923f68
|
||||
2009-04-07T01:30:57.044470Z
|
||||
139
|
||||
2010-06-14T20:01:26.000000Z
|
||||
0d8197d3f408802760d39c2c5ef70299
|
||||
2010-06-15T00:59:38.715189Z
|
||||
289
|
||||
ncorbic
|
||||
|
||||
sample-doxygen.config
|
||||
|
@ -56,11 +56,11 @@ file
|
|||
|
||||
|
||||
|
||||
2009-12-04T21:21:35.000000Z
|
||||
17f4ef3cc598f84b869bbcc38d2e12aa
|
||||
2009-11-19T22:00:29.815332Z
|
||||
234
|
||||
davidr
|
||||
2010-06-17T18:13:17.000000Z
|
||||
c291876c4c6d01386787a8ca925c2363
|
||||
2010-06-17T18:02:18.733671Z
|
||||
292
|
||||
ncorbic
|
||||
|
||||
sources
|
||||
file
|
||||
|
@ -80,10 +80,10 @@ file
|
|||
|
||||
|
||||
|
||||
2009-08-25T20:44:41.000000Z
|
||||
80b2a1bced5f696771e5a92163a9967e
|
||||
2009-04-07T01:30:57.044470Z
|
||||
139
|
||||
2010-06-14T20:01:44.000000Z
|
||||
2226e4aee423aa808e5002b1c95e20eb
|
||||
2010-06-15T00:59:38.715189Z
|
||||
289
|
||||
ncorbic
|
||||
|
||||
Makefile.Linux
|
||||
|
|
|
@ -23,11 +23,12 @@
|
|||
char read_enable=0;
|
||||
char write_enable=0;
|
||||
char primary_enable=0;
|
||||
int tx_cnt=1;
|
||||
int rx_cnt=1;
|
||||
int tx_cnt=0;
|
||||
int rx_cnt=0;
|
||||
int tx_size=10;
|
||||
int tx_delay=0;
|
||||
int tx_data=-1;
|
||||
int buffer_multiplier=0;
|
||||
|
||||
unsigned char tx_file[WAN_IFNAME_SZ];
|
||||
unsigned char rx_file[WAN_IFNAME_SZ];
|
||||
|
@ -65,6 +66,7 @@ int rbs_events = 0;
|
|||
int rx2tx = 0;
|
||||
int flush_period=0;
|
||||
int stats_period=0;
|
||||
int hdlc_repeat=0;
|
||||
|
||||
unsigned long parse_active_channel(char* val);
|
||||
|
||||
|
@ -79,7 +81,7 @@ int init_args(int argc, char *argv[])
|
|||
|
||||
for (i = 0; i < argc; i++){
|
||||
|
||||
if (!strcmp(argv[i],"-i")){
|
||||
if (!strcmp(argv[i],"-i") || !strcmp(argv[i],"-chan")){
|
||||
|
||||
if (i+1 > argc-1){
|
||||
printf("ERROR: Number of Interfaces was NOT specified!\n");
|
||||
|
@ -87,7 +89,7 @@ int init_args(int argc, char *argv[])
|
|||
}
|
||||
wanpipe_if_no = atoi(argv[i+1]);
|
||||
|
||||
}else if (!strcmp(argv[i],"-p")){
|
||||
}else if (!strcmp(argv[i],"-p") || !strcmp(argv[i],"-span")){
|
||||
|
||||
if (i+1 > argc-1){
|
||||
printf("ERROR: Number of Ports was NOT specified!\n");
|
||||
|
@ -102,6 +104,8 @@ int init_args(int argc, char *argv[])
|
|||
}else if (!strcmp(argv[i],"-w")){
|
||||
write_enable=1;
|
||||
c_cnt=1;
|
||||
}else if (!strcmp(argv[i],"-hdlc_repeat")){
|
||||
hdlc_repeat=1;
|
||||
|
||||
}else if (!strcmp(argv[i],"-pri")){
|
||||
primary_enable=1;
|
||||
|
@ -219,6 +223,19 @@ int init_args(int argc, char *argv[])
|
|||
}else if (!strcmp(argv[i],"-verbose")){
|
||||
verbose=1;
|
||||
|
||||
}else if (!strcmp(argv[i],"-buffer_multiplier")) {
|
||||
if (i+1 > argc-1){
|
||||
printf("ERROR: Invalid prot!\n");
|
||||
return WAN_FALSE;
|
||||
}
|
||||
|
||||
if(isdigit(argv[i+1][0])){
|
||||
buffer_multiplier = atoi(argv[i+1]);
|
||||
}else{
|
||||
printf("ERROR: Invalid prot, must be a digit!\n");
|
||||
return WAN_FALSE;
|
||||
}
|
||||
|
||||
}else if (!strcmp(argv[i],"-prot")){
|
||||
if (i+1 > argc-1){
|
||||
printf("ERROR: Invalid prot!\n");
|
||||
|
@ -365,13 +382,13 @@ int init_args(int argc, char *argv[])
|
|||
static char api_usage[]="\n"
|
||||
"\n"
|
||||
"<options>:\n"
|
||||
" -p <port number> #port/span number\n"
|
||||
" -i <if number> #if/chan number\n"
|
||||
" -r #read enable\n"
|
||||
" -w #write eable\n"
|
||||
" -span <port/span number> #port/span number\n"
|
||||
" -chan <if/chan number> #if/chan number\n"
|
||||
" -r #read enable\n"
|
||||
" -w #write eable\n"
|
||||
"\n"
|
||||
" example 1: sangoma_c -p 1 -i 1 -r\n"
|
||||
" in this example Wanpipe 1, Interface 1 will be used for reading data\n"
|
||||
" example 1: sangoma_c -span 1 -chan 1 -r -verbose\n"
|
||||
" in this example Wanpipe span 1, Interface chan 1 will be used for reading data\n"
|
||||
"\n"
|
||||
"<extra options>\n"
|
||||
" -txcnt <digit> #number of tx packets (Dflt: 1)\n"
|
||||
|
|
|
@ -48,6 +48,8 @@ extern int rbs_events;
|
|||
extern int rx2tx;
|
||||
extern int flush_period;
|
||||
extern int stats_period;
|
||||
extern int hdlc_repeat;
|
||||
extern int buffer_multiplier;
|
||||
|
||||
extern unsigned char tx_file[WAN_IFNAME_SZ];
|
||||
extern unsigned char rx_file[WAN_IFNAME_SZ];
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,913 @@
|
|||
/******************************************************************************//**
|
||||
* \file sample.c
|
||||
* \brief WANPIPE(tm) API C Sample Code
|
||||
*
|
||||
* Authors: David Rokhvarg <davidr@sangoma.com>
|
||||
* Nenad Corbic <ncorbic@sangoma.com>
|
||||
*
|
||||
* Copyright (c) 2007 - 08, Sangoma Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* * Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Sangoma Technologies nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Sangoma Technologies ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Sangoma Technologies BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* ===============================================================================
|
||||
*
|
||||
*/
|
||||
|
||||
#include "libsangoma.h"
|
||||
#include "lib_api.h"
|
||||
|
||||
static u_int32_t poll_events_bitmap = 0;
|
||||
|
||||
/*!
|
||||
\def TEST_NUMBER_OF_OBJECTS
|
||||
\brief Number of wait objects to define in object array.
|
||||
|
||||
Objects are used to wait on file descripotrs.
|
||||
Usually there is one wait object per file descriptor.
|
||||
|
||||
In this example there is a single file descriptor and a
|
||||
single wait object.
|
||||
*/
|
||||
#define TEST_NUMBER_OF_OBJECTS 1
|
||||
|
||||
static sangoma_wait_obj_t *sangoma_wait_objects[TEST_NUMBER_OF_OBJECTS];
|
||||
|
||||
/* This example application has only a single execution thread - it is safe
|
||||
* to use a global buffer for received data and for data to be transmitted. */
|
||||
static unsigned char rxdata[MAX_NO_DATA_BYTES_IN_FRAME];
|
||||
static unsigned char txdata[MAX_NO_DATA_BYTES_IN_FRAME];
|
||||
|
||||
typedef struct sangoma_chan {
|
||||
int spanno;
|
||||
int channo;
|
||||
} sangoma_chan_t;
|
||||
sangoma_chan_t sangoma_channels[TEST_NUMBER_OF_OBJECTS];
|
||||
|
||||
/* Warning: non-thread safe globals. Ok for this single-thread example but not in production. */
|
||||
unsigned char rx_rbs_bits = WAN_RBS_SIG_A;
|
||||
FILE *pRxFile;
|
||||
int application_termination_flag = 0;
|
||||
|
||||
/*****************************************************************
|
||||
* Prototypes
|
||||
*****************************************************************/
|
||||
|
||||
int __cdecl main(int argc, char* argv[]);
|
||||
int open_sangoma_device(void);
|
||||
void handle_span_chan(int open_device_counter);
|
||||
int handle_tdm_event(uint32_t dev_index);
|
||||
int handle_data(uint32_t dev_index, int flags_out);
|
||||
int read_data(uint32_t dev_index, wp_api_hdr_t *rx_hdr, void *rx_buffer, int rx_buffer_length);
|
||||
int write_data(uint32_t dev_index, wp_api_hdr_t *tx_hdr, void *tx_buffer, int tx_len);
|
||||
int dtmf_event(sng_fd_t fd,unsigned char digit,unsigned char type,unsigned char port);
|
||||
int rbs_event(sng_fd_t fd,unsigned char rbs_bits);
|
||||
int rxhook_event(sng_fd_t fd,unsigned char hook_state);
|
||||
int rxring_event(sng_fd_t fd,unsigned char ring_state);
|
||||
int ringtrip_event (sng_fd_t fd, unsigned char ring_state);
|
||||
int write_data_to_file(unsigned char *data, unsigned int data_length);
|
||||
int sangoma_print_stats(sng_fd_t sangoma_dev);
|
||||
void cleanup(void);
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
BOOL WINAPI TerminateHandler(DWORD dwCtrlType);
|
||||
#else
|
||||
void TerminateHandler(int);
|
||||
#endif
|
||||
|
||||
/*****************************************************************
|
||||
* General Functions
|
||||
*****************************************************************/
|
||||
|
||||
/*!
|
||||
\fn void print_rx_data(unsigned char *data, int datalen)
|
||||
\brief Prints the contents of data packet
|
||||
\param data pointer to data buffer
|
||||
\param datalen size of data buffer
|
||||
\return void
|
||||
*/
|
||||
void print_rxdata(unsigned char *data, int datalen, wp_api_hdr_t *hdr); /* dont remove prototype, gcc complains */
|
||||
void print_rxdata(unsigned char *data, int datalen, wp_api_hdr_t *hdr)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("Data: (Len=%i,Errs=%i)\n",datalen,hdr->wp_api_rx_hdr_errors);
|
||||
for(i = 0; i < datalen; i++) {
|
||||
if((i % 20 == 0)){
|
||||
if(i){
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
printf("%02X ", data[i]);
|
||||
#if 0
|
||||
/* don't print too much!! */
|
||||
if(i > 100){
|
||||
printf("...\n");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
int sangoma_print_stats(sng_fd_t sangoma_dev)
|
||||
{
|
||||
int err;
|
||||
unsigned char firm_ver, cpld_ver;
|
||||
wanpipe_api_t wp_api;
|
||||
wanpipe_chan_stats_t stats_str;
|
||||
wanpipe_chan_stats_t *stats=&stats_str;
|
||||
memset(&wp_api,0,sizeof(wp_api));
|
||||
|
||||
|
||||
err=sangoma_get_stats(sangoma_dev, &wp_api, stats);
|
||||
if (err) {
|
||||
printf("sangoma_get_stats(() failed (err: %d (0x%X))!\n", err, err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf( "******* OPERATIONAL_STATS *******\n");
|
||||
|
||||
printf("\trx_packets\t: %u\n", stats->rx_packets);
|
||||
printf("\ttx_packets\t: %u\n", stats->tx_packets);
|
||||
printf("\trx_bytes\t: %u\n", stats->rx_bytes);
|
||||
printf("\ttx_bytes\t: %u\n", stats->tx_bytes);
|
||||
printf("\trx_errors\t: %u\n", stats->rx_errors); //Total number of Rx errors
|
||||
printf("\ttx_errors\t: %u\n", stats->tx_errors); //Total number of Tx errors
|
||||
printf("\trx_dropped\t: %u\n", stats->rx_dropped);
|
||||
printf("\ttx_dropped\t: %u\n", stats->tx_dropped);
|
||||
printf("\tmulticast\t: %u\n", stats->multicast);
|
||||
printf("\tcollisions\t: %u\n", stats->collisions);
|
||||
|
||||
printf("\trx_length_errors: %u\n", stats->rx_length_errors);
|
||||
printf("\trx_over_errors\t: %u\n", stats->rx_over_errors);
|
||||
printf("\trx_crc_errors\t: %u\n", stats->rx_crc_errors); //HDLC CRC mismatch
|
||||
printf("\trx_frame_errors\t: %u\n", stats->rx_frame_errors);//HDLC "abort" occured
|
||||
printf("\trx_fifo_errors\t: %u\n", stats->rx_fifo_errors);
|
||||
printf("\trx_missed_errors: %u\n", stats->rx_missed_errors);
|
||||
|
||||
printf("\ttx_aborted_errors: %u\n", stats->tx_aborted_errors);
|
||||
printf("\tTx Idle Data\t: %u\n", stats->tx_carrier_errors);
|
||||
|
||||
printf("\ttx_fifo_errors\t: %u\n", stats->tx_fifo_errors);
|
||||
printf("\ttx_heartbeat_errors: %u\n", stats->tx_heartbeat_errors);
|
||||
printf("\ttx_window_errors: %u\n", stats->tx_window_errors);
|
||||
|
||||
printf("\n\ttx_packets_in_q: %u\n", stats->current_number_of_frames_in_tx_queue);
|
||||
printf("\ttx_queue_size: %u\n", stats->max_tx_queue_length);
|
||||
|
||||
printf("\n\trx_packets_in_q: %u\n", stats->current_number_of_frames_in_rx_queue);
|
||||
printf("\trx_queue_size: %u\n", stats->max_rx_queue_length);
|
||||
|
||||
printf("\n\trx_events_in_q: %u\n", stats->current_number_of_events_in_event_queue);
|
||||
printf("\trx_event_queue_size: %u\n", stats->max_event_queue_length);
|
||||
printf("\trx_events: %u\n", stats->rx_events);
|
||||
printf("\trx_events_dropped: %u\n", stats->rx_events_dropped);
|
||||
|
||||
printf("\tHWEC tone (DTMF) events counter: %u\n", stats->rx_events_tone);
|
||||
printf( "*********************************\n");
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
err=sangoma_get_driver_version(sangoma_dev,&wp_api, NULL);
|
||||
if (err) {
|
||||
return 1;
|
||||
}
|
||||
printf("\tDriver Version: %u.%u.%u.%u\n",
|
||||
wp_api.wp_cmd.version.major,
|
||||
wp_api.wp_cmd.version.minor,
|
||||
wp_api.wp_cmd.version.minor1,
|
||||
wp_api.wp_cmd.version.minor2);
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
err=sangoma_get_firmware_version(sangoma_dev, &wp_api, &firm_ver);
|
||||
if (err) {
|
||||
return 1;
|
||||
}
|
||||
printf("\tFirmware Version: %X\n",
|
||||
firm_ver);
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
err=sangoma_get_cpld_version(sangoma_dev, &wp_api, &cpld_ver);
|
||||
if (err) {
|
||||
return 1;
|
||||
}
|
||||
printf("\tCPLD Version: %X\n",
|
||||
cpld_ver);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn int read_data(uint32_t dev_index)
|
||||
\brief Read data buffer from a device
|
||||
\param dev_index device index number associated with device file descriptor
|
||||
\param rx_hdr pointer to api header
|
||||
\param rx_buffer pointer to a buffer where recived data will be stored
|
||||
\param rx_buffer_length maximum length of rx_buffer
|
||||
\return 0 - Ok otherwise Error
|
||||
*/
|
||||
int read_data(uint32_t dev_index, wp_api_hdr_t *rx_hdr, void *rx_buffer, int rx_buffer_length)
|
||||
{
|
||||
sng_fd_t dev_fd = sangoma_wait_obj_get_fd(sangoma_wait_objects[dev_index]);
|
||||
sangoma_chan_t *chan = sangoma_wait_obj_get_context(sangoma_wait_objects[dev_index]);
|
||||
int Rx_lgth = 0;
|
||||
static int Rx_count= 0;
|
||||
wanpipe_api_t tdm_api;
|
||||
|
||||
memset(&tdm_api, 0x00, sizeof(tdm_api));
|
||||
memset(rx_hdr, 0, sizeof(wp_api_hdr_t));
|
||||
|
||||
/* read the message */
|
||||
Rx_lgth = sangoma_readmsg(
|
||||
dev_fd,
|
||||
rx_hdr, /* header buffer */
|
||||
sizeof(wp_api_hdr_t), /* header size */
|
||||
rx_buffer, /* data buffer */
|
||||
rx_buffer_length, /* data BUFFER size */
|
||||
0);
|
||||
if(Rx_lgth <= 0) {
|
||||
printf("Span: %d, Chan: %d: Error receiving data!\n",
|
||||
chan->spanno, chan->channo);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
if (rx_hdr->wp_api_rx_hdr_error_map) {
|
||||
if (rx_hdr->wp_api_rx_hdr_error_map & 1<<WP_FIFO_ERROR_BIT) {
|
||||
printf("Span: %d, Chan: %d rx fifo error\n");
|
||||
}
|
||||
if (rx_hdr->wp_api_rx_hdr_error_map & 1<<WP_CRC_ERROR_BIT) {
|
||||
printf("Span: %d, Chan: %d rx crc error\n");
|
||||
}
|
||||
if (rx_hdr->wp_api_rx_hdr_error_map & 1<<WP_ABORT_ERROR_BIT) {
|
||||
printf("Span: %d, Chan: %d rx abort error\n");
|
||||
}
|
||||
if (rx_hdr->wp_api_rx_hdr_error_map & 1<<WP_FRAME_ERROR_BIT) {
|
||||
printf("Span: %d, Chan: %d rx framing error\n");
|
||||
}
|
||||
if (rx_hdr->wp_api_rx_hdr_error_map & 1<<WP_DMA_ERROR_BIT) {
|
||||
printf("Span: %d, Chan: %d rx dma error\n");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
Rx_count++;
|
||||
|
||||
if (verbose){
|
||||
print_rxdata(rx_buffer, Rx_lgth,rx_hdr);
|
||||
}
|
||||
|
||||
if (stats_period && Rx_count % stats_period == 0) {
|
||||
sangoma_print_stats(dev_fd);
|
||||
}
|
||||
|
||||
/* use Rx_counter as "write" events trigger: */
|
||||
if(rbs_events == 1 && (Rx_count % 400) == 0){
|
||||
/* bitmap - set as needed: WAN_RBS_SIG_A | WAN_RBS_SIG_B | WAN_RBS_SIG_C | WAN_RBS_SIG_D;
|
||||
|
||||
In this example make bits A and B to change each time,
|
||||
so it's easy to see the change on the receiving side.
|
||||
*/
|
||||
if(rx_rbs_bits == WAN_RBS_SIG_A){
|
||||
rx_rbs_bits = WAN_RBS_SIG_B;
|
||||
}else{
|
||||
rx_rbs_bits = WAN_RBS_SIG_A;
|
||||
}
|
||||
printf("Writing RBS bits (0x%X)...\n", rx_rbs_bits);
|
||||
sangoma_tdm_write_rbs(dev_fd, &tdm_api,
|
||||
chan->channo,
|
||||
rx_rbs_bits);
|
||||
}
|
||||
|
||||
/* if user needs Rx data to be written into a file: */
|
||||
if(files_used & RX_FILE_USED){
|
||||
write_data_to_file(rx_buffer, Rx_lgth);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn int write_data(uint32_t dev_index, wp_api_hdr_t *tx_hdr, void *tx_data, int tx_len)
|
||||
\brief Transmit a data buffer to a device.
|
||||
\param dev_index device index number associated with device file descriptor
|
||||
\param tx_hdr pointer to a wp_api_hdr_t
|
||||
\param tx_data pointer to a data buffer
|
||||
\param tx_len tx data buffer len
|
||||
\return 0 - Ok otherwise Error
|
||||
*/
|
||||
int write_data(uint32_t dev_index, wp_api_hdr_t *tx_hdr, void *tx_buffer, int tx_len)
|
||||
{
|
||||
sng_fd_t dev_fd = sangoma_wait_obj_get_fd(sangoma_wait_objects[dev_index]);
|
||||
sangoma_chan_t *chan = sangoma_wait_obj_get_context(sangoma_wait_objects[dev_index]);
|
||||
int err;
|
||||
static int Tx_count = 0;
|
||||
|
||||
if (hdlc_repeat) {
|
||||
tx_hdr->wp_api_tx_hdr_hdlc_rpt_len=4;
|
||||
memset(tx_hdr->wp_api_tx_hdr_hdlc_rpt_data,Tx_count,4);
|
||||
}
|
||||
|
||||
/* write a message */
|
||||
err = sangoma_writemsg(
|
||||
dev_fd,
|
||||
tx_hdr, /* header buffer */
|
||||
sizeof(wp_api_hdr_t), /* header size */
|
||||
tx_buffer, /* data buffer */
|
||||
tx_len, /* DATA size */
|
||||
0);
|
||||
|
||||
if (err <= 0){
|
||||
printf("Span: %d, Chan: %d: Failed to send!\n",
|
||||
chan->spanno,
|
||||
chan->channo);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Tx_count++;
|
||||
if (verbose){
|
||||
printf("Packet sent: counter: %i, len: %i, errors %i\n", Tx_count, err, tx_hdr->wp_api_tx_hdr_errors);
|
||||
}else{
|
||||
if(Tx_count && (!(Tx_count % 1000))){
|
||||
printf("Packet sent: counter: %i, len: %i\n", Tx_count, err);
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
if(tx_cnt && Tx_count >= tx_cnt){
|
||||
write_enable=0;
|
||||
printf("Disabling POLLOUT...\n");
|
||||
/* No need for POLLOUT, turn it off!! If not turned off, and we
|
||||
* have nothing for transmission, sangoma_socket_waitfor() will return
|
||||
* immediately, creating a busy loop. */
|
||||
//sangoma_wait_objects[dev_index].flags_in &= (~POLLOUT);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn int handle_data(uint32_t dev_index, int flags_out)
|
||||
\brief Read data buffer from the device and transmit it back down.
|
||||
\param dev_index device index number associated with device file descriptor
|
||||
\return 0 - Ok otherwise Error
|
||||
|
||||
Read data buffer from a device.
|
||||
*/
|
||||
int handle_data(uint32_t dev_index, int flags_out)
|
||||
{
|
||||
wp_api_hdr_t rxhdr;
|
||||
int err=0;
|
||||
|
||||
memset(&rxhdr, 0, sizeof(rxhdr));
|
||||
|
||||
#if 0
|
||||
printf("%s(): span: %d, chan: %d\n", __FUNCTION__,
|
||||
sangoma_wait_objects[dev_index].span, sangoma_wait_objects[dev_index].chan);
|
||||
#endif
|
||||
|
||||
if(flags_out & POLLIN){
|
||||
if(read_data(dev_index, &rxhdr, rxdata, MAX_NO_DATA_BYTES_IN_FRAME) == 0){
|
||||
if(rx2tx){
|
||||
/* Send back received data (create a "software loopback"), just a test. */
|
||||
return write_data(dev_index, &rxhdr, rxdata,rxhdr.data_length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( (flags_out & POLLOUT) && write_enable ){
|
||||
|
||||
wp_api_hdr_t txhdr;
|
||||
static unsigned char tx_test_byte = 0;
|
||||
|
||||
memset(&txhdr, 0, sizeof(txhdr));
|
||||
txhdr.data_length = (unsigned short)tx_size;/* use '-txsize' command line option to change 'tx_size' */
|
||||
|
||||
/* set data which will be transmitted */
|
||||
memset(txdata, tx_test_byte, txhdr.data_length);
|
||||
|
||||
err = write_data(dev_index, &txhdr, txdata, tx_size);
|
||||
if (err== 0) {
|
||||
tx_test_byte++;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn int decode_api_event (wp_api_event_t *wp_tdm_api_event)
|
||||
\brief Handle API Event
|
||||
\param wp_tdm_api_event
|
||||
*/
|
||||
static void decode_api_event(wp_api_event_t *wp_tdm_api_event)
|
||||
{
|
||||
printf("%s(): span: %d, chan: %d\n", __FUNCTION__,
|
||||
wp_tdm_api_event->span, wp_tdm_api_event->channel);
|
||||
|
||||
switch(wp_tdm_api_event->wp_api_event_type)
|
||||
{
|
||||
case WP_API_EVENT_DTMF:/* DTMF detected by Hardware */
|
||||
printf("DTMF Event: Channel: %d, Digit: %c (Port: %s, Type:%s)!\n",
|
||||
wp_tdm_api_event->channel,
|
||||
wp_tdm_api_event->wp_api_event_dtmf_digit,
|
||||
(wp_tdm_api_event->wp_api_event_dtmf_port == WAN_EC_CHANNEL_PORT_ROUT)?"ROUT":"SOUT",
|
||||
(wp_tdm_api_event->wp_api_event_dtmf_type == WAN_EC_TONE_PRESENT)?"PRESENT":"STOP");
|
||||
break;
|
||||
|
||||
case WP_API_EVENT_RXHOOK:
|
||||
printf("RXHOOK Event: Channel: %d, %s! (0x%X)\n",
|
||||
wp_tdm_api_event->channel,
|
||||
WAN_EVENT_RXHOOK_DECODE(wp_tdm_api_event->wp_api_event_hook_state),
|
||||
wp_tdm_api_event->wp_api_event_hook_state);
|
||||
break;
|
||||
|
||||
case WP_API_EVENT_RING_DETECT:
|
||||
printf("RING Event: %s! (0x%X)\n",
|
||||
WAN_EVENT_RING_DECODE(wp_tdm_api_event->wp_api_event_ring_state),
|
||||
wp_tdm_api_event->wp_api_event_ring_state);
|
||||
break;
|
||||
|
||||
case WP_API_EVENT_RING_TRIP_DETECT:
|
||||
printf("RING TRIP Event: %s! (0x%X)\n",
|
||||
WAN_EVENT_RING_TRIP_DECODE(wp_tdm_api_event->wp_api_event_ring_state),
|
||||
wp_tdm_api_event->wp_api_event_ring_state);
|
||||
break;
|
||||
|
||||
case WP_API_EVENT_RBS:
|
||||
printf("RBS Event: Channel: %d, 0x%X!\n",
|
||||
wp_tdm_api_event->channel,
|
||||
wp_tdm_api_event->wp_api_event_rbs_bits);
|
||||
printf( "RX RBS: A:%1d B:%1d C:%1d D:%1d\n",
|
||||
(wp_tdm_api_event->wp_api_event_rbs_bits & WAN_RBS_SIG_A) ? 1 : 0,
|
||||
(wp_tdm_api_event->wp_api_event_rbs_bits & WAN_RBS_SIG_B) ? 1 : 0,
|
||||
(wp_tdm_api_event->wp_api_event_rbs_bits & WAN_RBS_SIG_C) ? 1 : 0,
|
||||
(wp_tdm_api_event->wp_api_event_rbs_bits & WAN_RBS_SIG_D) ? 1 : 0);
|
||||
break;
|
||||
|
||||
case WP_API_EVENT_LINK_STATUS:
|
||||
printf("Link Status Event: %s! (0x%X)\n",
|
||||
WAN_EVENT_LINK_STATUS_DECODE(wp_tdm_api_event->wp_api_event_link_status),
|
||||
wp_tdm_api_event->wp_api_event_link_status);
|
||||
break;
|
||||
|
||||
case WP_API_EVENT_ALARM:
|
||||
printf("New Alarm State: %s! (0x%X)\n", (wp_tdm_api_event->wp_api_event_alarm == 0?"Off":"On"),
|
||||
wp_tdm_api_event->wp_api_event_alarm);
|
||||
break;
|
||||
|
||||
case WP_API_EVENT_POLARITY_REVERSE:
|
||||
printf("Polarity Reversal Event : %s! (0x%X)\n",
|
||||
WP_API_EVENT_POLARITY_REVERSE_DECODE(wp_tdm_api_event->wp_api_event_polarity_reverse),
|
||||
wp_tdm_api_event->wp_api_event_polarity_reverse);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Unknown TDM API Event: %d\n", wp_tdm_api_event->wp_api_event_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn int handle_tdm_event(uint32_t dev_index)
|
||||
\brief Read Event buffer from the device
|
||||
\param dev_index device index number associated with device file descriptor
|
||||
\return 0 - Ok otherwise Error
|
||||
|
||||
An EVENT has occoured. Execute a system call to read the EVENT
|
||||
on a device.
|
||||
*/
|
||||
int handle_tdm_event(uint32_t dev_index)
|
||||
{
|
||||
wanpipe_api_t tdm_api;
|
||||
sng_fd_t dev_fd = sangoma_wait_obj_get_fd(sangoma_wait_objects[dev_index]);
|
||||
|
||||
#if 0
|
||||
printf("%s(): dev_index: %d, dev_fd: 0x%p\n", __FUNCTION__, dev_index, dev_fd);
|
||||
#endif
|
||||
|
||||
memset(&tdm_api, 0x00, sizeof(tdm_api));
|
||||
|
||||
if(sangoma_read_event(dev_fd, &tdm_api)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
decode_api_event(&tdm_api.wp_cmd.event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn void handle_span_chan(int open_device_counter)
|
||||
\brief Write data buffer into a file
|
||||
\param open_device_counter number of opened devices
|
||||
\return void
|
||||
|
||||
This function will wait on all opened devices.
|
||||
This example will wait for RX and EVENT signals.
|
||||
In case of POLLIN - rx data available
|
||||
In case of POLLPRI - event is available
|
||||
*/
|
||||
void handle_span_chan(int open_device_counter)
|
||||
{
|
||||
int iResult, i;
|
||||
u_int32_t input_flags[TEST_NUMBER_OF_OBJECTS];
|
||||
u_int32_t output_flags[TEST_NUMBER_OF_OBJECTS];
|
||||
|
||||
printf("\n\nSpan/Chan Handler: RxEnable=%s, TxEnable=%s, TxCnt=%i, TxLen=%i, rx2tx=%s\n",
|
||||
(read_enable? "Yes":"No"), (write_enable?"Yes":"No"),tx_cnt,tx_size, (rx2tx?"Yes":"No"));
|
||||
|
||||
for (i = 0; i < open_device_counter; i++) {
|
||||
input_flags[i] = poll_events_bitmap;
|
||||
}
|
||||
|
||||
/* Main Rx/Tx/Event loop */
|
||||
while(!application_termination_flag)
|
||||
{
|
||||
iResult = sangoma_waitfor_many(sangoma_wait_objects,
|
||||
input_flags,
|
||||
output_flags,
|
||||
open_device_counter /* number of wait objects */,
|
||||
5000 /* wait timeout, in milliseconds */);
|
||||
switch(iResult)
|
||||
{
|
||||
case SANG_STATUS_APIPOLL_TIMEOUT:
|
||||
/* timeout (not an error) */
|
||||
{
|
||||
sng_fd_t dev_fd = sangoma_wait_obj_get_fd(sangoma_wait_objects[0]);
|
||||
sangoma_print_stats(dev_fd);
|
||||
}
|
||||
printf("Timeout\n");
|
||||
continue;
|
||||
|
||||
case SANG_STATUS_SUCCESS:
|
||||
for(i = 0; i < open_device_counter; i++){
|
||||
|
||||
/* a wait object was signaled */
|
||||
if(output_flags[i] & POLLPRI){
|
||||
/* got tdm api event */
|
||||
if(handle_tdm_event(i)){
|
||||
printf("Error in handle_tdm_event()!\n");
|
||||
application_termination_flag=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(output_flags[i] & (POLLIN | POLLOUT)){
|
||||
/* rx data OR a free tx buffer available */
|
||||
if(handle_data(i, output_flags[i])){
|
||||
printf("Error in handle_data()!\n");
|
||||
//application_termination_flag=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}/* for() */
|
||||
break;
|
||||
|
||||
default:
|
||||
/* error */
|
||||
printf("Error: iResult: %s (%d)\n", SDLA_DECODE_SANG_STATUS(iResult), iResult);
|
||||
return;
|
||||
}
|
||||
|
||||
}/* while() */
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn int write_data_to_file(unsigned char *data, unsigned int data_length)
|
||||
\brief Write data buffer into a file
|
||||
\param data data buffer
|
||||
\param data_length length of a data buffer
|
||||
\return data_length = ok otherwise error
|
||||
|
||||
*/
|
||||
int write_data_to_file(unsigned char *data, unsigned int data_length)
|
||||
{
|
||||
if(pRxFile == NULL){
|
||||
return 1;
|
||||
}
|
||||
|
||||
return fwrite(data, 1, data_length, pRxFile);
|
||||
}
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
/*
|
||||
* TerminateHandler() - this handler is called by the system whenever user tries to terminate
|
||||
* the process with Ctrl+C, Ctrl+Break or closes the console window.
|
||||
* Perform a clean-up here.
|
||||
*/
|
||||
BOOL TerminateHandler(DWORD dwCtrlType)
|
||||
{
|
||||
printf("\nProcess terminated by user request.\n");
|
||||
application_termination_flag = 1;
|
||||
/* do the cleanup before exiting: */
|
||||
cleanup();
|
||||
/* return FALSE so the system will call the dafult handler which will terminate the process. */
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
/*!
|
||||
\fn void TerminateHandler (int sig)
|
||||
\brief Signal handler for graceful shutdown
|
||||
\param sig signal
|
||||
*/
|
||||
void TerminateHandler (int sig)
|
||||
{
|
||||
printf("\nProcess terminated by user request.\n");
|
||||
application_termination_flag = 1;
|
||||
/* do the cleanup before exiting: */
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\fn void cleanup()
|
||||
\brief Protperly shutdown single device
|
||||
\param dev_no device index number
|
||||
\return void
|
||||
|
||||
*/
|
||||
void cleanup()
|
||||
{
|
||||
int dev_no;
|
||||
sng_fd_t fd;
|
||||
sangoma_chan_t *chan;
|
||||
sangoma_wait_obj_t *sng_wait_object;
|
||||
wanpipe_api_t tdm_api;
|
||||
|
||||
/* do the cleanup before exiting: */
|
||||
for(dev_no = 0; dev_no < TEST_NUMBER_OF_OBJECTS; dev_no++){
|
||||
|
||||
sng_wait_object = sangoma_wait_objects[dev_no];
|
||||
if(!sng_wait_object){
|
||||
continue;
|
||||
}
|
||||
chan = sangoma_wait_obj_get_context(sng_wait_object);
|
||||
printf("%s(): span: %d, chan: %d ...\n", __FUNCTION__,
|
||||
chan->channo,
|
||||
chan->spanno);
|
||||
|
||||
fd = sangoma_wait_obj_get_fd(sng_wait_object);
|
||||
memset(&tdm_api, 0x00, sizeof(tdm_api));
|
||||
|
||||
if(dtmf_enable_octasic == 1){
|
||||
/* Disable dtmf detection on Octasic chip */
|
||||
sangoma_tdm_disable_dtmf_events(fd, &tdm_api);
|
||||
}
|
||||
|
||||
if(dtmf_enable_remora == 1){
|
||||
/* Disable dtmf detection on Sangoma's Remora SLIC chip */
|
||||
sangoma_tdm_disable_rm_dtmf_events(fd, &tdm_api);
|
||||
}
|
||||
|
||||
if(remora_hook == 1){
|
||||
sangoma_tdm_disable_rxhook_events(fd, &tdm_api);
|
||||
}
|
||||
|
||||
if(rbs_events == 1){
|
||||
sangoma_tdm_disable_rbs_events(fd, &tdm_api);
|
||||
}
|
||||
|
||||
sangoma_wait_obj_delete(&sng_wait_object);
|
||||
|
||||
sangoma_close(&fd);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\fn int open_sangoma_device()
|
||||
\brief Open a single span chan device
|
||||
\return 0 ok otherise error.
|
||||
|
||||
This function will open a single span chan.
|
||||
|
||||
However it can be rewritten to iterate for all spans and chans and try to
|
||||
open all existing wanpipe devices.
|
||||
|
||||
For each opened device, a wait object will be initialized.
|
||||
For each device, configure the chunk size for tx/rx
|
||||
enable events such as DTMF/RBS ...etc
|
||||
*/
|
||||
int open_sangoma_device()
|
||||
{
|
||||
int span, chan, err = 0, open_dev_cnt = 0;
|
||||
sangoma_status_t status;
|
||||
sng_fd_t dev_fd = INVALID_HANDLE_VALUE;
|
||||
wanpipe_api_t tdm_api;
|
||||
|
||||
span = wanpipe_port_no;
|
||||
chan = wanpipe_if_no;
|
||||
|
||||
/* span and chan are 1-based */
|
||||
dev_fd = sangoma_open_api_span_chan(span, chan);
|
||||
if( dev_fd == INVALID_HANDLE_VALUE){
|
||||
printf("Warning: Failed to open span %d, chan %d\n", span , chan);
|
||||
return 1;
|
||||
}else{
|
||||
printf("Successfuly opened span %d, chan %d\n", span , chan);
|
||||
}
|
||||
|
||||
memset(&tdm_api, 0x00, sizeof(tdm_api));
|
||||
|
||||
status = sangoma_wait_obj_create(&sangoma_wait_objects[open_dev_cnt], dev_fd, SANGOMA_DEVICE_WAIT_OBJ);
|
||||
if(status != SANG_STATUS_SUCCESS){
|
||||
printf("Error: Failed to create 'sangoma_wait_object'!\n");
|
||||
return 1;
|
||||
}
|
||||
sangoma_channels[open_dev_cnt].channo = chan;
|
||||
sangoma_channels[open_dev_cnt].spanno = span;
|
||||
sangoma_wait_obj_set_context(sangoma_wait_objects[open_dev_cnt], &sangoma_channels[open_dev_cnt]);
|
||||
/* open_dev_cnt++; */
|
||||
|
||||
if((err = sangoma_get_full_cfg(dev_fd, &tdm_api))){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(set_codec_slinear){
|
||||
printf("Setting SLINEAR codec\n");
|
||||
if((err=sangoma_tdm_set_codec(dev_fd, &tdm_api, WP_SLINEAR))){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(set_codec_none){
|
||||
printf("Disabling codec\n");
|
||||
if((err=sangoma_tdm_set_codec(dev_fd, &tdm_api, WP_NONE))){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(usr_period){
|
||||
printf("Setting user period: %d\n", usr_period);
|
||||
if((err=sangoma_tdm_set_usr_period(dev_fd, &tdm_api, usr_period))){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(set_codec_slinear || usr_period || set_codec_none){
|
||||
/* display new configuration AFTER it was changed */
|
||||
if((err=sangoma_get_full_cfg(dev_fd, &tdm_api))){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(dtmf_enable_octasic == 1){
|
||||
poll_events_bitmap |= POLLPRI;
|
||||
/* enable dtmf detection on Octasic chip */
|
||||
if((err=sangoma_tdm_enable_dtmf_events(dev_fd, &tdm_api))){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(dtmf_enable_remora == 1){
|
||||
poll_events_bitmap |= POLLPRI;
|
||||
/* enable dtmf detection on Sangoma's Remora SLIC chip (A200 ONLY) */
|
||||
if((err=sangoma_tdm_enable_rm_dtmf_events(dev_fd, &tdm_api))){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(remora_hook == 1){
|
||||
poll_events_bitmap |= POLLPRI;
|
||||
if((err=sangoma_tdm_enable_rxhook_events(dev_fd, &tdm_api))){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(rbs_events == 1){
|
||||
poll_events_bitmap |= POLLPRI;
|
||||
if((err=sangoma_tdm_enable_rbs_events(dev_fd, &tdm_api, 20))){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (buffer_multiplier) {
|
||||
printf("Setting buffer multiplier to %i\n",buffer_multiplier);
|
||||
err=sangoma_tdm_set_buffer_multiplier(dev_fd,&tdm_api,buffer_multiplier);
|
||||
if (err) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Device Config RxQ=%i TxQ=%i \n",
|
||||
sangoma_get_rx_queue_sz(dev_fd,&tdm_api),
|
||||
sangoma_get_rx_queue_sz(dev_fd,&tdm_api));
|
||||
|
||||
sangoma_set_rx_queue_sz(dev_fd,&tdm_api,20);
|
||||
sangoma_set_tx_queue_sz(dev_fd,&tdm_api,30);
|
||||
|
||||
printf("Device Config RxQ=%i TxQ=%i \n",
|
||||
sangoma_get_rx_queue_sz(dev_fd,&tdm_api),
|
||||
sangoma_get_tx_queue_sz(dev_fd,&tdm_api));
|
||||
|
||||
sangoma_flush_bufs(dev_fd,&tdm_api);
|
||||
|
||||
sangoma_print_stats(dev_fd);
|
||||
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn int __cdecl main(int argc, char* argv[])
|
||||
\brief Main function that starts the sample code
|
||||
\param argc number of arguments
|
||||
\param argv argument list
|
||||
*/
|
||||
int __cdecl main(int argc, char* argv[])
|
||||
{
|
||||
int proceed, i;
|
||||
|
||||
proceed=init_args(argc,argv);
|
||||
if (proceed != WAN_TRUE){
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* register Ctrl+C handler - we want a clean termination */
|
||||
#if defined(__WINDOWS__)
|
||||
if (!SetConsoleCtrlHandler(TerminateHandler, TRUE)) {
|
||||
printf("ERROR : Unable to register terminate handler ( %d ).\nProcess terminated.\n",
|
||||
GetLastError());
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
signal(SIGHUP,TerminateHandler);
|
||||
signal(SIGTERM,TerminateHandler);
|
||||
#endif
|
||||
|
||||
for(i = 0; i < TEST_NUMBER_OF_OBJECTS; i++){
|
||||
sangoma_wait_objects[i] = NULL;
|
||||
}
|
||||
|
||||
poll_events_bitmap = 0;
|
||||
if(read_enable == 1){
|
||||
poll_events_bitmap |= POLLIN;
|
||||
}
|
||||
|
||||
if(write_enable == 1 && rx2tx == 1){
|
||||
/* These two options are mutually exclusive because 'rx2tx' option
|
||||
* indicates "use Reciever as the timing source for Transmitter". */
|
||||
write_enable = 0;
|
||||
}
|
||||
|
||||
if(write_enable == 1){
|
||||
poll_events_bitmap |= POLLOUT;
|
||||
}
|
||||
|
||||
/* Front End connect/disconnect, and other events, such as DTMF... */
|
||||
poll_events_bitmap |= (POLLHUP | POLLPRI);
|
||||
#if defined(__WINDOWS__)
|
||||
printf("Enabling Poll Events:\n");
|
||||
print_poll_event_bitmap(poll_events_bitmap);
|
||||
#endif
|
||||
printf("Connecting to Port/Span: %d, Interface/Chan: %d\n",
|
||||
wanpipe_port_no, wanpipe_if_no);
|
||||
|
||||
|
||||
if(open_sangoma_device()){
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("********************************\n");
|
||||
printf("files_used: 0x%x\n", files_used);
|
||||
printf("********************************\n");
|
||||
if(files_used & RX_FILE_USED){
|
||||
pRxFile = fopen( (const char*)&rx_file[0], "wb" );
|
||||
if(pRxFile == NULL){
|
||||
printf("Can't open Rx file: [%s]!!\n", rx_file);
|
||||
}else{
|
||||
printf("Open Rx file: %s. OK.\n", rx_file);
|
||||
}
|
||||
}
|
||||
|
||||
handle_span_chan(1 /* handle a single device */);
|
||||
|
||||
/* returned from main loop, do the cleanup before exiting: */
|
||||
cleanup();
|
||||
|
||||
printf("\nSample application exiting.(press any key)\n");
|
||||
_getch();
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,945 @@
|
|||
/******************************************************************************//**
|
||||
* \file sample.c
|
||||
* \brief WANPIPE(tm) API C Sample Code
|
||||
*
|
||||
* Authors: David Rokhvarg <davidr@sangoma.com>
|
||||
* Nenad Corbic <ncorbic@sangoma.com>
|
||||
*
|
||||
* Copyright (c) 2007 - 08, Sangoma Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* * Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Sangoma Technologies nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Sangoma Technologies ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Sangoma Technologies BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* ===============================================================================
|
||||
*
|
||||
*/
|
||||
|
||||
#include "libsangoma.h"
|
||||
#include "lib_api.h"
|
||||
|
||||
static u_int32_t poll_events_bitmap = 0;
|
||||
|
||||
/*!
|
||||
\def TEST_NUMBER_OF_OBJECTS
|
||||
\brief Number of wait objects to define in object array.
|
||||
|
||||
Objects are used to wait on file descripotrs.
|
||||
Usually there is one wait object per file descriptor.
|
||||
|
||||
In this example there is a single file descriptor and a
|
||||
single wait object.
|
||||
*/
|
||||
#define TEST_NUMBER_OF_OBJECTS 1
|
||||
|
||||
static sangoma_wait_obj_t *sangoma_wait_objects[TEST_NUMBER_OF_OBJECTS];
|
||||
|
||||
/* This example application has only a single execution thread - it is safe
|
||||
* to use a global buffer for received data and for data to be transmitted. */
|
||||
static unsigned char rxdata[MAX_NO_DATA_BYTES_IN_FRAME];
|
||||
static unsigned char txdata[MAX_NO_DATA_BYTES_IN_FRAME];
|
||||
|
||||
typedef struct sangoma_chan {
|
||||
int spanno;
|
||||
int channo;
|
||||
} sangoma_chan_t;
|
||||
sangoma_chan_t sangoma_channels[TEST_NUMBER_OF_OBJECTS];
|
||||
|
||||
/* Warning: non-thread safe globals. Ok for this single-thread example but not in production. */
|
||||
unsigned char rx_rbs_bits = WAN_RBS_SIG_A;
|
||||
FILE *pRxFile;
|
||||
int application_termination_flag = 0;
|
||||
|
||||
/*****************************************************************
|
||||
* Prototypes
|
||||
*****************************************************************/
|
||||
|
||||
int __cdecl main(int argc, char* argv[]);
|
||||
int open_sangoma_device(void);
|
||||
void handle_span_chan(int open_device_counter);
|
||||
int handle_tdm_event(uint32_t dev_index);
|
||||
int handle_data(uint32_t dev_index, int flags_out);
|
||||
int read_data(uint32_t dev_index, wp_api_hdr_t *rx_hdr, void *rx_buffer, int rx_buffer_length);
|
||||
int write_data(uint32_t dev_index, wp_api_hdr_t *tx_hdr, void *tx_buffer, int tx_len);
|
||||
int dtmf_event(sng_fd_t fd,unsigned char digit,unsigned char type,unsigned char port);
|
||||
int rbs_event(sng_fd_t fd,unsigned char rbs_bits);
|
||||
int rxhook_event(sng_fd_t fd,unsigned char hook_state);
|
||||
int rxring_event(sng_fd_t fd,unsigned char ring_state);
|
||||
int ringtrip_event (sng_fd_t fd, unsigned char ring_state);
|
||||
int write_data_to_file(unsigned char *data, unsigned int data_length);
|
||||
int sangoma_print_stats(sng_fd_t sangoma_dev);
|
||||
void cleanup(void);
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
BOOL WINAPI TerminateHandler(DWORD dwCtrlType);
|
||||
#else
|
||||
void TerminateHandler(int);
|
||||
#endif
|
||||
|
||||
/*****************************************************************
|
||||
* General Functions
|
||||
*****************************************************************/
|
||||
|
||||
/*!
|
||||
\fn void print_rx_data(unsigned char *data, int datalen)
|
||||
\brief Prints the contents of data packet
|
||||
\param data pointer to data buffer
|
||||
\param datalen size of data buffer
|
||||
\return void
|
||||
*/
|
||||
void print_rxdata(unsigned char *data, int datalen, wp_api_hdr_t *hdr); /* dont remove prototype, gcc complains */
|
||||
void print_rxdata(unsigned char *data, int datalen, wp_api_hdr_t *hdr)
|
||||
{
|
||||
int i;
|
||||
int err=0;
|
||||
|
||||
<<<<<<< .mine
|
||||
printf("Data: (Len=%i,Errs=%i)\n",datalen,hdr->wp_api_rx_hdr_errors);
|
||||
=======
|
||||
#ifdef WP_API_FEATURE_RX_TX_ERRS
|
||||
err=hdr->wp_api_rx_hdr_errors;
|
||||
#endif
|
||||
printf("Data: (Len=%i,Errs=%i)\n",datalen,err);
|
||||
>>>>>>> .r292
|
||||
for(i = 0; i < datalen; i++) {
|
||||
if((i % 20 == 0)){
|
||||
if(i){
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
printf("%02X ", data[i]);
|
||||
#if 0
|
||||
/* don't print too much!! */
|
||||
if(i > 100){
|
||||
printf("...\n");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
int sangoma_print_stats(sng_fd_t sangoma_dev)
|
||||
{
|
||||
int err;
|
||||
unsigned char firm_ver, cpld_ver;
|
||||
wanpipe_api_t wp_api;
|
||||
wanpipe_chan_stats_t stats_str;
|
||||
wanpipe_chan_stats_t *stats=&stats_str;
|
||||
memset(&wp_api,0,sizeof(wp_api));
|
||||
|
||||
|
||||
err=sangoma_get_stats(sangoma_dev, &wp_api, stats);
|
||||
if (err) {
|
||||
printf("sangoma_get_stats(() failed (err: %d (0x%X))!\n", err, err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf( "******* OPERATIONAL_STATS *******\n");
|
||||
|
||||
printf("\trx_packets\t: %u\n", stats->rx_packets);
|
||||
printf("\ttx_packets\t: %u\n", stats->tx_packets);
|
||||
printf("\trx_bytes\t: %u\n", stats->rx_bytes);
|
||||
printf("\ttx_bytes\t: %u\n", stats->tx_bytes);
|
||||
printf("\trx_errors\t: %u\n", stats->rx_errors); //Total number of Rx errors
|
||||
printf("\ttx_errors\t: %u\n", stats->tx_errors); //Total number of Tx errors
|
||||
printf("\trx_dropped\t: %u\n", stats->rx_dropped);
|
||||
printf("\ttx_dropped\t: %u\n", stats->tx_dropped);
|
||||
printf("\tmulticast\t: %u\n", stats->multicast);
|
||||
printf("\tcollisions\t: %u\n", stats->collisions);
|
||||
|
||||
printf("\trx_length_errors: %u\n", stats->rx_length_errors);
|
||||
printf("\trx_over_errors\t: %u\n", stats->rx_over_errors);
|
||||
printf("\trx_crc_errors\t: %u\n", stats->rx_crc_errors); //HDLC CRC mismatch
|
||||
printf("\trx_frame_errors\t: %u\n", stats->rx_frame_errors);//HDLC "abort" occured
|
||||
printf("\trx_fifo_errors\t: %u\n", stats->rx_fifo_errors);
|
||||
printf("\trx_missed_errors: %u\n", stats->rx_missed_errors);
|
||||
|
||||
printf("\ttx_aborted_errors: %u\n", stats->tx_aborted_errors);
|
||||
printf("\tTx Idle Data\t: %u\n", stats->tx_carrier_errors);
|
||||
|
||||
printf("\ttx_fifo_errors\t: %u\n", stats->tx_fifo_errors);
|
||||
printf("\ttx_heartbeat_errors: %u\n", stats->tx_heartbeat_errors);
|
||||
printf("\ttx_window_errors: %u\n", stats->tx_window_errors);
|
||||
|
||||
printf("\n\ttx_packets_in_q: %u\n", stats->current_number_of_frames_in_tx_queue);
|
||||
printf("\ttx_queue_size: %u\n", stats->max_tx_queue_length);
|
||||
|
||||
printf("\n\trx_packets_in_q: %u\n", stats->current_number_of_frames_in_rx_queue);
|
||||
printf("\trx_queue_size: %u\n", stats->max_rx_queue_length);
|
||||
|
||||
printf("\n\trx_events_in_q: %u\n", stats->current_number_of_events_in_event_queue);
|
||||
printf("\trx_event_queue_size: %u\n", stats->max_event_queue_length);
|
||||
printf("\trx_events: %u\n", stats->rx_events);
|
||||
printf("\trx_events_dropped: %u\n", stats->rx_events_dropped);
|
||||
|
||||
printf("\tHWEC tone (DTMF) events counter: %u\n", stats->rx_events_tone);
|
||||
printf( "*********************************\n");
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
err=sangoma_get_driver_version(sangoma_dev,&wp_api, NULL);
|
||||
if (err) {
|
||||
return 1;
|
||||
}
|
||||
printf("\tDriver Version: %u.%u.%u.%u\n",
|
||||
wp_api.wp_cmd.version.major,
|
||||
wp_api.wp_cmd.version.minor,
|
||||
wp_api.wp_cmd.version.minor1,
|
||||
wp_api.wp_cmd.version.minor2);
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
err=sangoma_get_firmware_version(sangoma_dev, &wp_api, &firm_ver);
|
||||
if (err) {
|
||||
return 1;
|
||||
}
|
||||
printf("\tFirmware Version: %X\n",
|
||||
firm_ver);
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
err=sangoma_get_cpld_version(sangoma_dev, &wp_api, &cpld_ver);
|
||||
if (err) {
|
||||
return 1;
|
||||
}
|
||||
printf("\tCPLD Version: %X\n",
|
||||
cpld_ver);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn int read_data(uint32_t dev_index)
|
||||
\brief Read data buffer from a device
|
||||
\param dev_index device index number associated with device file descriptor
|
||||
\param rx_hdr pointer to api header
|
||||
\param rx_buffer pointer to a buffer where recived data will be stored
|
||||
\param rx_buffer_length maximum length of rx_buffer
|
||||
\return 0 - Ok otherwise Error
|
||||
*/
|
||||
int read_data(uint32_t dev_index, wp_api_hdr_t *rx_hdr, void *rx_buffer, int rx_buffer_length)
|
||||
{
|
||||
sng_fd_t dev_fd = sangoma_wait_obj_get_fd(sangoma_wait_objects[dev_index]);
|
||||
sangoma_chan_t *chan = sangoma_wait_obj_get_context(sangoma_wait_objects[dev_index]);
|
||||
int Rx_lgth = 0;
|
||||
static int Rx_count= 0;
|
||||
wanpipe_api_t tdm_api;
|
||||
|
||||
memset(&tdm_api, 0x00, sizeof(tdm_api));
|
||||
memset(rx_hdr, 0, sizeof(wp_api_hdr_t));
|
||||
|
||||
/* read the message */
|
||||
Rx_lgth = sangoma_readmsg(
|
||||
dev_fd,
|
||||
rx_hdr, /* header buffer */
|
||||
sizeof(wp_api_hdr_t), /* header size */
|
||||
rx_buffer, /* data buffer */
|
||||
rx_buffer_length, /* data BUFFER size */
|
||||
0);
|
||||
if(Rx_lgth <= 0) {
|
||||
printf("Span: %d, Chan: %d: Error receiving data!\n",
|
||||
chan->spanno, chan->channo);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
<<<<<<< .mine
|
||||
if (rx_hdr->wp_api_rx_hdr_error_map) {
|
||||
if (rx_hdr->wp_api_rx_hdr_error_map & 1<<WP_FIFO_ERROR_BIT) {
|
||||
printf("Span: %d, Chan: %d rx fifo error\n");
|
||||
}
|
||||
if (rx_hdr->wp_api_rx_hdr_error_map & 1<<WP_CRC_ERROR_BIT) {
|
||||
printf("Span: %d, Chan: %d rx crc error\n");
|
||||
}
|
||||
if (rx_hdr->wp_api_rx_hdr_error_map & 1<<WP_ABORT_ERROR_BIT) {
|
||||
printf("Span: %d, Chan: %d rx abort error\n");
|
||||
}
|
||||
if (rx_hdr->wp_api_rx_hdr_error_map & 1<<WP_FRAME_ERROR_BIT) {
|
||||
printf("Span: %d, Chan: %d rx framing error\n");
|
||||
}
|
||||
if (rx_hdr->wp_api_rx_hdr_error_map & 1<<WP_DMA_ERROR_BIT) {
|
||||
printf("Span: %d, Chan: %d rx dma error\n");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
=======
|
||||
#ifdef WP_API_FEATURE_RX_TX_ERRS
|
||||
if (rx_hdr->wp_api_rx_hdr_error_map) {
|
||||
if (rx_hdr->wp_api_rx_hdr_error_map & 1<<WP_FIFO_ERROR_BIT) {
|
||||
printf("Span: %d, Chan: %d rx fifo error 0x%02X\n",chan->spanno,chan->channo,rx_hdr->wp_api_rx_hdr_error_map);
|
||||
}
|
||||
if (rx_hdr->wp_api_rx_hdr_error_map & 1<<WP_CRC_ERROR_BIT) {
|
||||
printf("Span: %d, Chan: %d rx crc error 0x%02X\n",chan->spanno,chan->channo,rx_hdr->wp_api_rx_hdr_error_map);
|
||||
}
|
||||
if (rx_hdr->wp_api_rx_hdr_error_map & 1<<WP_ABORT_ERROR_BIT) {
|
||||
printf("Span: %d, Chan: %d rx abort error 0x%02X\n",chan->spanno,chan->channo,rx_hdr->wp_api_rx_hdr_error_map);
|
||||
}
|
||||
if (rx_hdr->wp_api_rx_hdr_error_map & 1<<WP_FRAME_ERROR_BIT) {
|
||||
printf("Span: %d, Chan: %d rx framing error 0x%02X\n",chan->spanno,chan->channo,rx_hdr->wp_api_rx_hdr_error_map);
|
||||
}
|
||||
if (rx_hdr->wp_api_rx_hdr_error_map & 1<<WP_DMA_ERROR_BIT) {
|
||||
printf("Span: %d, Chan: %d rx dma error 0x%02X\n",chan->spanno,chan->channo,rx_hdr->wp_api_rx_hdr_error_map);
|
||||
}
|
||||
//return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
>>>>>>> .r292
|
||||
Rx_count++;
|
||||
|
||||
if (verbose){
|
||||
print_rxdata(rx_buffer, Rx_lgth,rx_hdr);
|
||||
}
|
||||
|
||||
if (stats_period && Rx_count % stats_period == 0) {
|
||||
sangoma_print_stats(dev_fd);
|
||||
}
|
||||
|
||||
/* use Rx_counter as "write" events trigger: */
|
||||
if(rbs_events == 1 && (Rx_count % 400) == 0){
|
||||
/* bitmap - set as needed: WAN_RBS_SIG_A | WAN_RBS_SIG_B | WAN_RBS_SIG_C | WAN_RBS_SIG_D;
|
||||
|
||||
In this example make bits A and B to change each time,
|
||||
so it's easy to see the change on the receiving side.
|
||||
*/
|
||||
if(rx_rbs_bits == WAN_RBS_SIG_A){
|
||||
rx_rbs_bits = WAN_RBS_SIG_B;
|
||||
}else{
|
||||
rx_rbs_bits = WAN_RBS_SIG_A;
|
||||
}
|
||||
printf("Writing RBS bits (0x%X)...\n", rx_rbs_bits);
|
||||
sangoma_tdm_write_rbs(dev_fd, &tdm_api,
|
||||
chan->channo,
|
||||
rx_rbs_bits);
|
||||
}
|
||||
|
||||
/* if user needs Rx data to be written into a file: */
|
||||
if(files_used & RX_FILE_USED){
|
||||
write_data_to_file(rx_buffer, Rx_lgth);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn int write_data(uint32_t dev_index, wp_api_hdr_t *tx_hdr, void *tx_data, int tx_len)
|
||||
\brief Transmit a data buffer to a device.
|
||||
\param dev_index device index number associated with device file descriptor
|
||||
\param tx_hdr pointer to a wp_api_hdr_t
|
||||
\param tx_data pointer to a data buffer
|
||||
\param tx_len tx data buffer len
|
||||
\return 0 - Ok otherwise Error
|
||||
*/
|
||||
int write_data(uint32_t dev_index, wp_api_hdr_t *tx_hdr, void *tx_buffer, int tx_len)
|
||||
{
|
||||
sng_fd_t dev_fd = sangoma_wait_obj_get_fd(sangoma_wait_objects[dev_index]);
|
||||
sangoma_chan_t *chan = sangoma_wait_obj_get_context(sangoma_wait_objects[dev_index]);
|
||||
int err;
|
||||
static int Tx_count = 0;
|
||||
|
||||
if (hdlc_repeat) {
|
||||
tx_hdr->wp_api_tx_hdr_hdlc_rpt_len=4;
|
||||
memset(tx_hdr->wp_api_tx_hdr_hdlc_rpt_data,Tx_count,4);
|
||||
}
|
||||
|
||||
/* write a message */
|
||||
err = sangoma_writemsg(
|
||||
dev_fd,
|
||||
tx_hdr, /* header buffer */
|
||||
sizeof(wp_api_hdr_t), /* header size */
|
||||
tx_buffer, /* data buffer */
|
||||
tx_len, /* DATA size */
|
||||
0);
|
||||
|
||||
if (err <= 0){
|
||||
printf("Span: %d, Chan: %d: Failed to send!\n",
|
||||
chan->spanno,
|
||||
chan->channo);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Tx_count++;
|
||||
if (verbose){
|
||||
printf("Packet sent: counter: %i, len: %i, errors %i\n", Tx_count, err, tx_hdr->wp_api_tx_hdr_errors);
|
||||
}else{
|
||||
if(Tx_count && (!(Tx_count % 1000))){
|
||||
printf("Packet sent: counter: %i, len: %i\n", Tx_count, err);
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
if(tx_cnt && Tx_count >= tx_cnt){
|
||||
write_enable=0;
|
||||
printf("Disabling POLLOUT...\n");
|
||||
/* No need for POLLOUT, turn it off!! If not turned off, and we
|
||||
* have nothing for transmission, sangoma_socket_waitfor() will return
|
||||
* immediately, creating a busy loop. */
|
||||
//sangoma_wait_objects[dev_index].flags_in &= (~POLLOUT);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn int handle_data(uint32_t dev_index, int flags_out)
|
||||
\brief Read data buffer from the device and transmit it back down.
|
||||
\param dev_index device index number associated with device file descriptor
|
||||
\return 0 - Ok otherwise Error
|
||||
|
||||
Read data buffer from a device.
|
||||
*/
|
||||
int handle_data(uint32_t dev_index, int flags_out)
|
||||
{
|
||||
wp_api_hdr_t rxhdr;
|
||||
int err=0;
|
||||
|
||||
memset(&rxhdr, 0, sizeof(rxhdr));
|
||||
|
||||
#if 0
|
||||
printf("%s(): span: %d, chan: %d\n", __FUNCTION__,
|
||||
sangoma_wait_objects[dev_index].span, sangoma_wait_objects[dev_index].chan);
|
||||
#endif
|
||||
|
||||
if(flags_out & POLLIN){
|
||||
if(read_data(dev_index, &rxhdr, rxdata, MAX_NO_DATA_BYTES_IN_FRAME) == 0){
|
||||
if(rx2tx){
|
||||
/* Send back received data (create a "software loopback"), just a test. */
|
||||
return write_data(dev_index, &rxhdr, rxdata,rxhdr.data_length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( (flags_out & POLLOUT) && write_enable ){
|
||||
|
||||
wp_api_hdr_t txhdr;
|
||||
static unsigned char tx_test_byte = 0;
|
||||
|
||||
memset(&txhdr, 0, sizeof(txhdr));
|
||||
txhdr.data_length = (unsigned short)tx_size;/* use '-txsize' command line option to change 'tx_size' */
|
||||
|
||||
/* set data which will be transmitted */
|
||||
memset(txdata, tx_test_byte, txhdr.data_length);
|
||||
|
||||
err = write_data(dev_index, &txhdr, txdata, tx_size);
|
||||
if (err== 0) {
|
||||
tx_test_byte++;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn int decode_api_event (wp_api_event_t *wp_tdm_api_event)
|
||||
\brief Handle API Event
|
||||
\param wp_tdm_api_event
|
||||
*/
|
||||
static void decode_api_event(wp_api_event_t *wp_tdm_api_event)
|
||||
{
|
||||
printf("%s(): span: %d, chan: %d\n", __FUNCTION__,
|
||||
wp_tdm_api_event->span, wp_tdm_api_event->channel);
|
||||
|
||||
switch(wp_tdm_api_event->wp_api_event_type)
|
||||
{
|
||||
case WP_API_EVENT_DTMF:/* DTMF detected by Hardware */
|
||||
printf("DTMF Event: Channel: %d, Digit: %c (Port: %s, Type:%s)!\n",
|
||||
wp_tdm_api_event->channel,
|
||||
wp_tdm_api_event->wp_api_event_dtmf_digit,
|
||||
(wp_tdm_api_event->wp_api_event_dtmf_port == WAN_EC_CHANNEL_PORT_ROUT)?"ROUT":"SOUT",
|
||||
(wp_tdm_api_event->wp_api_event_dtmf_type == WAN_EC_TONE_PRESENT)?"PRESENT":"STOP");
|
||||
break;
|
||||
|
||||
case WP_API_EVENT_RXHOOK:
|
||||
printf("RXHOOK Event: Channel: %d, %s! (0x%X)\n",
|
||||
wp_tdm_api_event->channel,
|
||||
WAN_EVENT_RXHOOK_DECODE(wp_tdm_api_event->wp_api_event_hook_state),
|
||||
wp_tdm_api_event->wp_api_event_hook_state);
|
||||
break;
|
||||
|
||||
case WP_API_EVENT_RING_DETECT:
|
||||
printf("RING Event: %s! (0x%X)\n",
|
||||
WAN_EVENT_RING_DECODE(wp_tdm_api_event->wp_api_event_ring_state),
|
||||
wp_tdm_api_event->wp_api_event_ring_state);
|
||||
break;
|
||||
|
||||
case WP_API_EVENT_RING_TRIP_DETECT:
|
||||
printf("RING TRIP Event: %s! (0x%X)\n",
|
||||
WAN_EVENT_RING_TRIP_DECODE(wp_tdm_api_event->wp_api_event_ring_state),
|
||||
wp_tdm_api_event->wp_api_event_ring_state);
|
||||
break;
|
||||
|
||||
case WP_API_EVENT_RBS:
|
||||
printf("RBS Event: Channel: %d, 0x%X!\n",
|
||||
wp_tdm_api_event->channel,
|
||||
wp_tdm_api_event->wp_api_event_rbs_bits);
|
||||
printf( "RX RBS: A:%1d B:%1d C:%1d D:%1d\n",
|
||||
(wp_tdm_api_event->wp_api_event_rbs_bits & WAN_RBS_SIG_A) ? 1 : 0,
|
||||
(wp_tdm_api_event->wp_api_event_rbs_bits & WAN_RBS_SIG_B) ? 1 : 0,
|
||||
(wp_tdm_api_event->wp_api_event_rbs_bits & WAN_RBS_SIG_C) ? 1 : 0,
|
||||
(wp_tdm_api_event->wp_api_event_rbs_bits & WAN_RBS_SIG_D) ? 1 : 0);
|
||||
break;
|
||||
|
||||
case WP_API_EVENT_LINK_STATUS:
|
||||
printf("Link Status Event: %s! (0x%X)\n",
|
||||
WAN_EVENT_LINK_STATUS_DECODE(wp_tdm_api_event->wp_api_event_link_status),
|
||||
wp_tdm_api_event->wp_api_event_link_status);
|
||||
break;
|
||||
|
||||
case WP_API_EVENT_ALARM:
|
||||
printf("New Alarm State: %s! (0x%X)\n", (wp_tdm_api_event->wp_api_event_alarm == 0?"Off":"On"),
|
||||
wp_tdm_api_event->wp_api_event_alarm);
|
||||
break;
|
||||
|
||||
case WP_API_EVENT_POLARITY_REVERSE:
|
||||
printf("Polarity Reversal Event : %s! (0x%X)\n",
|
||||
WP_API_EVENT_POLARITY_REVERSE_DECODE(wp_tdm_api_event->wp_api_event_polarity_reverse),
|
||||
wp_tdm_api_event->wp_api_event_polarity_reverse);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Unknown TDM API Event: %d\n", wp_tdm_api_event->wp_api_event_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn int handle_tdm_event(uint32_t dev_index)
|
||||
\brief Read Event buffer from the device
|
||||
\param dev_index device index number associated with device file descriptor
|
||||
\return 0 - Ok otherwise Error
|
||||
|
||||
An EVENT has occoured. Execute a system call to read the EVENT
|
||||
on a device.
|
||||
*/
|
||||
int handle_tdm_event(uint32_t dev_index)
|
||||
{
|
||||
wanpipe_api_t tdm_api;
|
||||
sng_fd_t dev_fd = sangoma_wait_obj_get_fd(sangoma_wait_objects[dev_index]);
|
||||
|
||||
#if 0
|
||||
printf("%s(): dev_index: %d, dev_fd: 0x%p\n", __FUNCTION__, dev_index, dev_fd);
|
||||
#endif
|
||||
|
||||
memset(&tdm_api, 0x00, sizeof(tdm_api));
|
||||
|
||||
if(sangoma_read_event(dev_fd, &tdm_api)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
decode_api_event(&tdm_api.wp_cmd.event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn void handle_span_chan(int open_device_counter)
|
||||
\brief Write data buffer into a file
|
||||
\param open_device_counter number of opened devices
|
||||
\return void
|
||||
|
||||
This function will wait on all opened devices.
|
||||
This example will wait for RX and EVENT signals.
|
||||
In case of POLLIN - rx data available
|
||||
In case of POLLPRI - event is available
|
||||
*/
|
||||
void handle_span_chan(int open_device_counter)
|
||||
{
|
||||
int iResult, i;
|
||||
u_int32_t input_flags[TEST_NUMBER_OF_OBJECTS];
|
||||
u_int32_t output_flags[TEST_NUMBER_OF_OBJECTS];
|
||||
|
||||
printf("\n\nSpan/Chan Handler: RxEnable=%s, TxEnable=%s, TxCnt=%i, TxLen=%i, rx2tx=%s\n",
|
||||
(read_enable? "Yes":"No"), (write_enable?"Yes":"No"),tx_cnt,tx_size, (rx2tx?"Yes":"No"));
|
||||
|
||||
for (i = 0; i < open_device_counter; i++) {
|
||||
input_flags[i] = poll_events_bitmap;
|
||||
}
|
||||
|
||||
/* Main Rx/Tx/Event loop */
|
||||
while(!application_termination_flag)
|
||||
{
|
||||
iResult = sangoma_waitfor_many(sangoma_wait_objects,
|
||||
input_flags,
|
||||
output_flags,
|
||||
open_device_counter /* number of wait objects */,
|
||||
5000 /* wait timeout, in milliseconds */);
|
||||
switch(iResult)
|
||||
{
|
||||
case SANG_STATUS_APIPOLL_TIMEOUT:
|
||||
/* timeout (not an error) */
|
||||
{
|
||||
sng_fd_t dev_fd = sangoma_wait_obj_get_fd(sangoma_wait_objects[0]);
|
||||
sangoma_print_stats(dev_fd);
|
||||
}
|
||||
printf("Timeout\n");
|
||||
continue;
|
||||
|
||||
case SANG_STATUS_SUCCESS:
|
||||
for(i = 0; i < open_device_counter; i++){
|
||||
|
||||
/* a wait object was signaled */
|
||||
if(output_flags[i] & POLLPRI){
|
||||
/* got tdm api event */
|
||||
if(handle_tdm_event(i)){
|
||||
printf("Error in handle_tdm_event()!\n");
|
||||
application_termination_flag=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(output_flags[i] & (POLLIN | POLLOUT)){
|
||||
/* rx data OR a free tx buffer available */
|
||||
if(handle_data(i, output_flags[i])){
|
||||
printf("Error in handle_data()!\n");
|
||||
//application_termination_flag=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}/* for() */
|
||||
break;
|
||||
|
||||
default:
|
||||
/* error */
|
||||
printf("Error: iResult: %s (%d)\n", SDLA_DECODE_SANG_STATUS(iResult), iResult);
|
||||
return;
|
||||
}
|
||||
|
||||
}/* while() */
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn int write_data_to_file(unsigned char *data, unsigned int data_length)
|
||||
\brief Write data buffer into a file
|
||||
\param data data buffer
|
||||
\param data_length length of a data buffer
|
||||
\return data_length = ok otherwise error
|
||||
|
||||
*/
|
||||
int write_data_to_file(unsigned char *data, unsigned int data_length)
|
||||
{
|
||||
if(pRxFile == NULL){
|
||||
return 1;
|
||||
}
|
||||
|
||||
return fwrite(data, 1, data_length, pRxFile);
|
||||
}
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
/*
|
||||
* TerminateHandler() - this handler is called by the system whenever user tries to terminate
|
||||
* the process with Ctrl+C, Ctrl+Break or closes the console window.
|
||||
* Perform a clean-up here.
|
||||
*/
|
||||
BOOL TerminateHandler(DWORD dwCtrlType)
|
||||
{
|
||||
printf("\nProcess terminated by user request.\n");
|
||||
application_termination_flag = 1;
|
||||
/* do the cleanup before exiting: */
|
||||
cleanup();
|
||||
/* return FALSE so the system will call the dafult handler which will terminate the process. */
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
/*!
|
||||
\fn void TerminateHandler (int sig)
|
||||
\brief Signal handler for graceful shutdown
|
||||
\param sig signal
|
||||
*/
|
||||
void TerminateHandler (int sig)
|
||||
{
|
||||
printf("\nProcess terminated by user request.\n");
|
||||
application_termination_flag = 1;
|
||||
/* do the cleanup before exiting: */
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\fn void cleanup()
|
||||
\brief Protperly shutdown single device
|
||||
\param dev_no device index number
|
||||
\return void
|
||||
|
||||
*/
|
||||
void cleanup()
|
||||
{
|
||||
int dev_no;
|
||||
sng_fd_t fd;
|
||||
sangoma_chan_t *chan;
|
||||
sangoma_wait_obj_t *sng_wait_object;
|
||||
wanpipe_api_t tdm_api;
|
||||
|
||||
/* do the cleanup before exiting: */
|
||||
for(dev_no = 0; dev_no < TEST_NUMBER_OF_OBJECTS; dev_no++){
|
||||
|
||||
sng_wait_object = sangoma_wait_objects[dev_no];
|
||||
if(!sng_wait_object){
|
||||
continue;
|
||||
}
|
||||
chan = sangoma_wait_obj_get_context(sng_wait_object);
|
||||
printf("%s(): span: %d, chan: %d ...\n", __FUNCTION__,
|
||||
chan->channo,
|
||||
chan->spanno);
|
||||
|
||||
fd = sangoma_wait_obj_get_fd(sng_wait_object);
|
||||
memset(&tdm_api, 0x00, sizeof(tdm_api));
|
||||
|
||||
if(dtmf_enable_octasic == 1){
|
||||
/* Disable dtmf detection on Octasic chip */
|
||||
sangoma_tdm_disable_dtmf_events(fd, &tdm_api);
|
||||
}
|
||||
|
||||
if(dtmf_enable_remora == 1){
|
||||
/* Disable dtmf detection on Sangoma's Remora SLIC chip */
|
||||
sangoma_tdm_disable_rm_dtmf_events(fd, &tdm_api);
|
||||
}
|
||||
|
||||
if(remora_hook == 1){
|
||||
sangoma_tdm_disable_rxhook_events(fd, &tdm_api);
|
||||
}
|
||||
|
||||
if(rbs_events == 1){
|
||||
sangoma_tdm_disable_rbs_events(fd, &tdm_api);
|
||||
}
|
||||
|
||||
sangoma_wait_obj_delete(&sng_wait_object);
|
||||
|
||||
sangoma_close(&fd);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\fn int open_sangoma_device()
|
||||
\brief Open a single span chan device
|
||||
\return 0 ok otherise error.
|
||||
|
||||
This function will open a single span chan.
|
||||
|
||||
However it can be rewritten to iterate for all spans and chans and try to
|
||||
open all existing wanpipe devices.
|
||||
|
||||
For each opened device, a wait object will be initialized.
|
||||
For each device, configure the chunk size for tx/rx
|
||||
enable events such as DTMF/RBS ...etc
|
||||
*/
|
||||
int open_sangoma_device()
|
||||
{
|
||||
int span, chan, err = 0, open_dev_cnt = 0;
|
||||
sangoma_status_t status;
|
||||
sng_fd_t dev_fd = INVALID_HANDLE_VALUE;
|
||||
wanpipe_api_t tdm_api;
|
||||
|
||||
span = wanpipe_port_no;
|
||||
chan = wanpipe_if_no;
|
||||
|
||||
/* span and chan are 1-based */
|
||||
dev_fd = sangoma_open_api_span_chan(span, chan);
|
||||
if( dev_fd == INVALID_HANDLE_VALUE){
|
||||
printf("Warning: Failed to open span %d, chan %d\n", span , chan);
|
||||
return 1;
|
||||
}else{
|
||||
printf("Successfuly opened span %d, chan %d\n", span , chan);
|
||||
}
|
||||
|
||||
memset(&tdm_api, 0x00, sizeof(tdm_api));
|
||||
|
||||
status = sangoma_wait_obj_create(&sangoma_wait_objects[open_dev_cnt], dev_fd, SANGOMA_DEVICE_WAIT_OBJ);
|
||||
if(status != SANG_STATUS_SUCCESS){
|
||||
printf("Error: Failed to create 'sangoma_wait_object'!\n");
|
||||
return 1;
|
||||
}
|
||||
sangoma_channels[open_dev_cnt].channo = chan;
|
||||
sangoma_channels[open_dev_cnt].spanno = span;
|
||||
sangoma_wait_obj_set_context(sangoma_wait_objects[open_dev_cnt], &sangoma_channels[open_dev_cnt]);
|
||||
/* open_dev_cnt++; */
|
||||
|
||||
if((err = sangoma_get_full_cfg(dev_fd, &tdm_api))){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(set_codec_slinear){
|
||||
printf("Setting SLINEAR codec\n");
|
||||
if((err=sangoma_tdm_set_codec(dev_fd, &tdm_api, WP_SLINEAR))){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(set_codec_none){
|
||||
printf("Disabling codec\n");
|
||||
if((err=sangoma_tdm_set_codec(dev_fd, &tdm_api, WP_NONE))){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(usr_period){
|
||||
printf("Setting user period: %d\n", usr_period);
|
||||
if((err=sangoma_tdm_set_usr_period(dev_fd, &tdm_api, usr_period))){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(set_codec_slinear || usr_period || set_codec_none){
|
||||
/* display new configuration AFTER it was changed */
|
||||
if((err=sangoma_get_full_cfg(dev_fd, &tdm_api))){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(dtmf_enable_octasic == 1){
|
||||
poll_events_bitmap |= POLLPRI;
|
||||
/* enable dtmf detection on Octasic chip */
|
||||
if((err=sangoma_tdm_enable_dtmf_events(dev_fd, &tdm_api))){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(dtmf_enable_remora == 1){
|
||||
poll_events_bitmap |= POLLPRI;
|
||||
/* enable dtmf detection on Sangoma's Remora SLIC chip (A200 ONLY) */
|
||||
if((err=sangoma_tdm_enable_rm_dtmf_events(dev_fd, &tdm_api))){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(remora_hook == 1){
|
||||
poll_events_bitmap |= POLLPRI;
|
||||
if((err=sangoma_tdm_enable_rxhook_events(dev_fd, &tdm_api))){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(rbs_events == 1){
|
||||
poll_events_bitmap |= POLLPRI;
|
||||
if((err=sangoma_tdm_enable_rbs_events(dev_fd, &tdm_api, 20))){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (buffer_multiplier) {
|
||||
printf("Setting buffer multiplier to %i\n",buffer_multiplier);
|
||||
err=sangoma_tdm_set_buffer_multiplier(dev_fd,&tdm_api,buffer_multiplier);
|
||||
if (err) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Device Config RxQ=%i TxQ=%i \n",
|
||||
sangoma_get_rx_queue_sz(dev_fd,&tdm_api),
|
||||
sangoma_get_rx_queue_sz(dev_fd,&tdm_api));
|
||||
|
||||
sangoma_set_rx_queue_sz(dev_fd,&tdm_api,20);
|
||||
sangoma_set_tx_queue_sz(dev_fd,&tdm_api,30);
|
||||
|
||||
printf("Device Config RxQ=%i TxQ=%i \n",
|
||||
sangoma_get_rx_queue_sz(dev_fd,&tdm_api),
|
||||
sangoma_get_tx_queue_sz(dev_fd,&tdm_api));
|
||||
|
||||
sangoma_flush_bufs(dev_fd,&tdm_api);
|
||||
|
||||
sangoma_print_stats(dev_fd);
|
||||
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn int __cdecl main(int argc, char* argv[])
|
||||
\brief Main function that starts the sample code
|
||||
\param argc number of arguments
|
||||
\param argv argument list
|
||||
*/
|
||||
int __cdecl main(int argc, char* argv[])
|
||||
{
|
||||
int proceed, i;
|
||||
|
||||
proceed=init_args(argc,argv);
|
||||
if (proceed != WAN_TRUE){
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* register Ctrl+C handler - we want a clean termination */
|
||||
#if defined(__WINDOWS__)
|
||||
if (!SetConsoleCtrlHandler(TerminateHandler, TRUE)) {
|
||||
printf("ERROR : Unable to register terminate handler ( %d ).\nProcess terminated.\n",
|
||||
GetLastError());
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
signal(SIGHUP,TerminateHandler);
|
||||
signal(SIGTERM,TerminateHandler);
|
||||
#endif
|
||||
|
||||
for(i = 0; i < TEST_NUMBER_OF_OBJECTS; i++){
|
||||
sangoma_wait_objects[i] = NULL;
|
||||
}
|
||||
|
||||
poll_events_bitmap = 0;
|
||||
if(read_enable == 1){
|
||||
poll_events_bitmap |= POLLIN;
|
||||
}
|
||||
|
||||
if(write_enable == 1 && rx2tx == 1){
|
||||
/* These two options are mutually exclusive because 'rx2tx' option
|
||||
* indicates "use Reciever as the timing source for Transmitter". */
|
||||
write_enable = 0;
|
||||
}
|
||||
|
||||
if(write_enable == 1){
|
||||
poll_events_bitmap |= POLLOUT;
|
||||
}
|
||||
|
||||
/* Front End connect/disconnect, and other events, such as DTMF... */
|
||||
poll_events_bitmap |= (POLLHUP | POLLPRI);
|
||||
#if defined(__WINDOWS__)
|
||||
printf("Enabling Poll Events:\n");
|
||||
print_poll_event_bitmap(poll_events_bitmap);
|
||||
#endif
|
||||
printf("Connecting to Port/Span: %d, Interface/Chan: %d\n",
|
||||
wanpipe_port_no, wanpipe_if_no);
|
||||
|
||||
|
||||
if(open_sangoma_device()){
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("********************************\n");
|
||||
printf("files_used: 0x%x\n", files_used);
|
||||
printf("********************************\n");
|
||||
if(files_used & RX_FILE_USED){
|
||||
pRxFile = fopen( (const char*)&rx_file[0], "wb" );
|
||||
if(pRxFile == NULL){
|
||||
printf("Can't open Rx file: [%s]!!\n", rx_file);
|
||||
}else{
|
||||
printf("Open Rx file: %s. OK.\n", rx_file);
|
||||
}
|
||||
}
|
||||
|
||||
handle_span_chan(1 /* handle a single device */);
|
||||
|
||||
/* returned from main loop, do the cleanup before exiting: */
|
||||
cleanup();
|
||||
|
||||
printf("\nSample application exiting.(press any key)\n");
|
||||
_getch();
|
||||
return 0;
|
||||
}
|
|
@ -23,11 +23,12 @@
|
|||
char read_enable=0;
|
||||
char write_enable=0;
|
||||
char primary_enable=0;
|
||||
int tx_cnt=1;
|
||||
int rx_cnt=1;
|
||||
int tx_cnt=0;
|
||||
int rx_cnt=0;
|
||||
int tx_size=10;
|
||||
int tx_delay=0;
|
||||
int tx_data=-1;
|
||||
int buffer_multiplier=0;
|
||||
|
||||
unsigned char tx_file[WAN_IFNAME_SZ];
|
||||
unsigned char rx_file[WAN_IFNAME_SZ];
|
||||
|
@ -65,6 +66,7 @@ int rbs_events = 0;
|
|||
int rx2tx = 0;
|
||||
int flush_period=0;
|
||||
int stats_period=0;
|
||||
int hdlc_repeat=0;
|
||||
|
||||
unsigned long parse_active_channel(char* val);
|
||||
|
||||
|
@ -79,7 +81,7 @@ int init_args(int argc, char *argv[])
|
|||
|
||||
for (i = 0; i < argc; i++){
|
||||
|
||||
if (!strcmp(argv[i],"-i")){
|
||||
if (!strcmp(argv[i],"-i") || !strcmp(argv[i],"-chan")){
|
||||
|
||||
if (i+1 > argc-1){
|
||||
printf("ERROR: Number of Interfaces was NOT specified!\n");
|
||||
|
@ -87,7 +89,7 @@ int init_args(int argc, char *argv[])
|
|||
}
|
||||
wanpipe_if_no = atoi(argv[i+1]);
|
||||
|
||||
}else if (!strcmp(argv[i],"-p")){
|
||||
}else if (!strcmp(argv[i],"-p") || !strcmp(argv[i],"-span")){
|
||||
|
||||
if (i+1 > argc-1){
|
||||
printf("ERROR: Number of Ports was NOT specified!\n");
|
||||
|
@ -102,6 +104,8 @@ int init_args(int argc, char *argv[])
|
|||
}else if (!strcmp(argv[i],"-w")){
|
||||
write_enable=1;
|
||||
c_cnt=1;
|
||||
}else if (!strcmp(argv[i],"-hdlc_repeat")){
|
||||
hdlc_repeat=1;
|
||||
|
||||
}else if (!strcmp(argv[i],"-pri")){
|
||||
primary_enable=1;
|
||||
|
@ -219,6 +223,19 @@ int init_args(int argc, char *argv[])
|
|||
}else if (!strcmp(argv[i],"-verbose")){
|
||||
verbose=1;
|
||||
|
||||
}else if (!strcmp(argv[i],"-buffer_multiplier")) {
|
||||
if (i+1 > argc-1){
|
||||
printf("ERROR: Invalid prot!\n");
|
||||
return WAN_FALSE;
|
||||
}
|
||||
|
||||
if(isdigit(argv[i+1][0])){
|
||||
buffer_multiplier = atoi(argv[i+1]);
|
||||
}else{
|
||||
printf("ERROR: Invalid prot, must be a digit!\n");
|
||||
return WAN_FALSE;
|
||||
}
|
||||
|
||||
}else if (!strcmp(argv[i],"-prot")){
|
||||
if (i+1 > argc-1){
|
||||
printf("ERROR: Invalid prot!\n");
|
||||
|
@ -365,13 +382,13 @@ int init_args(int argc, char *argv[])
|
|||
static char api_usage[]="\n"
|
||||
"\n"
|
||||
"<options>:\n"
|
||||
" -p <port number> #port/span number\n"
|
||||
" -i <if number> #if/chan number\n"
|
||||
" -r #read enable\n"
|
||||
" -w #write eable\n"
|
||||
" -span <port/span number> #port/span number\n"
|
||||
" -chan <if/chan number> #if/chan number\n"
|
||||
" -r #read enable\n"
|
||||
" -w #write eable\n"
|
||||
"\n"
|
||||
" example 1: sangoma_c -p 1 -i 1 -r\n"
|
||||
" in this example Wanpipe 1, Interface 1 will be used for reading data\n"
|
||||
" example 1: sangoma_c -span 1 -chan 1 -r -verbose\n"
|
||||
" in this example Wanpipe span 1, Interface chan 1 will be used for reading data\n"
|
||||
"\n"
|
||||
"<extra options>\n"
|
||||
" -txcnt <digit> #number of tx packets (Dflt: 1)\n"
|
||||
|
|
|
@ -48,6 +48,8 @@ extern int rbs_events;
|
|||
extern int rx2tx;
|
||||
extern int flush_period;
|
||||
extern int stats_period;
|
||||
extern int hdlc_repeat;
|
||||
extern int buffer_multiplier;
|
||||
|
||||
extern unsigned char tx_file[WAN_IFNAME_SZ];
|
||||
extern unsigned char rx_file[WAN_IFNAME_SZ];
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,13 +1,19 @@
|
|||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 45
|
||||
/svn/libsangoma/!svn/ver/270/trunk/sample_cpp
|
||||
/svn/libsangoma/!svn/ver/291/trunk/sample_cpp
|
||||
END
|
||||
sangoma_port.h
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 60
|
||||
/svn/libsangoma/!svn/ver/248/trunk/sample_cpp/sangoma_port.h
|
||||
/svn/libsangoma/!svn/ver/278/trunk/sample_cpp/sangoma_port.h
|
||||
END
|
||||
sources
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 53
|
||||
/svn/libsangoma/!svn/ver/291/trunk/sample_cpp/sources
|
||||
END
|
||||
sample.vcproj
|
||||
K 25
|
||||
|
@ -15,17 +21,11 @@ svn:wc:ra_dav:version-url
|
|||
V 59
|
||||
/svn/libsangoma/!svn/ver/248/trunk/sample_cpp/sample.vcproj
|
||||
END
|
||||
sources
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 53
|
||||
/svn/libsangoma/!svn/ver/248/trunk/sample_cpp/sources
|
||||
END
|
||||
sangoma_interface.cpp
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 67
|
||||
/svn/libsangoma/!svn/ver/270/trunk/sample_cpp/sangoma_interface.cpp
|
||||
/svn/libsangoma/!svn/ver/288/trunk/sample_cpp/sangoma_interface.cpp
|
||||
END
|
||||
sample_linux_compat.h
|
||||
K 25
|
||||
|
@ -37,13 +37,13 @@ sangoma_interface.h
|
|||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 65
|
||||
/svn/libsangoma/!svn/ver/270/trunk/sample_cpp/sangoma_interface.h
|
||||
/svn/libsangoma/!svn/ver/278/trunk/sample_cpp/sangoma_interface.h
|
||||
END
|
||||
sangoma_port_configurator.cpp
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 75
|
||||
/svn/libsangoma/!svn/ver/268/trunk/sample_cpp/sangoma_port_configurator.cpp
|
||||
/svn/libsangoma/!svn/ver/279/trunk/sample_cpp/sangoma_port_configurator.cpp
|
||||
END
|
||||
compile.bat
|
||||
K 25
|
||||
|
@ -61,13 +61,13 @@ sangoma_port_configurator.h
|
|||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 73
|
||||
/svn/libsangoma/!svn/ver/268/trunk/sample_cpp/sangoma_port_configurator.h
|
||||
/svn/libsangoma/!svn/ver/275/trunk/sample_cpp/sangoma_port_configurator.h
|
||||
END
|
||||
sample.cpp
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 56
|
||||
/svn/libsangoma/!svn/ver/270/trunk/sample_cpp/sample.cpp
|
||||
/svn/libsangoma/!svn/ver/288/trunk/sample_cpp/sample.cpp
|
||||
END
|
||||
sangoma_cthread.h
|
||||
K 25
|
||||
|
@ -79,13 +79,13 @@ sample.h
|
|||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 54
|
||||
/svn/libsangoma/!svn/ver/269/trunk/sample_cpp/sample.h
|
||||
/svn/libsangoma/!svn/ver/288/trunk/sample_cpp/sample.h
|
||||
END
|
||||
sangoma_port.cpp
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 62
|
||||
/svn/libsangoma/!svn/ver/248/trunk/sample_cpp/sangoma_port.cpp
|
||||
/svn/libsangoma/!svn/ver/286/trunk/sample_cpp/sangoma_port.cpp
|
||||
END
|
||||
Makefile.Linux
|
||||
K 25
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
8
|
||||
|
||||
dir
|
||||
273
|
||||
293
|
||||
https://www.sangomapbx.com/svn/libsangoma/trunk/sample_cpp
|
||||
https://www.sangomapbx.com/svn/libsangoma
|
||||
|
||||
|
||||
|
||||
2010-03-17T17:19:58.104959Z
|
||||
270
|
||||
2010-06-16T16:45:22.358768Z
|
||||
291
|
||||
davidr
|
||||
has-props
|
||||
|
||||
|
@ -32,10 +32,10 @@ file
|
|||
|
||||
|
||||
|
||||
2010-02-10T23:05:43.000000Z
|
||||
64b4431c40f821db3c3ec77054f084c0
|
||||
2010-01-22T21:30:47.609627Z
|
||||
248
|
||||
2010-05-18T21:27:49.000000Z
|
||||
f3310f38d215e71ef19ee59d33c0c458
|
||||
2010-05-14T20:03:16.936101Z
|
||||
278
|
||||
davidr
|
||||
|
||||
sample.vcproj
|
||||
|
@ -57,10 +57,10 @@ file
|
|||
|
||||
|
||||
|
||||
2010-02-10T23:05:43.000000Z
|
||||
3bfbd303967164dde107c6accf8d9f84
|
||||
2010-01-22T21:30:47.609627Z
|
||||
248
|
||||
2010-06-17T04:11:26.000000Z
|
||||
1b8b6c522d904f33d986cb1c667d37e6
|
||||
2010-06-16T16:45:22.358768Z
|
||||
291
|
||||
davidr
|
||||
|
||||
sangoma_interface.cpp
|
||||
|
@ -69,10 +69,10 @@ file
|
|||
|
||||
|
||||
|
||||
2010-03-23T16:14:34.000000Z
|
||||
380486fdf6a516f0415b3d0dc8c58f78
|
||||
2010-03-17T17:19:58.104959Z
|
||||
270
|
||||
2010-06-15T17:24:48.000000Z
|
||||
24af2258baf4305756df5b3f7f0ead6b
|
||||
2010-06-14T19:08:36.321535Z
|
||||
288
|
||||
davidr
|
||||
|
||||
sample_linux_compat.h
|
||||
|
@ -93,10 +93,10 @@ file
|
|||
|
||||
|
||||
|
||||
2010-03-23T16:14:34.000000Z
|
||||
72a11cbee60d7ac08fe0e09d18d34b43
|
||||
2010-03-17T17:19:58.104959Z
|
||||
270
|
||||
2010-05-18T21:27:49.000000Z
|
||||
6bd775531d9264b8c89af6956f133ca9
|
||||
2010-05-14T20:03:16.936101Z
|
||||
278
|
||||
davidr
|
||||
|
||||
sangoma_port_configurator.cpp
|
||||
|
@ -105,11 +105,11 @@ file
|
|||
|
||||
|
||||
|
||||
2010-03-23T16:14:34.000000Z
|
||||
dd259c7c57987730dc55b0c6b67e9497
|
||||
2010-03-10T21:56:50.328276Z
|
||||
268
|
||||
jpatel
|
||||
2010-06-04T16:18:07.000000Z
|
||||
7b4b0e298f916258cbd2ef3e6c5b2e74
|
||||
2010-05-28T23:22:41.955986Z
|
||||
279
|
||||
davidr
|
||||
|
||||
compile.bat
|
||||
file
|
||||
|
@ -141,10 +141,10 @@ file
|
|||
|
||||
|
||||
|
||||
2010-03-23T16:14:34.000000Z
|
||||
946fd40742fd52ca8775b538372956af
|
||||
2010-03-10T21:56:50.328276Z
|
||||
268
|
||||
2010-05-18T21:27:49.000000Z
|
||||
468db72af14d384b25eb30ec91ca2841
|
||||
2010-05-03T20:57:12.906314Z
|
||||
275
|
||||
jpatel
|
||||
|
||||
sample.cpp
|
||||
|
@ -153,10 +153,10 @@ file
|
|||
|
||||
|
||||
|
||||
2010-03-23T16:14:34.000000Z
|
||||
78341087eea6b46442f6bdd047eba2a8
|
||||
2010-03-17T17:19:58.104959Z
|
||||
270
|
||||
2010-06-15T17:24:48.000000Z
|
||||
b7c6eb4619987ebdd5f00ef8fb3f1a53
|
||||
2010-06-14T19:08:36.321535Z
|
||||
288
|
||||
davidr
|
||||
|
||||
sangoma_cthread.h
|
||||
|
@ -177,10 +177,10 @@ file
|
|||
|
||||
|
||||
|
||||
2010-03-23T16:14:34.000000Z
|
||||
c7026dce798297ddf34b7d592f7c5ac1
|
||||
2010-03-15T20:12:36.300714Z
|
||||
269
|
||||
2010-06-15T17:24:48.000000Z
|
||||
10d072dd323da3f8db2b123f08751ce2
|
||||
2010-06-14T19:08:36.321535Z
|
||||
288
|
||||
davidr
|
||||
|
||||
sangoma_port.cpp
|
||||
|
@ -189,10 +189,10 @@ file
|
|||
|
||||
|
||||
|
||||
2010-02-10T23:05:43.000000Z
|
||||
e7715c5d2deb029f1abef3bce2b71aba
|
||||
2010-01-22T21:30:47.609627Z
|
||||
248
|
||||
2010-06-14T16:38:14.000000Z
|
||||
9d6b5a506886857fc50242ed6514f07d
|
||||
2010-06-10T21:10:51.668331Z
|
||||
286
|
||||
davidr
|
||||
|
||||
Makefile.Linux
|
||||
|
|
|
@ -59,17 +59,12 @@ callback_functions_t callback_functions;
|
|||
* Prototypes & Defines
|
||||
*****************************************************************/
|
||||
|
||||
static int got_rx_data(void *sang_if_ptr, void *rx_data);
|
||||
static int got_rx_data(void *sang_if_ptr, void *rxhdr, void *rx_data);
|
||||
static void got_tdm_api_event(void *sang_if_ptr, void *event_data);
|
||||
#if USE_WP_LOGGER
|
||||
static void got_logger_event(void *sang_if_ptr, wp_logger_event_t *logger_event);
|
||||
#endif
|
||||
|
||||
typedef struct{
|
||||
void *sang_if_ptr;
|
||||
wp_api_event_t event;
|
||||
}TDM_API_EVENT_THREAD_PARAM;
|
||||
|
||||
|
||||
#if USE_STELEPHONY_API
|
||||
//Sangoma Telephony API (Stelephony.dll) provides the following telephony services:
|
||||
|
@ -88,13 +83,6 @@ CRITICAL_SECTION PrintCriticalSection;
|
|||
//critical section for TDM events
|
||||
CRITICAL_SECTION TdmEventCriticalSection;
|
||||
|
||||
#if defined (__WINDOWS__)
|
||||
DWORD TdmApiEventThreadFunc(LPDWORD lpdwParam);
|
||||
#else
|
||||
void *TdmApiEventThreadFunc(void *lpdwParam);
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* Debugging Macros
|
||||
*****************************************************************/
|
||||
|
@ -195,9 +183,9 @@ void PrintRxData(wp_api_hdr_t *hdr, void *pdata)
|
|||
if(program_settings.silent){
|
||||
if((rx_counter % 1000) == 0){
|
||||
INFO_MAIN("Rx counter: %d, Rx datlen: %d\n", rx_counter, datlen);
|
||||
#if 0
|
||||
#if 1
|
||||
INFO_MAIN("Timestamp: Seconds: %d, Microseconds: %d\n",
|
||||
hdr->wp_api_hdr_time_stamp_sec, hdr->wp_api_hdr_time_stamp_use);
|
||||
hdr->time_stamp_sec, hdr->time_stamp_usec);
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
|
@ -222,10 +210,13 @@ void PrintRxData(wp_api_hdr_t *hdr, void *pdata)
|
|||
|
||||
/*!
|
||||
\fn static int got_rx_data(void *sang_if_ptr, void *rx_data)
|
||||
\brief Callback function indicating data rx is pending
|
||||
\brief Callback function indicating data rx is pending.
|
||||
\param sang_if_ptr sangoma interface pointer
|
||||
\param rx_data API data element strcutre containt header + data
|
||||
\return 0 - ok non-zero - Error
|
||||
|
||||
This function must return as fast as possible
|
||||
because it is called from real time receiver thread.
|
||||
*/
|
||||
static int got_rx_data(void *sang_if_ptr, void *rxhdr, void *rx_data)
|
||||
{
|
||||
|
@ -267,71 +258,33 @@ static int got_rx_data(void *sang_if_ptr, void *rxhdr, void *rx_data)
|
|||
\param event_data API event element strcutre containt header + data
|
||||
\return 0 - ok non-zero - Error
|
||||
|
||||
Currently Windows launches a thread to handle the event, where
|
||||
Linux handles the event directly. Implementation is left to the user.
|
||||
|
||||
Handling of Events must be done OUTSIDE of the REAL-TIME Rx thread
|
||||
because it may make take a lot of time.
|
||||
Create a special thread for Event hadling Or push Event into
|
||||
a queue - implentation is left to the user.
|
||||
In this example event is handled directly.
|
||||
*/
|
||||
static void got_tdm_api_event(void *sang_if_ptr, void *event_data)
|
||||
{
|
||||
TDM_API_EVENT_THREAD_PARAM *param =
|
||||
(TDM_API_EVENT_THREAD_PARAM*)malloc(sizeof(TDM_API_EVENT_THREAD_PARAM));
|
||||
|
||||
if(param == NULL){
|
||||
ERR_MAIN("Failed to allocate memory for 'Event Thread parameter'!!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(¶m->event, event_data, sizeof(wp_api_event_t));
|
||||
param->sang_if_ptr = sang_if_ptr;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//Handling of Events must be done OUTSIDE of the REAL-TIME Rx thread//
|
||||
//because it may make take a lot of time. //
|
||||
//Create a special thread for Event hadling. //
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#if defined(__WINDOWS__)
|
||||
DWORD dwThreadId;
|
||||
|
||||
if(CreateThread(
|
||||
NULL, /* no security attributes */
|
||||
0, /* use default stack size */
|
||||
(LPTHREAD_START_ROUTINE)TdmApiEventThreadFunc, /* thread function */
|
||||
param, /* argument to thread function */
|
||||
0, /* use default creation flags */
|
||||
&dwThreadId /* returns the thread identifier */
|
||||
) == NULL){
|
||||
ERR_MAIN("Failed to create 'TdmApiEvent' thread!!\n");
|
||||
}
|
||||
#else
|
||||
//FIXME: implement the thread. Consider using sangoma_cthread class.
|
||||
TdmApiEventThreadFunc(param);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn void *TdmApiEventThreadFunc(void *lpdwParam)
|
||||
\brief Event handling Function
|
||||
\param lpdwParam pointer to the span/chan device
|
||||
\return void
|
||||
*/
|
||||
#if defined(__WINDOWS__)
|
||||
DWORD TdmApiEventThreadFunc(LPDWORD lpdwParam)
|
||||
#else
|
||||
void *TdmApiEventThreadFunc(void *lpdwParam)
|
||||
#endif
|
||||
{
|
||||
TDM_API_EVENT_THREAD_PARAM *param;
|
||||
sangoma_interface *sang_if;
|
||||
wp_api_event_t *wp_tdm_api_event;
|
||||
sangoma_interface *sang_if = (sangoma_interface *)sang_if_ptr;
|
||||
wp_api_event_t *wp_tdm_api_event = (wp_api_event_t *)event_data;
|
||||
wan_time_t wan_time;
|
||||
char *timestamp_str;
|
||||
|
||||
EnterCriticalSection(&TdmEventCriticalSection);
|
||||
|
||||
param = (TDM_API_EVENT_THREAD_PARAM*)lpdwParam;
|
||||
/* Windows: wan_time is 64bit, time_stamp_sec is 32bit
|
||||
* Linux: wan_time and time_stamp_sec is 32bit */
|
||||
wan_time = wp_tdm_api_event->time_stamp_sec;
|
||||
timestamp_str = sangoma_ctime( &wan_time );
|
||||
|
||||
wp_tdm_api_event = ¶m->event;
|
||||
sang_if = (sangoma_interface*)param->sang_if_ptr;
|
||||
/* Display Logger Event Timestamp as UNIX-style Date string. */
|
||||
/*DBG_MAIN("Time and Date:\t\t%s\n", (timestamp_str == NULL ? "Invalid Timestamp" : timestamp_str));*/
|
||||
|
||||
DBG_MAIN("%s(): ifname: %s: Span: %d, Channel: %d\n", __FUNCTION__, sang_if->device_name,
|
||||
wp_tdm_api_event->wp_api_event_span, wp_tdm_api_event->wp_api_event_channel);
|
||||
DBG_MAIN("%s(): Span: %d, Channel: %d (Seconds:%u, Microseconds:%u)\n", __FUNCTION__,
|
||||
wp_tdm_api_event->wp_api_event_span, wp_tdm_api_event->wp_api_event_channel,
|
||||
wp_tdm_api_event->time_stamp_sec, wp_tdm_api_event->time_stamp_usec);
|
||||
|
||||
switch(wp_tdm_api_event->wp_api_event_type)
|
||||
{
|
||||
|
@ -340,7 +293,6 @@ void *TdmApiEventThreadFunc(void *lpdwParam)
|
|||
wp_tdm_api_event->wp_api_event_dtmf_digit,
|
||||
(wp_tdm_api_event->wp_api_event_dtmf_port == WAN_EC_CHANNEL_PORT_ROUT)?"ROUT":"SOUT",
|
||||
(wp_tdm_api_event->wp_api_event_dtmf_type == WAN_EC_TONE_PRESENT)?"PRESENT":"STOP");
|
||||
|
||||
break;
|
||||
|
||||
case WP_API_EVENT_RXHOOK:
|
||||
|
@ -395,10 +347,8 @@ void *TdmApiEventThreadFunc(void *lpdwParam)
|
|||
break;
|
||||
}
|
||||
|
||||
free(lpdwParam);
|
||||
LeaveCriticalSection(&TdmEventCriticalSection);
|
||||
//Done with the Event, exit the thread.
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
#if USE_WP_LOGGER
|
||||
|
@ -567,6 +517,8 @@ static int parse_command_line_args(int argc, char* argv[])
|
|||
#ifdef WP_API_FEATURE_LIBSNG_HWEC
|
||||
"\t-use_hwec \tInitialize/Configure/Use the Hardware Echo Canceller\n"
|
||||
#endif
|
||||
"\t-real_time \tRun the Program at real-time priority. This maybe\n"
|
||||
"\t \t\timportant when Audio stream is used for timing.\n"
|
||||
"\n"
|
||||
"Example: sample -c 1 -i 1\n";
|
||||
|
||||
|
@ -686,9 +638,11 @@ static int parse_command_line_args(int argc, char* argv[])
|
|||
i++;
|
||||
INFO_MAIN("Setting rxgain to %d.\n", program_settings.txgain);
|
||||
}else if(_stricmp(argv[i], "-use_hwec") == 0){
|
||||
|
||||
INFO_MAIN("Using hardware echo canceller...\n");
|
||||
program_settings.use_hardware_echo_canceller = 1;
|
||||
}else if(_stricmp(argv[i], "-real_time") == 0){
|
||||
INFO_MAIN("Will be running at real-time priority...\n");
|
||||
program_settings.real_time = 1;
|
||||
}else{
|
||||
INFO_MAIN("Error: Invalid Argument %s\n",argv[i]);
|
||||
return 1;
|
||||
|
@ -751,6 +705,10 @@ int __cdecl main(int argc, char* argv[])
|
|||
InitializeCriticalSection(&PrintCriticalSection);
|
||||
InitializeCriticalSection(&TdmEventCriticalSection);
|
||||
|
||||
if (program_settings.real_time) {
|
||||
sng_set_process_priority_to_real_time();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//User may provide Wanpipe Number and Interface Number as a command line arguments:
|
||||
INFO_MAIN("Using wanpipe_number: %d, interface_number: %d\n", program_settings.wanpipe_number, program_settings.interface_number);
|
||||
|
@ -842,7 +800,7 @@ int __cdecl main(int argc, char* argv[])
|
|||
INFO_MAIN("Press 'd' to disable bri bchan loopback\n");
|
||||
break;
|
||||
}
|
||||
INFO_MAIN("Press 'o' to enable DTMF events (on Octasic chip)\n");
|
||||
INFO_MAIN("Press 'o' to control DTMF events on DSP (Octasic)\n");
|
||||
if (program_settings.encode_sw_dtmf) {
|
||||
INFO_MAIN("Press 'x' to send software DTMF\n");
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ typedef struct{
|
|||
int txgain;
|
||||
int rxgain;
|
||||
unsigned char use_hardware_echo_canceller;
|
||||
unsigned char real_time;
|
||||
}wp_program_settings_t;
|
||||
|
||||
#define DEV_NAME_LEN 100
|
||||
|
@ -63,9 +64,9 @@ typedef struct{
|
|||
|
||||
}callback_functions_t;
|
||||
|
||||
#if defined (__WINDOWS__)
|
||||
static void DecodeLastError(LPSTR lpszFunction)
|
||||
{
|
||||
#if defined (__WINDOWS__)
|
||||
LPVOID lpMsgBuf;
|
||||
DWORD dwLastErr = GetLastError();
|
||||
FormatMessage(
|
||||
|
@ -83,8 +84,32 @@ static void DecodeLastError(LPSTR lpszFunction)
|
|||
printf("Last Error: %s (GetLastError() returned: %d)\n", (char*)lpMsgBuf, dwLastErr);
|
||||
// Free the buffer.
|
||||
LocalFree( lpMsgBuf );
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
//This Program interfaces directly to hardware, it should be real time.
|
||||
static void sng_set_process_priority_to_real_time()
|
||||
{
|
||||
#if defined (__WINDOWS__)
|
||||
if (!SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)) {
|
||||
printf("Failed to set program priority!\n");
|
||||
}
|
||||
#else
|
||||
//TODO: implement for Linux
|
||||
#endif
|
||||
}
|
||||
|
||||
//This Execution Thread interfaces directly to hardware, it should be real time.
|
||||
static void sng_set_thread_priority_to_real_time()
|
||||
{
|
||||
#if defined (__WINDOWS__)
|
||||
if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL)) {
|
||||
printf("Failed to set thread priority!\n");
|
||||
}
|
||||
#else
|
||||
//TODO: implement for Linux
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This flag controls debugging of time difference between
|
||||
* data receive indications. Disabled by default. */
|
||||
|
@ -118,13 +143,14 @@ debug_print_dbg_struct(
|
|||
const char *caller_name
|
||||
)
|
||||
{
|
||||
printf("timediff_deviation_counter: %d\n\tTimeDiff (ms) between '%s()':\n\tHighest:%d Lowest:%d Expected: %d Latest: %d\n",
|
||||
printf("timediff_deviation_counter: %d\n\tTimeDiff (ms) between '%s()':\n\tHighest:%d Lowest:%d Expected: %d Latest: %d allowed deviation:%d\n",
|
||||
wan_debug_ptr->timediff_deviation_counter,
|
||||
caller_name,
|
||||
wan_debug_ptr->highest_timediff,
|
||||
wan_debug_ptr->lowest_timediff,
|
||||
wan_debug_ptr->high_resolution_timediff_value,
|
||||
wan_debug_ptr->latest_timediff);
|
||||
wan_debug_ptr->latest_timediff,
|
||||
wan_debug_ptr->allowed_deviation_of_timediff_value);
|
||||
}
|
||||
|
||||
/* Call this function to mesure TimeDiff between some function call. */
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
|
||||
#define DO_COMMAND(wan_udp) DoManagementCommand(sangoma_dev, &wan_udp);
|
||||
|
||||
#define NUMBER_OF_WAIT_OBJECTS 1
|
||||
|
||||
#ifdef WP_API_FEATURE_LIBSNG_HWEC /* defined in wanpipe_api_iface.h */
|
||||
# include "wanpipe_events.h"
|
||||
# include "wanec_api.h"
|
||||
|
@ -32,7 +30,8 @@ sangoma_interface::sangoma_interface(int wanpipe_number, int interface_number)
|
|||
memset(device_name, 0x00, DEV_NAME_LEN);
|
||||
memset(&wan_udp, 0x00, sizeof(wan_udp));
|
||||
memset(&tdm_api_cmd, 0x00, sizeof(tdm_api_cmd));
|
||||
memset(&wp_api, 0x00, sizeof(wp_api));
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
|
||||
WanpipeNumber = wanpipe_number;
|
||||
InterfaceNumber = interface_number;
|
||||
|
@ -47,7 +46,7 @@ sangoma_interface::sangoma_interface(int wanpipe_number, int interface_number)
|
|||
terminate_tx_rx_threads = 0;
|
||||
is_rbs_monitoring_enabled = 0;
|
||||
|
||||
sng_wait_obj = NULL;
|
||||
memset(sng_wait_obj, 0x00, sizeof(sng_wait_obj));
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//receive stuff
|
||||
|
@ -79,7 +78,8 @@ sangoma_interface::sangoma_interface(int wanpipe_number, int interface_number)
|
|||
memset(&wan_debug_rx_timing, 0x00, sizeof(wan_debug_t));
|
||||
debug_set_timing_info( &wan_debug_rx_timing,
|
||||
20 /* expected timediff in milliseconds */,
|
||||
2 /* allowed deviation from expected timediff */);
|
||||
2 /* allowed deviation from expected timediff
|
||||
* (allowed_deviation_of_timediff_value) */);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -95,16 +95,17 @@ int sangoma_interface::init(callback_functions_t *callback_functions_ptr)
|
|||
|
||||
memcpy(&callback_functions, callback_functions_ptr, sizeof(callback_functions_t));
|
||||
|
||||
DBG_IFACE("%s(): WanpipeNumber: %d, InterfaceNumber: %d\n", __FUNCTION__, WanpipeNumber, InterfaceNumber);
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//open handle for reading and writing data, for events reception and other commands
|
||||
sangoma_dev = open_api_device();
|
||||
sangoma_dev = sangoma_open_api_span_chan(WanpipeNumber, InterfaceNumber);
|
||||
if (sangoma_dev == INVALID_HANDLE_VALUE){
|
||||
ERR_IFACE( "Unable to open %s for Rx/Tx!\n", device_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj, sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){
|
||||
ERR_IFACE("Failed to create 'sangoma_wait_object' for %s\n", device_name);
|
||||
if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj[SANGOMA_TX_WAIT_OBJECT], sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){
|
||||
ERR_IFACE("Failed to create 'Tx/Rx/Event WAIT_OBJECT' for %s\n", device_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -182,13 +183,6 @@ int sangoma_interface::init(callback_functions_t *callback_functions_ptr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
sng_fd_t sangoma_interface::open_api_device()
|
||||
{
|
||||
DBG_IFACE("%s(): WanpipeNumber: %d, InterfaceNumber: %d\n", __FUNCTION__, WanpipeNumber, InterfaceNumber);
|
||||
|
||||
return sangoma_open_api_span_chan(WanpipeNumber, InterfaceNumber);
|
||||
}
|
||||
|
||||
void sangoma_interface::generate_bit_rev_table(void)
|
||||
{
|
||||
unsigned char util_char;
|
||||
|
@ -589,6 +583,8 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats)
|
|||
{
|
||||
int err;
|
||||
unsigned char firm_ver, cpld_ver;
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
|
||||
err=sangoma_get_stats(sangoma_dev, &wp_api, stats);
|
||||
if (err) {
|
||||
|
@ -612,9 +608,11 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats)
|
|||
INFO_IFACE("\trx_length_errors: %u\n", stats->rx_length_errors);
|
||||
INFO_IFACE("\trx_over_errors\t: %u\n", stats->rx_over_errors);
|
||||
INFO_IFACE("\trx_crc_errors\t: %u\n", stats->rx_crc_errors); //HDLC CRC mismatch
|
||||
INFO_IFACE("\trx_frame_errors\t: %u\n", stats->rx_frame_errors);//HDLC "abort" occured
|
||||
INFO_IFACE("\trx_frame_errors\t: %u\n", stats->rx_frame_errors);//HDLC Frame Start or Stop Flag is missing
|
||||
INFO_IFACE("\trx_fifo_errors\t: %u\n", stats->rx_fifo_errors);
|
||||
INFO_IFACE("\trx_missed_errors: %u\n", stats->rx_missed_errors);
|
||||
INFO_IFACE("\trx_hdlc_abort_counter: %u\n", stats->rx_hdlc_abort_counter);//Transmitter aborted frame transmission.
|
||||
//Not an error.
|
||||
|
||||
INFO_IFACE("\ttx_aborted_errors: %u\n", stats->tx_aborted_errors);
|
||||
INFO_IFACE("\tTx Idle Data\t: %u\n", stats->tx_carrier_errors);
|
||||
|
@ -637,6 +635,7 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats)
|
|||
INFO_IFACE("\tHWEC tone (DTMF) events counter: %u\n", stats->rx_events_tone);
|
||||
INFO_IFACE( "*********************************\n");
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
err=sangoma_get_driver_version(sangoma_dev,&wp_api, NULL);
|
||||
if (err) {
|
||||
return 1;
|
||||
|
@ -647,6 +646,7 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats)
|
|||
wp_api.wp_cmd.version.minor1,
|
||||
wp_api.wp_cmd.version.minor2);
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
err=sangoma_get_firmware_version(sangoma_dev, &wp_api, &firm_ver);
|
||||
if (err) {
|
||||
return 1;
|
||||
|
@ -654,6 +654,7 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats)
|
|||
INFO_IFACE("\tFirmware Version: %X\n",
|
||||
firm_ver);
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
err=sangoma_get_cpld_version(sangoma_dev, &wp_api, &cpld_ver);
|
||||
if (err) {
|
||||
return 1;
|
||||
|
@ -669,11 +670,13 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats)
|
|||
|
||||
int sangoma_interface::flush_operational_stats()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_flush_stats(sangoma_dev,&wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::flush_tx_buffers()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_flush_bufs(sangoma_dev,&wp_api);
|
||||
}
|
||||
|
||||
|
@ -702,6 +705,7 @@ int sangoma_interface::enable_rbs_monitoring()
|
|||
// set Idle Transmit flag (BitStream/Voice only).
|
||||
int sangoma_interface::set_tx_idle_flag(unsigned char new_idle_flag)
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
tdm_api_cmd.cmd = WP_API_CMD_SET_IDLE_FLAG;
|
||||
tdm_api_cmd.idle_flag = new_idle_flag;
|
||||
return tdmv_api_ioctl(&tdm_api_cmd);
|
||||
|
@ -712,6 +716,7 @@ char sangoma_interface::get_rbs(rbs_management_t *rbs_management_ptr)
|
|||
{
|
||||
int err;
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
err=sangoma_tdm_read_rbs(sangoma_dev, &wp_api, rbs_management_ptr->channel, &rbs_management_ptr->ABCD_bits);
|
||||
if (err) {
|
||||
ERR_IFACE( "Error: command WANPIPEMON_GET_RBS_BITS failed!\n");
|
||||
|
@ -736,6 +741,7 @@ char sangoma_interface::set_rbs(rbs_management_t *rbs_management_ptr)
|
|||
{
|
||||
int err;
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
err=sangoma_tdm_write_rbs(sangoma_dev, &wp_api, rbs_management_ptr->channel, rbs_management_ptr->ABCD_bits);
|
||||
if (err) {
|
||||
return 1;
|
||||
|
@ -833,6 +839,17 @@ int sangoma_interface::get_interface_configuration(if_cfg_t *wanif_conf_ptr)
|
|||
}
|
||||
INFO_IFACE( "****************************\n");
|
||||
|
||||
#if 0
|
||||
// Audio Codec can be read for Voice interface.
|
||||
// For Data interface this setting is ignored by the API.
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
sangoma_get_hw_coding(sangoma_dev, &wp_api);
|
||||
if (wp_api.wp_cmd.result == SANG_STATUS_SUCCESS) {
|
||||
INFO_IFACE("Audio Codec: %s\n",
|
||||
WP_CODEC_FORMAT_DECODE(wp_api.wp_cmd.hw_tdm_coding));
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -841,6 +858,7 @@ void sangoma_interface::get_api_driver_version (PDRIVER_VERSION version)
|
|||
|
||||
int err;
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
err=sangoma_get_driver_version(sangoma_dev, &wp_api, version);
|
||||
if(err){
|
||||
ERR_IFACE("Error: command READ_CODE_VERSION failed!\n");
|
||||
|
@ -874,6 +892,7 @@ void sangoma_interface::get_card_customer_id(u_int8_t *customer_id)
|
|||
|
||||
int sangoma_interface::get_open_handles_counter()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_get_open_cnt(sangoma_dev,&wp_api);
|
||||
}
|
||||
|
||||
|
@ -883,12 +902,15 @@ int sangoma_interface::get_open_handles_counter()
|
|||
//receive data until the LAST handel is closed.
|
||||
void sangoma_interface::cleanup()
|
||||
{
|
||||
int i;
|
||||
|
||||
INFO_IFACE("sangoma_interface::cleanup()\n");
|
||||
|
||||
if(sng_wait_obj){
|
||||
sangoma_wait_obj_delete(&sng_wait_obj);
|
||||
for (i = 0; i < SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS; i++) {
|
||||
if(sng_wait_obj[i]){
|
||||
sangoma_wait_obj_delete(&sng_wait_obj[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
if(sangoma_dev != INVALID_HANDLE_VALUE){
|
||||
if(is_rbs_monitoring_enabled == 1){
|
||||
|
@ -924,7 +946,7 @@ int sangoma_interface::tdmv_api_ioctl(wanpipe_api_cmd_t *api_cmd)
|
|||
{
|
||||
int err;
|
||||
|
||||
memset(&wp_api, 0x00, sizeof(wp_api));
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
|
||||
memcpy(&wp_api.wp_cmd, api_cmd, sizeof(wanpipe_api_cmd_t));
|
||||
|
||||
|
@ -937,11 +959,13 @@ int sangoma_interface::tdmv_api_ioctl(wanpipe_api_cmd_t *api_cmd)
|
|||
|
||||
int sangoma_interface::tdm_enable_ring_detect_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_ring_detect_events(sangoma_dev,&wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_disable_ring_detect_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_disable_ring_detect_events(sangoma_dev,&wp_api);
|
||||
}
|
||||
|
||||
|
@ -950,13 +974,15 @@ int sangoma_interface::tdm_disable_ring_detect_events()
|
|||
* 1250 is most used value. To disable flash event set rxflashtime to 0 */
|
||||
int sangoma_interface::tdm_control_flash_events(int rxflashtime)
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_set_rm_rxflashtime(sangoma_dev, &wp_api, rxflashtime);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_control_rm_txgain(int txgain)
|
||||
{
|
||||
#if WP_API_FEATURE_RM_GAIN
|
||||
return sangoma_set_rm_tx_gain(sangoma_dev,&wp_api, txgain);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_set_rm_tx_gain(sangoma_dev, &wp_api, txgain);
|
||||
#else
|
||||
return SANG_STATUS_UNSUPPORTED_FUNCTION;
|
||||
#endif
|
||||
|
@ -965,6 +991,7 @@ int sangoma_interface::tdm_control_rm_txgain(int txgain)
|
|||
int sangoma_interface::tdm_control_rm_rxgain(int rxgain)
|
||||
{
|
||||
#if WP_API_FEATURE_RM_GAIN
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_set_rm_rx_gain(sangoma_dev, &wp_api, rxgain);
|
||||
#else
|
||||
return SANG_STATUS_UNSUPPORTED_FUNCTION;
|
||||
|
@ -973,96 +1000,117 @@ int sangoma_interface::tdm_control_rm_rxgain(int rxgain)
|
|||
|
||||
int sangoma_interface::tdm_enable_ring_trip_detect_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_ring_trip_detect_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_disable_ring_trip_detect_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_disable_ring_trip_detect_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_enable_rm_dtmf_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_rm_dtmf_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_disable_rm_dtmf_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_disable_rm_dtmf_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_enable_dtmf_events(uint8_t channel)
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
wp_api.wp_cmd.chan = channel;
|
||||
return sangoma_tdm_enable_dtmf_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_disable_dtmf_events(uint8_t channel)
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
wp_api.wp_cmd.chan = channel;
|
||||
return sangoma_tdm_disable_dtmf_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_enable_rxhook_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_rxhook_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_disable_rxhook_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_disable_rxhook_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_enable_ring_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_ring_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_disable_ring_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_disable_ring_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_txsig_onhook()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_txsig_onhook(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_txsig_kewl()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_txsig_kewl(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_txsig_onhooktransfer()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_txsig_onhooktransfer(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_set_rm_polarity(int polarity)
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_set_polarity(sangoma_dev, &wp_api, polarity);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_txsig_offhook()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_txsig_offhook(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_enable_tone_events(uint16_t tone_id)
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_tone_events(sangoma_dev, &wp_api, tone_id);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_disable_tone_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_disable_tone_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_enable_bri_bchan_loopback(u_int8_t channel)
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_enable_bri_bchan_loopback(sangoma_dev, &wp_api, channel);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_disable_bri_bchan_loopback(u_int8_t channel)
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_disable_bri_bchan_loopback(sangoma_dev, &wp_api, channel);
|
||||
}
|
||||
|
||||
|
@ -1073,49 +1121,57 @@ int sangoma_interface::tdm_disable_bri_bchan_loopback(u_int8_t channel)
|
|||
Valid values are between 20 and 100 (including). */
|
||||
int sangoma_interface::tdm_enable_rbs_events(int polls_per_second)
|
||||
{
|
||||
return sangoma_tdm_enable_rbs_events(sangoma_dev, &wp_api,polls_per_second);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_rbs_events(sangoma_dev, &wp_api, polls_per_second);
|
||||
}
|
||||
|
||||
/* Stop monitoring change in state of RBS bits */
|
||||
int sangoma_interface::tdm_disable_rbs_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_disable_rbs_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
/* Activate ISDN BRI line. */
|
||||
int sangoma_interface::tdm_front_end_activate()
|
||||
{
|
||||
return sangoma_set_fe_status(sangoma_dev, &wp_api,WAN_FE_CONNECTED);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_set_fe_status(sangoma_dev, &wp_api, WAN_FE_CONNECTED);
|
||||
}
|
||||
|
||||
/* De-activate ISDN BRI line. */
|
||||
int sangoma_interface::tdm_front_end_deactivate()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_set_fe_status(sangoma_dev, &wp_api, WAN_FE_DISCONNECTED);
|
||||
}
|
||||
|
||||
/* get current state of the line - is it Connected or Disconnected */
|
||||
int sangoma_interface::tdm_get_front_end_status(unsigned char *status)
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_get_fe_status(sangoma_dev, &wp_api, status);
|
||||
}
|
||||
|
||||
/* Milliseconds interval between receive of Voice Data */
|
||||
int sangoma_interface::tdm_set_user_period(unsigned int usr_period)
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_set_usr_period(sangoma_dev, &wp_api, usr_period);
|
||||
}
|
||||
|
||||
int sangoma_interface::stop()
|
||||
{
|
||||
int wait_counter = 0;
|
||||
int wait_counter = 0, i;
|
||||
DBG_IFACE("%s()\n", __FUNCTION__);
|
||||
INFO_IFACE("Stopping.");
|
||||
|
||||
terminate_tx_rx_threads = 1;
|
||||
|
||||
if(sng_wait_obj){
|
||||
sangoma_wait_obj_signal(sng_wait_obj);
|
||||
for (i = 0; i < SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS; i++) {
|
||||
if(sng_wait_obj[i]){
|
||||
sangoma_wait_obj_signal(sng_wait_obj[i]);
|
||||
}
|
||||
}
|
||||
|
||||
while(terminate_tx_rx_threads == 1 && wait_counter++ < 5){
|
||||
|
@ -1362,20 +1418,25 @@ void sangoma_interface::TxThreadFunc()
|
|||
void sangoma_interface::RxThreadFunc()
|
||||
{
|
||||
int iResult;
|
||||
u_int32_t input_flags[NUMBER_OF_WAIT_OBJECTS], output_flags[NUMBER_OF_WAIT_OBJECTS];
|
||||
|
||||
input_flags[0] = (POLLIN | POLLPRI);
|
||||
u_int32_t output_flags[SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS];
|
||||
u_int32_t input_flags[SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS];
|
||||
|
||||
input_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT] = (WP_POLLIN | WP_POLLPRI);
|
||||
|
||||
INFO_IFACE("\n%s: %s() - start\n", device_name, __FUNCTION__);
|
||||
#if defined(__WINDOWS__)
|
||||
INFO_IFACE("ThreadID: %d - Start\n", ::GetCurrentThreadId());
|
||||
#endif
|
||||
|
||||
if (program_settings.real_time) {
|
||||
sng_set_thread_priority_to_real_time();
|
||||
}
|
||||
|
||||
while(terminate_tx_rx_threads == 0){
|
||||
iResult = sangoma_waitfor_many(&sng_wait_obj,
|
||||
iResult = sangoma_waitfor_many(sng_wait_obj,
|
||||
input_flags,
|
||||
output_flags,
|
||||
NUMBER_OF_WAIT_OBJECTS,
|
||||
SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS,
|
||||
5000 /* Wait timeout, in milliseconds. Or SANGOMA_INFINITE_API_POLL_WAIT. */
|
||||
);
|
||||
if(terminate_tx_rx_threads){
|
||||
|
@ -1391,21 +1452,22 @@ void sangoma_interface::RxThreadFunc()
|
|||
|
||||
case SANG_STATUS_SUCCESS:
|
||||
/* a wait object was signaled */
|
||||
if(output_flags[0] & POLLIN){
|
||||
if(output_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT] & WP_POLLIN){
|
||||
/* data */
|
||||
if(read_data()){
|
||||
ERR_IFACE("Error in read_data()!\n");
|
||||
}
|
||||
}
|
||||
|
||||
if(output_flags[0] & POLLPRI){
|
||||
if(output_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT] & WP_POLLPRI){
|
||||
if(read_event()){
|
||||
ERR_IFACE("Error in read_event()!\n");
|
||||
}
|
||||
}
|
||||
|
||||
if(!output_flags[0] || (output_flags[0] & (~input_flags[0])) ){
|
||||
WARN_IFACE("\nUnexpected output_flags[0]: 0x%X\n\n", output_flags[0]);
|
||||
if( output_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT] & (~input_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT]) ){
|
||||
ERR_IFACE("\nUnexpected output_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT]: 0x%X\n\n", output_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT]);
|
||||
iResult = SANG_STATUS_IO_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1430,7 +1492,7 @@ int sangoma_interface::read_event()
|
|||
{
|
||||
int err;
|
||||
|
||||
memset(&wp_api, 0, sizeof(wp_api));
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
|
||||
err = sangoma_read_event(sangoma_dev, &wp_api);
|
||||
if(err){
|
||||
|
@ -1481,6 +1543,13 @@ int sangoma_interface::read_data()
|
|||
|
||||
#if DBG_TIMING
|
||||
debug_update_timediff(&wan_debug_rx_timing, __FUNCTION__);
|
||||
if(1){
|
||||
static int dbg_counter = 0;
|
||||
dbg_counter++;
|
||||
if(!(dbg_counter % 100)){
|
||||
debug_print_dbg_struct(&wan_debug_rx_timing, "sangoma_interface::read_data");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
@ -1541,48 +1610,73 @@ int sangoma_interface::write_data(wp_api_hdr_t *hdr, void *tx_buffer)
|
|||
|
||||
int sangoma_interface::transmit(wp_api_hdr_t *hdr, void *data)
|
||||
{
|
||||
int iResult;
|
||||
u_int32_t input_flags[NUMBER_OF_WAIT_OBJECTS], output_flags[NUMBER_OF_WAIT_OBJECTS];
|
||||
int iResult, retry_wait;
|
||||
u_int32_t output_flags[SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS];
|
||||
u_int32_t input_flags[SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS];
|
||||
|
||||
input_flags[0] = (POLLOUT);
|
||||
input_flags[SANGOMA_TX_WAIT_OBJECT] = (WP_POLLOUT);
|
||||
|
||||
iResult = sangoma_waitfor_many(&sng_wait_obj,
|
||||
input_flags,
|
||||
output_flags,
|
||||
NUMBER_OF_WAIT_OBJECTS,
|
||||
2000 /* wait timeout, in milliseconds */);
|
||||
do {
|
||||
|
||||
switch(iResult)
|
||||
{
|
||||
case SANG_STATUS_APIPOLL_TIMEOUT:
|
||||
//Timeout. It is possible line is disconnected.
|
||||
DBG_IFACE("%s: Tx Timeout!\n", device_name);
|
||||
return SANG_STATUS_TX_TIMEOUT;
|
||||
iResult = sangoma_waitfor_many(sng_wait_obj,
|
||||
input_flags,
|
||||
output_flags,
|
||||
SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS,
|
||||
2000 /* wait timeout, in milliseconds */);
|
||||
|
||||
case SANG_STATUS_SUCCESS:
|
||||
/* a wait object was signaled */
|
||||
if(output_flags[0] & POLLOUT){
|
||||
/* POLLOUT bit is set - there is at least one free Tx buffer. */
|
||||
iResult = write_data(hdr, data);
|
||||
if(SANG_ERROR(iResult)){
|
||||
ERR_IFACE("Error in write_data()!\n");
|
||||
retry_wait = 0;
|
||||
switch(iResult)
|
||||
{
|
||||
case SANG_STATUS_APIPOLL_TIMEOUT:
|
||||
//Timeout. It is possible line is disconnected.
|
||||
DBG_IFACE("%s: Tx Timeout!\n", device_name);
|
||||
return SANG_STATUS_TX_TIMEOUT;
|
||||
|
||||
case SANG_STATUS_SUCCESS:
|
||||
/* a wait object was signaled */
|
||||
if(output_flags[SANGOMA_TX_WAIT_OBJECT] & WP_POLLOUT){
|
||||
/* WP_POLLOUT bit is set - there is at least one free Tx buffer. */
|
||||
iResult = write_data(hdr, data);
|
||||
if(SANG_ERROR(iResult)){
|
||||
ERR_IFACE("Error in write_data()! iResult:%d\n", iResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!output_flags[0] || (output_flags[0] & (~input_flags[0])) ){
|
||||
WARN_IFACE("\nUnexpected output_flags[0]: 0x%X\n\n", output_flags[0]);
|
||||
}
|
||||
break;
|
||||
if(!output_flags[SANGOMA_TX_WAIT_OBJECT]){
|
||||
//
|
||||
//For case (1) when there are multiple objects in sng_wait_obj[],
|
||||
//the wait was woken up by another object in the array.
|
||||
//
|
||||
//For case (2) when there is a single object in sng_wait_obj[],
|
||||
//the Tx wait was woken up by Rx Data or Event.
|
||||
//This sitation is possible because for each Interface,
|
||||
//at the kernel-mode driver level, there is a
|
||||
//SINGLE signalling object which can be signalled for THREE reasons:
|
||||
//Rx Data, API Event AND by availability of free Tx buffer.
|
||||
//
|
||||
//For both cases (1) and (2) the right action is to
|
||||
//retry the wait for free Tx buffer.
|
||||
//
|
||||
retry_wait = 1;
|
||||
}
|
||||
|
||||
default:
|
||||
/* error */
|
||||
ERR_IFACE("iResult: %s (%d)\n", SDLA_DECODE_SANG_STATUS(iResult), iResult);
|
||||
if(SANG_STATUS_FAILED_ALLOCATE_MEMORY == iResult){
|
||||
INFO_IFACE("Fatal Error. Press any key to exit the application.\n");
|
||||
_getch();
|
||||
exit(1);
|
||||
}
|
||||
}//switch(iResult)
|
||||
if( output_flags[SANGOMA_TX_WAIT_OBJECT] & (~input_flags[SANGOMA_TX_WAIT_OBJECT]) ){
|
||||
ERR_IFACE("\nUnexpected output_flags[SANGOMA_TX_WAIT_OBJECT]: 0x%X\n\n", output_flags[SANGOMA_TX_WAIT_OBJECT]);
|
||||
iResult = SANG_STATUS_IO_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* error */
|
||||
ERR_IFACE("iResult: %s (%d)\n", SDLA_DECODE_SANG_STATUS(iResult), iResult);
|
||||
if(SANG_STATUS_FAILED_ALLOCATE_MEMORY == iResult){
|
||||
INFO_IFACE("Fatal Error. Press any key to exit the application.\n");
|
||||
_getch();
|
||||
exit(1);
|
||||
}
|
||||
}//switch(iResult)
|
||||
|
||||
} while(retry_wait);
|
||||
|
||||
return iResult;
|
||||
}
|
||||
|
@ -1590,50 +1684,50 @@ int sangoma_interface::transmit(wp_api_hdr_t *hdr, void *data)
|
|||
///////////////////////////////////////////////////////////////////////
|
||||
int sangoma_interface::start_ring_tone()
|
||||
{
|
||||
DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_tone_events(sangoma_dev, &wp_api, WP_API_EVENT_TONE_RING);
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
int sangoma_interface::start_congestion_tone()
|
||||
{
|
||||
DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_tone_events(sangoma_dev, &wp_api, WP_API_EVENT_TONE_CONGESTION);
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
int sangoma_interface::start_busy_tone()
|
||||
{
|
||||
DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_tone_events(sangoma_dev, &wp_api, WP_API_EVENT_TONE_BUSY);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
int sangoma_interface::start_dial_tone()
|
||||
{
|
||||
DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_tone_events(sangoma_dev, &wp_api, WP_API_EVENT_TONE_DIAL);
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
int sangoma_interface::stop_all_tones()
|
||||
{
|
||||
DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_disable_tone_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
int sangoma_interface::start_ringing_phone()
|
||||
{
|
||||
DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_ring_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
int sangoma_interface::stop_ringing_phone()
|
||||
{
|
||||
DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_disable_ring_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
int sangoma_interface::fxo_go_off_hook()
|
||||
{
|
||||
DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
|
||||
if(wanif_conf_struct.sub_media != MOD_TYPE_FXO){
|
||||
ERR_IFACE( "%s: The 'Go Off Hook' command valid only for FXO!\n", device_name);
|
||||
|
@ -1645,19 +1739,21 @@ int sangoma_interface::fxo_go_off_hook()
|
|||
///////////////////////////////////////////////////////////////////////
|
||||
int sangoma_interface::fxs_txsig_offhook()
|
||||
{
|
||||
DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_txsig_offhook(sangoma_dev,&wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::fxo_go_on_hook()
|
||||
{
|
||||
DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__);
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
|
||||
if(wanif_conf_struct.sub_media != MOD_TYPE_FXO){
|
||||
ERR_IFACE( "%s: The 'Go On Hook' command valid only for FXO!\n", device_name);
|
||||
return 1;
|
||||
}
|
||||
return sangoma_tdm_txsig_onhook(sangoma_dev,&wp_api);
|
||||
return sangoma_tdm_txsig_onhook(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
//set a Telephony interface to it's default state
|
||||
|
@ -1793,7 +1889,7 @@ int sangoma_api_ctrl_dev::init(callback_functions_t *callback_functions_ptr)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj, sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){
|
||||
if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj[0], sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){
|
||||
ERR_IFACE("Failed to create 'sangoma_wait_object' for %s\n", device_name);
|
||||
return 1;
|
||||
}
|
||||
|
@ -1833,7 +1929,7 @@ int sangoma_api_logger_dev::init(callback_functions_t *callback_functions_ptr)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj, sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){
|
||||
if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj[0], sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){
|
||||
ERR_IFACE("Failed to create 'sangoma_wait_object' for %s\n", device_name);
|
||||
return 1;
|
||||
}
|
||||
|
@ -1930,26 +2026,40 @@ int sangoma_api_logger_dev::get_logger_dev_operational_stats(wp_logger_stats_t *
|
|||
memcpy(stats, &logger_cmd.stats, sizeof(*stats));
|
||||
|
||||
INFO_IFACE("*** Logger Device Statistics ***\n");
|
||||
INFO_IFACE("\trx_events\t: %u\n", stats->rx_events);
|
||||
INFO_IFACE("\trx_events_dropped\t: %u\n", stats->rx_events_dropped);
|
||||
INFO_IFACE("\tmax_event_queue_length\t: %u\n", stats->max_event_queue_length);
|
||||
INFO_IFACE("\tcurrent_number_of_events_in_event_queue\t: %u\n", stats->current_number_of_events_in_event_queue);
|
||||
INFO_IFACE("\trx_events\t: %lu\n", stats->rx_events);
|
||||
INFO_IFACE("\trx_events_dropped\t: %lu\n", stats->rx_events_dropped);
|
||||
INFO_IFACE("\tmax_event_queue_length\t: %lu\n", stats->max_event_queue_length);
|
||||
INFO_IFACE("\tcurrent_number_of_events_in_event_queue\t: %lu\n", stats->current_number_of_events_in_event_queue);
|
||||
INFO_IFACE("\n");
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef WP_API_FEATURE_LIBSNG_HWEC
|
||||
|
||||
#define WP_HWEC_USE_OPTIONAL_CHIP_CONFIG_PARAMS 1
|
||||
|
||||
/* NOTE: HWEC must NOT be enabled on a d-channel. The 'in_ulChannelMap' should be
|
||||
* the bitmap of voice channels only. */
|
||||
* the bitmap of voice channel(s) only. */
|
||||
sangoma_status_t config_hwec(char *strDeviceName, unsigned long in_ulChannelMap)
|
||||
{
|
||||
sangoma_status_t rc;
|
||||
#if WP_HWEC_USE_OPTIONAL_CHIP_CONFIG_PARAMS
|
||||
wan_custom_param_t custom_params[1];//Optional paramter(s) for chip-wide initialization
|
||||
#endif
|
||||
|
||||
DBG_IFACE("%s(): strDeviceName: %s, in_ulChannelMap: 0x%X\n", __FUNCTION__, strDeviceName, in_ulChannelMap);
|
||||
|
||||
// Initialize the echo canceller (done once per-physical card)
|
||||
rc = sangoma_hwec_config_init(strDeviceName);
|
||||
// Optionally disable output from HWEC API Library and From API Driver.
|
||||
//sangoma_hwec_config_verbosity(0);
|
||||
|
||||
// Initialize the echo canceller (done once per-port)
|
||||
#if WP_HWEC_USE_OPTIONAL_CHIP_CONFIG_PARAMS
|
||||
sangoma_hwec_initialize_custom_parameter_structure(&custom_params[0], "WANEC_EnableAcousticEcho", "TRUE");
|
||||
rc = sangoma_hwec_config_init(strDeviceName, custom_params, sizeof(custom_params)/sizeof(custom_params[0]));
|
||||
#else
|
||||
rc = sangoma_hwec_config_init(strDeviceName, NULL, 0);
|
||||
#endif
|
||||
if (SANG_STATUS_SUCCESS != rc) {
|
||||
ERR_IFACE( "Failed to initialize echo canceller. rc: %d\n", rc);
|
||||
return rc;
|
||||
|
@ -1982,10 +2092,10 @@ sangoma_status_t config_hwec(char *strDeviceName, unsigned long in_ulChannelMap)
|
|||
}
|
||||
|
||||
#if 0
|
||||
/* "WANEC_SoutAdaptiveNoiseReduction", "WANEC_TailDisplacement", "WANEC_DtmfToneRemoval", "WANEC_AcousticEcho"...*/
|
||||
/* "WANEC_SoutAdaptiveNoiseReduction", "WANEC_TailDisplacement", "WANEC_DtmfToneRemoval", "WANEC_AcousticEcho"...*/
|
||||
|
||||
// Optionally, Enable noise reduction from PSTN
|
||||
rc = sangoma_hwec_config_channel_parameters(strDeviceName,
|
||||
rc = sangoma_hwec_config_channel_parameter(strDeviceName,
|
||||
"WANEC_SoutAdaptiveNoiseReduction",
|
||||
"TRUE",
|
||||
in_ulChannelMap );
|
||||
|
@ -1993,6 +2103,15 @@ sangoma_status_t config_hwec(char *strDeviceName, unsigned long in_ulChannelMap)
|
|||
ERR_IFACE( "Failed to enable noise reduction.\n" );
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = sangoma_hwec_config_channel_parameter(strDeviceName,
|
||||
"WANEC_TailDisplacement",
|
||||
"32",
|
||||
in_ulChannelMap );
|
||||
if (SANG_STATUS_SUCCESS != rc) {
|
||||
ERR_IFACE( "Failed to change HWEC tail displacement.\n" );
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
|
|
@ -90,6 +90,12 @@
|
|||
# include "libstelephony.h"
|
||||
#endif
|
||||
|
||||
/* sangoma_waitfor_many() can wait on an array of sangoma wait objects.
|
||||
* In this example there is a single object in the array. */
|
||||
#define SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS 1
|
||||
#define SANGOMA_TX_WAIT_OBJECT 0
|
||||
#define SANGOMA_RX_AND_EVENT_WAIT_OBJECT 0
|
||||
|
||||
/*!
|
||||
\class sangoma_interface
|
||||
\brief Sangoma Interface Class that deals with span/chan IO (read/write/events)
|
||||
|
@ -100,8 +106,8 @@ protected:
|
|||
/*! Sangoma IO device descriptor */
|
||||
sng_fd_t sangoma_dev;
|
||||
|
||||
/*! wait object device for an IO device */
|
||||
sangoma_wait_obj_t *sng_wait_obj;
|
||||
/*! wait object for an IO device */
|
||||
sangoma_wait_obj_t *sng_wait_obj[SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS];
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//receive stuff
|
||||
|
@ -275,8 +281,6 @@ public:
|
|||
//remove all data from API driver's transmit queue
|
||||
int flush_tx_buffers (void);
|
||||
|
||||
sng_fd_t open_api_device();
|
||||
|
||||
unsigned char get_adapter_type();
|
||||
unsigned int get_sub_media();
|
||||
void set_fe_debug_mode(sdla_fe_debug_t *fe_debug);
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
#define ERR_CFG if(1)printf("PORT:");if(1)printf
|
||||
#define _ERR_CFG if(1)printf
|
||||
|
||||
#define DEV_NAME_PREFIX "\\\\.\\"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//common functions
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@ -35,15 +33,9 @@ sangoma_port::sangoma_port()
|
|||
sangoma_port::~sangoma_port()
|
||||
{
|
||||
DBG_CFG("%s()\n", __FUNCTION__);
|
||||
|
||||
if(wp_handle != INVALID_HANDLE_VALUE){
|
||||
CloseHandle(wp_handle);
|
||||
wp_handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
cleanup();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int sangoma_port::init(uint16_t wanpipe_number)
|
||||
{
|
||||
DBG_CFG("%s()\n", __FUNCTION__);
|
||||
|
@ -57,6 +49,16 @@ int sangoma_port::init(uint16_t wanpipe_number)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void sangoma_port::cleanup()
|
||||
{
|
||||
DBG_CFG("%s()\n", __FUNCTION__);
|
||||
|
||||
if(wp_handle != INVALID_HANDLE_VALUE){
|
||||
sangoma_close(&wp_handle);
|
||||
wp_handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
int sangoma_port::get_hardware_info(hardware_info_t *hardware_info)
|
||||
{
|
||||
port_management_struct_t port_management;
|
||||
|
@ -179,6 +181,10 @@ int sangoma_port::scan_for_sangoma_cards(wanpipe_instance_info_t *wanpipe_info_a
|
|||
}else{
|
||||
DBG_CFG("Found a Card but Card Model is different from what was searched for.\n");
|
||||
}
|
||||
|
||||
//For each init() there MUST be cleanup(). Otherwise Open Handles will remain to the Port.
|
||||
cleanup();
|
||||
|
||||
}//for()
|
||||
|
||||
return card_counter;
|
||||
|
|
|
@ -74,6 +74,7 @@ public:
|
|||
int start_port();
|
||||
|
||||
int init(uint16_t wanpipe_number);
|
||||
void cleanup();
|
||||
|
||||
sangoma_port();
|
||||
virtual ~sangoma_port();
|
||||
|
@ -82,7 +83,7 @@ public:
|
|||
|
||||
protected:
|
||||
uint16_t wp_number;
|
||||
HANDLE wp_handle;
|
||||
sng_fd_t wp_handle;
|
||||
|
||||
int push_a_card_into_wanpipe_info_array(wanpipe_instance_info_t *wanpipe_info_array,
|
||||
hardware_info_t *new_hw_info);
|
||||
|
|
|
@ -442,7 +442,7 @@ int sangoma_port_configurator::initialize_e1_tdm_span_voice_api_configration_str
|
|||
FE_LCODE(sdla_fe_cfg) = WAN_LCODE_HDB3;
|
||||
FE_FRAME(sdla_fe_cfg) = WAN_FR_CRC4;
|
||||
FE_LINENO(sdla_fe_cfg) = hardware_info->port_number;
|
||||
FE_TDMV_LAW(sdla_fe_cfg) = WAN_TDMV_MULAW;
|
||||
FE_TDMV_LAW(sdla_fe_cfg) = WAN_TDMV_ALAW;
|
||||
FE_NETWORK_SYNC(sdla_fe_cfg) = 0;
|
||||
|
||||
FE_LBO(sdla_fe_cfg) = WAN_E1_120;
|
||||
|
@ -525,6 +525,72 @@ int sangoma_port_configurator::control_analog_rm_lcm(port_cfg_t *port_cfg, int c
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************/
|
||||
/*********** Analog Global Gain Setting Functions**************/
|
||||
/**************************************************************/
|
||||
|
||||
//Note: following gain settings are global. It requires drivers to
|
||||
//restart the card.
|
||||
//It is recommended to use dynamic analog txgain/rxgain functions
|
||||
//from libsangoma library:sangoma_set_rm_tx_gain and sangoma_set_rm_rx_gain
|
||||
|
||||
int sangoma_port_configurator::set_analog_rm_fxo_txgain(port_cfg_t *port_cfg, int txgain)
|
||||
{
|
||||
wandev_conf_t *wandev_conf = &port_cfg->wandev_conf;
|
||||
sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg;
|
||||
|
||||
if(wandev_conf->card_type == WANOPT_AFT_ANALOG){//Only valid for Analog cards
|
||||
sdla_fe_cfg->cfg.remora.fxo_txgain = txgain;
|
||||
} else{
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int sangoma_port_configurator::set_analog_rm_fxo_rxgain(port_cfg_t *port_cfg, int rxgain)
|
||||
{
|
||||
wandev_conf_t *wandev_conf = &port_cfg->wandev_conf;
|
||||
sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg;
|
||||
|
||||
if(wandev_conf->card_type == WANOPT_AFT_ANALOG){//Only valid for Analog cards
|
||||
sdla_fe_cfg->cfg.remora.fxo_rxgain = rxgain;
|
||||
} else{
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sangoma_port_configurator::set_analog_rm_fxs_txgain(port_cfg_t *port_cfg, int txgain)
|
||||
{
|
||||
wandev_conf_t *wandev_conf = &port_cfg->wandev_conf;
|
||||
sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg;
|
||||
|
||||
if(wandev_conf->card_type == WANOPT_AFT_ANALOG){//Only valid for Analog cards
|
||||
sdla_fe_cfg->cfg.remora.fxs_txgain = txgain;
|
||||
} else{
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sangoma_port_configurator::set_analog_rm_fxs_rxgain(port_cfg_t *port_cfg, int rxgain)
|
||||
{
|
||||
wandev_conf_t *wandev_conf = &port_cfg->wandev_conf;
|
||||
sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg;
|
||||
|
||||
if(wandev_conf->card_type == WANOPT_AFT_ANALOG){//Only valid for Analog cards
|
||||
sdla_fe_cfg->cfg.remora.fxs_rxgain = rxgain;
|
||||
} else{
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************/
|
||||
/*********** End of Analog Global Gain Setting Functions ******/
|
||||
/**************************************************************/
|
||||
|
||||
|
||||
int sangoma_port_configurator::set_analog_opermode(port_cfg_t *port_cfg, char *opermode)
|
||||
{
|
||||
wandev_conf_t *wandev_conf = &port_cfg->wandev_conf;
|
||||
|
|
|
@ -56,6 +56,38 @@ public:
|
|||
//opermode valid country name supported by Analog FXO
|
||||
int set_analog_opermode(port_cfg_t *port_cfg, char *opermode);
|
||||
|
||||
|
||||
/**************************************************************/
|
||||
/*********** Analog Global Gain Setting Functions**************/
|
||||
/**************************************************************/
|
||||
|
||||
//Note: following gain settings are global. It requires drivers to
|
||||
//restart the card.
|
||||
//It is recommended to use dynamic analog txgain/rxgain functions
|
||||
//from libsangoma library:sangoma_set_rm_tx_gain and sangoma_set_rm_rx_gain
|
||||
|
||||
|
||||
//Function to set FXO txgain
|
||||
//FXO - txgain value ranges from -150 to 120
|
||||
int set_analog_rm_fxo_txgain(port_cfg_t *port_cfg, int txgain);
|
||||
|
||||
//Function to set FXO rxgain
|
||||
//FXO - rxgain value ranges from -150 to 120
|
||||
int set_analog_rm_fxo_rxgain(port_cfg_t *port_cfg, int rxgain);
|
||||
|
||||
//Function to set FXS txgain
|
||||
//FXO - txgain value can be -35 or 35
|
||||
int set_analog_rm_fxs_txgain(port_cfg_t *port_cfg, int txgain);
|
||||
|
||||
//Function to set FXS rxgain
|
||||
//FXO - rxgain value can be -35 or 35
|
||||
int set_analog_rm_fxs_rxgain(port_cfg_t *port_cfg, int rxgain);
|
||||
|
||||
/**************************************************************/
|
||||
/*********** End of Analog Global Gain Setting Functions ******/
|
||||
/**************************************************************/
|
||||
|
||||
|
||||
//Function to check correctness of 'port_cfg_t' structure.
|
||||
int check_port_cfg_structure(port_cfg_t *port_cfg);
|
||||
|
||||
|
|
|
@ -36,8 +36,7 @@ $(SDK_LIB_PATH)\uuid.lib \
|
|||
$(SDK_LIB_PATH)\comctl32.lib \
|
||||
$(SDK_LIB_PATH)\Setupapi.lib \
|
||||
$(SANG_WP_DEVEL)\libsangoma\$(O)\libsangoma.lib \
|
||||
$(SANG_WP_DEVEL)\stelephony\$(O)\stelephony.lib \
|
||||
$(SANG_WP_DEVEL)\wanpipe_common\wantools\wanec_apilib\$(O)\waneclib.lib
|
||||
$(SANG_WP_DEVEL)\stelephony\$(O)\stelephony.lib
|
||||
|
||||
|
||||
SOURCES=sample.cpp \
|
||||
|
|
|
@ -59,17 +59,12 @@ callback_functions_t callback_functions;
|
|||
* Prototypes & Defines
|
||||
*****************************************************************/
|
||||
|
||||
static int got_rx_data(void *sang_if_ptr, void *rx_data);
|
||||
static int got_rx_data(void *sang_if_ptr, void *rxhdr, void *rx_data);
|
||||
static void got_tdm_api_event(void *sang_if_ptr, void *event_data);
|
||||
#if USE_WP_LOGGER
|
||||
static void got_logger_event(void *sang_if_ptr, wp_logger_event_t *logger_event);
|
||||
#endif
|
||||
|
||||
typedef struct{
|
||||
void *sang_if_ptr;
|
||||
wp_api_event_t event;
|
||||
}TDM_API_EVENT_THREAD_PARAM;
|
||||
|
||||
|
||||
#if USE_STELEPHONY_API
|
||||
//Sangoma Telephony API (Stelephony.dll) provides the following telephony services:
|
||||
|
@ -88,13 +83,6 @@ CRITICAL_SECTION PrintCriticalSection;
|
|||
//critical section for TDM events
|
||||
CRITICAL_SECTION TdmEventCriticalSection;
|
||||
|
||||
#if defined (__WINDOWS__)
|
||||
DWORD TdmApiEventThreadFunc(LPDWORD lpdwParam);
|
||||
#else
|
||||
void *TdmApiEventThreadFunc(void *lpdwParam);
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* Debugging Macros
|
||||
*****************************************************************/
|
||||
|
@ -195,9 +183,9 @@ void PrintRxData(wp_api_hdr_t *hdr, void *pdata)
|
|||
if(program_settings.silent){
|
||||
if((rx_counter % 1000) == 0){
|
||||
INFO_MAIN("Rx counter: %d, Rx datlen: %d\n", rx_counter, datlen);
|
||||
#if 0
|
||||
#if 1
|
||||
INFO_MAIN("Timestamp: Seconds: %d, Microseconds: %d\n",
|
||||
hdr->wp_api_hdr_time_stamp_sec, hdr->wp_api_hdr_time_stamp_use);
|
||||
hdr->time_stamp_sec, hdr->time_stamp_usec);
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
|
@ -222,10 +210,13 @@ void PrintRxData(wp_api_hdr_t *hdr, void *pdata)
|
|||
|
||||
/*!
|
||||
\fn static int got_rx_data(void *sang_if_ptr, void *rx_data)
|
||||
\brief Callback function indicating data rx is pending
|
||||
\brief Callback function indicating data rx is pending.
|
||||
\param sang_if_ptr sangoma interface pointer
|
||||
\param rx_data API data element strcutre containt header + data
|
||||
\return 0 - ok non-zero - Error
|
||||
|
||||
This function must return as fast as possible
|
||||
because it is called from real time receiver thread.
|
||||
*/
|
||||
static int got_rx_data(void *sang_if_ptr, void *rxhdr, void *rx_data)
|
||||
{
|
||||
|
@ -267,71 +258,33 @@ static int got_rx_data(void *sang_if_ptr, void *rxhdr, void *rx_data)
|
|||
\param event_data API event element strcutre containt header + data
|
||||
\return 0 - ok non-zero - Error
|
||||
|
||||
Currently Windows launches a thread to handle the event, where
|
||||
Linux handles the event directly. Implementation is left to the user.
|
||||
|
||||
Handling of Events must be done OUTSIDE of the REAL-TIME Rx thread
|
||||
because it may make take a lot of time.
|
||||
Create a special thread for Event hadling Or push Event into
|
||||
a queue - implentation is left to the user.
|
||||
In this example event is handled directly.
|
||||
*/
|
||||
static void got_tdm_api_event(void *sang_if_ptr, void *event_data)
|
||||
{
|
||||
TDM_API_EVENT_THREAD_PARAM *param =
|
||||
(TDM_API_EVENT_THREAD_PARAM*)malloc(sizeof(TDM_API_EVENT_THREAD_PARAM));
|
||||
|
||||
if(param == NULL){
|
||||
ERR_MAIN("Failed to allocate memory for 'Event Thread parameter'!!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(¶m->event, event_data, sizeof(wp_api_event_t));
|
||||
param->sang_if_ptr = sang_if_ptr;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//Handling of Events must be done OUTSIDE of the REAL-TIME Rx thread//
|
||||
//because it may make take a lot of time. //
|
||||
//Create a special thread for Event hadling. //
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#if defined(__WINDOWS__)
|
||||
DWORD dwThreadId;
|
||||
|
||||
if(CreateThread(
|
||||
NULL, /* no security attributes */
|
||||
0, /* use default stack size */
|
||||
(LPTHREAD_START_ROUTINE)TdmApiEventThreadFunc, /* thread function */
|
||||
param, /* argument to thread function */
|
||||
0, /* use default creation flags */
|
||||
&dwThreadId /* returns the thread identifier */
|
||||
) == NULL){
|
||||
ERR_MAIN("Failed to create 'TdmApiEvent' thread!!\n");
|
||||
}
|
||||
#else
|
||||
//FIXME: implement the thread. Consider using sangoma_cthread class.
|
||||
TdmApiEventThreadFunc(param);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn void *TdmApiEventThreadFunc(void *lpdwParam)
|
||||
\brief Event handling Function
|
||||
\param lpdwParam pointer to the span/chan device
|
||||
\return void
|
||||
*/
|
||||
#if defined(__WINDOWS__)
|
||||
DWORD TdmApiEventThreadFunc(LPDWORD lpdwParam)
|
||||
#else
|
||||
void *TdmApiEventThreadFunc(void *lpdwParam)
|
||||
#endif
|
||||
{
|
||||
TDM_API_EVENT_THREAD_PARAM *param;
|
||||
sangoma_interface *sang_if;
|
||||
wp_api_event_t *wp_tdm_api_event;
|
||||
sangoma_interface *sang_if = (sangoma_interface *)sang_if_ptr;
|
||||
wp_api_event_t *wp_tdm_api_event = (wp_api_event_t *)event_data;
|
||||
wan_time_t wan_time;
|
||||
char *timestamp_str;
|
||||
|
||||
EnterCriticalSection(&TdmEventCriticalSection);
|
||||
|
||||
param = (TDM_API_EVENT_THREAD_PARAM*)lpdwParam;
|
||||
/* Windows: wan_time is 64bit, time_stamp_sec is 32bit
|
||||
* Linux: wan_time and time_stamp_sec is 32bit */
|
||||
wan_time = wp_tdm_api_event->time_stamp_sec;
|
||||
timestamp_str = sangoma_ctime( &wan_time );
|
||||
|
||||
wp_tdm_api_event = ¶m->event;
|
||||
sang_if = (sangoma_interface*)param->sang_if_ptr;
|
||||
/* Display Logger Event Timestamp as UNIX-style Date string. */
|
||||
/*DBG_MAIN("Time and Date:\t\t%s\n", (timestamp_str == NULL ? "Invalid Timestamp" : timestamp_str));*/
|
||||
|
||||
DBG_MAIN("%s(): ifname: %s: Span: %d, Channel: %d\n", __FUNCTION__, sang_if->device_name,
|
||||
wp_tdm_api_event->wp_api_event_span, wp_tdm_api_event->wp_api_event_channel);
|
||||
DBG_MAIN("%s(): Span: %d, Channel: %d (Seconds:%u, Microseconds:%u)\n", __FUNCTION__,
|
||||
wp_tdm_api_event->wp_api_event_span, wp_tdm_api_event->wp_api_event_channel,
|
||||
wp_tdm_api_event->time_stamp_sec, wp_tdm_api_event->time_stamp_usec);
|
||||
|
||||
switch(wp_tdm_api_event->wp_api_event_type)
|
||||
{
|
||||
|
@ -340,7 +293,6 @@ void *TdmApiEventThreadFunc(void *lpdwParam)
|
|||
wp_tdm_api_event->wp_api_event_dtmf_digit,
|
||||
(wp_tdm_api_event->wp_api_event_dtmf_port == WAN_EC_CHANNEL_PORT_ROUT)?"ROUT":"SOUT",
|
||||
(wp_tdm_api_event->wp_api_event_dtmf_type == WAN_EC_TONE_PRESENT)?"PRESENT":"STOP");
|
||||
|
||||
break;
|
||||
|
||||
case WP_API_EVENT_RXHOOK:
|
||||
|
@ -395,10 +347,8 @@ void *TdmApiEventThreadFunc(void *lpdwParam)
|
|||
break;
|
||||
}
|
||||
|
||||
free(lpdwParam);
|
||||
LeaveCriticalSection(&TdmEventCriticalSection);
|
||||
//Done with the Event, exit the thread.
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
#if USE_WP_LOGGER
|
||||
|
@ -567,6 +517,8 @@ static int parse_command_line_args(int argc, char* argv[])
|
|||
#ifdef WP_API_FEATURE_LIBSNG_HWEC
|
||||
"\t-use_hwec \tInitialize/Configure/Use the Hardware Echo Canceller\n"
|
||||
#endif
|
||||
"\t-real_time \tRun the Program at real-time priority. This maybe\n"
|
||||
"\t \t\timportant when Audio stream is used for timing.\n"
|
||||
"\n"
|
||||
"Example: sample -c 1 -i 1\n";
|
||||
|
||||
|
@ -686,9 +638,11 @@ static int parse_command_line_args(int argc, char* argv[])
|
|||
i++;
|
||||
INFO_MAIN("Setting rxgain to %d.\n", program_settings.txgain);
|
||||
}else if(_stricmp(argv[i], "-use_hwec") == 0){
|
||||
|
||||
INFO_MAIN("Using hardware echo canceller...\n");
|
||||
program_settings.use_hardware_echo_canceller = 1;
|
||||
}else if(_stricmp(argv[i], "-real_time") == 0){
|
||||
INFO_MAIN("Will be running at real-time priority...\n");
|
||||
program_settings.real_time = 1;
|
||||
}else{
|
||||
INFO_MAIN("Error: Invalid Argument %s\n",argv[i]);
|
||||
return 1;
|
||||
|
@ -751,6 +705,10 @@ int __cdecl main(int argc, char* argv[])
|
|||
InitializeCriticalSection(&PrintCriticalSection);
|
||||
InitializeCriticalSection(&TdmEventCriticalSection);
|
||||
|
||||
if (program_settings.real_time) {
|
||||
sng_set_process_priority_to_real_time();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//User may provide Wanpipe Number and Interface Number as a command line arguments:
|
||||
INFO_MAIN("Using wanpipe_number: %d, interface_number: %d\n", program_settings.wanpipe_number, program_settings.interface_number);
|
||||
|
@ -842,7 +800,7 @@ int __cdecl main(int argc, char* argv[])
|
|||
INFO_MAIN("Press 'd' to disable bri bchan loopback\n");
|
||||
break;
|
||||
}
|
||||
INFO_MAIN("Press 'o' to enable DTMF events (on Octasic chip)\n");
|
||||
INFO_MAIN("Press 'o' to control DTMF events on DSP (Octasic)\n");
|
||||
if (program_settings.encode_sw_dtmf) {
|
||||
INFO_MAIN("Press 'x' to send software DTMF\n");
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ typedef struct{
|
|||
int txgain;
|
||||
int rxgain;
|
||||
unsigned char use_hardware_echo_canceller;
|
||||
unsigned char real_time;
|
||||
}wp_program_settings_t;
|
||||
|
||||
#define DEV_NAME_LEN 100
|
||||
|
@ -63,9 +64,9 @@ typedef struct{
|
|||
|
||||
}callback_functions_t;
|
||||
|
||||
#if defined (__WINDOWS__)
|
||||
static void DecodeLastError(LPSTR lpszFunction)
|
||||
{
|
||||
#if defined (__WINDOWS__)
|
||||
LPVOID lpMsgBuf;
|
||||
DWORD dwLastErr = GetLastError();
|
||||
FormatMessage(
|
||||
|
@ -83,8 +84,32 @@ static void DecodeLastError(LPSTR lpszFunction)
|
|||
printf("Last Error: %s (GetLastError() returned: %d)\n", (char*)lpMsgBuf, dwLastErr);
|
||||
// Free the buffer.
|
||||
LocalFree( lpMsgBuf );
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
//This Program interfaces directly to hardware, it should be real time.
|
||||
static void sng_set_process_priority_to_real_time()
|
||||
{
|
||||
#if defined (__WINDOWS__)
|
||||
if (!SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)) {
|
||||
printf("Failed to set program priority!\n");
|
||||
}
|
||||
#else
|
||||
//TODO: implement for Linux
|
||||
#endif
|
||||
}
|
||||
|
||||
//This Execution Thread interfaces directly to hardware, it should be real time.
|
||||
static void sng_set_thread_priority_to_real_time()
|
||||
{
|
||||
#if defined (__WINDOWS__)
|
||||
if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL)) {
|
||||
printf("Failed to set thread priority!\n");
|
||||
}
|
||||
#else
|
||||
//TODO: implement for Linux
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This flag controls debugging of time difference between
|
||||
* data receive indications. Disabled by default. */
|
||||
|
@ -118,13 +143,14 @@ debug_print_dbg_struct(
|
|||
const char *caller_name
|
||||
)
|
||||
{
|
||||
printf("timediff_deviation_counter: %d\n\tTimeDiff (ms) between '%s()':\n\tHighest:%d Lowest:%d Expected: %d Latest: %d\n",
|
||||
printf("timediff_deviation_counter: %d\n\tTimeDiff (ms) between '%s()':\n\tHighest:%d Lowest:%d Expected: %d Latest: %d allowed deviation:%d\n",
|
||||
wan_debug_ptr->timediff_deviation_counter,
|
||||
caller_name,
|
||||
wan_debug_ptr->highest_timediff,
|
||||
wan_debug_ptr->lowest_timediff,
|
||||
wan_debug_ptr->high_resolution_timediff_value,
|
||||
wan_debug_ptr->latest_timediff);
|
||||
wan_debug_ptr->latest_timediff,
|
||||
wan_debug_ptr->allowed_deviation_of_timediff_value);
|
||||
}
|
||||
|
||||
/* Call this function to mesure TimeDiff between some function call. */
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
|
||||
#define DO_COMMAND(wan_udp) DoManagementCommand(sangoma_dev, &wan_udp);
|
||||
|
||||
#define NUMBER_OF_WAIT_OBJECTS 1
|
||||
|
||||
#ifdef WP_API_FEATURE_LIBSNG_HWEC /* defined in wanpipe_api_iface.h */
|
||||
# include "wanpipe_events.h"
|
||||
# include "wanec_api.h"
|
||||
|
@ -32,7 +30,8 @@ sangoma_interface::sangoma_interface(int wanpipe_number, int interface_number)
|
|||
memset(device_name, 0x00, DEV_NAME_LEN);
|
||||
memset(&wan_udp, 0x00, sizeof(wan_udp));
|
||||
memset(&tdm_api_cmd, 0x00, sizeof(tdm_api_cmd));
|
||||
memset(&wp_api, 0x00, sizeof(wp_api));
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
|
||||
WanpipeNumber = wanpipe_number;
|
||||
InterfaceNumber = interface_number;
|
||||
|
@ -47,7 +46,7 @@ sangoma_interface::sangoma_interface(int wanpipe_number, int interface_number)
|
|||
terminate_tx_rx_threads = 0;
|
||||
is_rbs_monitoring_enabled = 0;
|
||||
|
||||
sng_wait_obj = NULL;
|
||||
memset(sng_wait_obj, 0x00, sizeof(sng_wait_obj));
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//receive stuff
|
||||
|
@ -79,7 +78,8 @@ sangoma_interface::sangoma_interface(int wanpipe_number, int interface_number)
|
|||
memset(&wan_debug_rx_timing, 0x00, sizeof(wan_debug_t));
|
||||
debug_set_timing_info( &wan_debug_rx_timing,
|
||||
20 /* expected timediff in milliseconds */,
|
||||
2 /* allowed deviation from expected timediff */);
|
||||
2 /* allowed deviation from expected timediff
|
||||
* (allowed_deviation_of_timediff_value) */);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -95,16 +95,17 @@ int sangoma_interface::init(callback_functions_t *callback_functions_ptr)
|
|||
|
||||
memcpy(&callback_functions, callback_functions_ptr, sizeof(callback_functions_t));
|
||||
|
||||
DBG_IFACE("%s(): WanpipeNumber: %d, InterfaceNumber: %d\n", __FUNCTION__, WanpipeNumber, InterfaceNumber);
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//open handle for reading and writing data, for events reception and other commands
|
||||
sangoma_dev = open_api_device();
|
||||
sangoma_dev = sangoma_open_api_span_chan(WanpipeNumber, InterfaceNumber);
|
||||
if (sangoma_dev == INVALID_HANDLE_VALUE){
|
||||
ERR_IFACE( "Unable to open %s for Rx/Tx!\n", device_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj, sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){
|
||||
ERR_IFACE("Failed to create 'sangoma_wait_object' for %s\n", device_name);
|
||||
if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj[SANGOMA_TX_WAIT_OBJECT], sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){
|
||||
ERR_IFACE("Failed to create 'Tx/Rx/Event WAIT_OBJECT' for %s\n", device_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -182,13 +183,6 @@ int sangoma_interface::init(callback_functions_t *callback_functions_ptr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
sng_fd_t sangoma_interface::open_api_device()
|
||||
{
|
||||
DBG_IFACE("%s(): WanpipeNumber: %d, InterfaceNumber: %d\n", __FUNCTION__, WanpipeNumber, InterfaceNumber);
|
||||
|
||||
return sangoma_open_api_span_chan(WanpipeNumber, InterfaceNumber);
|
||||
}
|
||||
|
||||
void sangoma_interface::generate_bit_rev_table(void)
|
||||
{
|
||||
unsigned char util_char;
|
||||
|
@ -589,6 +583,8 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats)
|
|||
{
|
||||
int err;
|
||||
unsigned char firm_ver, cpld_ver;
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
|
||||
err=sangoma_get_stats(sangoma_dev, &wp_api, stats);
|
||||
if (err) {
|
||||
|
@ -612,9 +608,11 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats)
|
|||
INFO_IFACE("\trx_length_errors: %u\n", stats->rx_length_errors);
|
||||
INFO_IFACE("\trx_over_errors\t: %u\n", stats->rx_over_errors);
|
||||
INFO_IFACE("\trx_crc_errors\t: %u\n", stats->rx_crc_errors); //HDLC CRC mismatch
|
||||
INFO_IFACE("\trx_frame_errors\t: %u\n", stats->rx_frame_errors);//HDLC "abort" occured
|
||||
INFO_IFACE("\trx_frame_errors\t: %u\n", stats->rx_frame_errors);//HDLC Frame Start or Stop Flag is missing
|
||||
INFO_IFACE("\trx_fifo_errors\t: %u\n", stats->rx_fifo_errors);
|
||||
INFO_IFACE("\trx_missed_errors: %u\n", stats->rx_missed_errors);
|
||||
INFO_IFACE("\trx_hdlc_abort_counter: %u\n", stats->rx_hdlc_abort_counter);//Transmitter aborted frame transmission.
|
||||
//Not an error.
|
||||
|
||||
INFO_IFACE("\ttx_aborted_errors: %u\n", stats->tx_aborted_errors);
|
||||
INFO_IFACE("\tTx Idle Data\t: %u\n", stats->tx_carrier_errors);
|
||||
|
@ -637,6 +635,7 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats)
|
|||
INFO_IFACE("\tHWEC tone (DTMF) events counter: %u\n", stats->rx_events_tone);
|
||||
INFO_IFACE( "*********************************\n");
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
err=sangoma_get_driver_version(sangoma_dev,&wp_api, NULL);
|
||||
if (err) {
|
||||
return 1;
|
||||
|
@ -647,6 +646,7 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats)
|
|||
wp_api.wp_cmd.version.minor1,
|
||||
wp_api.wp_cmd.version.minor2);
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
err=sangoma_get_firmware_version(sangoma_dev, &wp_api, &firm_ver);
|
||||
if (err) {
|
||||
return 1;
|
||||
|
@ -654,6 +654,7 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats)
|
|||
INFO_IFACE("\tFirmware Version: %X\n",
|
||||
firm_ver);
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
err=sangoma_get_cpld_version(sangoma_dev, &wp_api, &cpld_ver);
|
||||
if (err) {
|
||||
return 1;
|
||||
|
@ -669,11 +670,13 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats)
|
|||
|
||||
int sangoma_interface::flush_operational_stats()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_flush_stats(sangoma_dev,&wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::flush_tx_buffers()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_flush_bufs(sangoma_dev,&wp_api);
|
||||
}
|
||||
|
||||
|
@ -702,6 +705,7 @@ int sangoma_interface::enable_rbs_monitoring()
|
|||
// set Idle Transmit flag (BitStream/Voice only).
|
||||
int sangoma_interface::set_tx_idle_flag(unsigned char new_idle_flag)
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
tdm_api_cmd.cmd = WP_API_CMD_SET_IDLE_FLAG;
|
||||
tdm_api_cmd.idle_flag = new_idle_flag;
|
||||
return tdmv_api_ioctl(&tdm_api_cmd);
|
||||
|
@ -712,6 +716,7 @@ char sangoma_interface::get_rbs(rbs_management_t *rbs_management_ptr)
|
|||
{
|
||||
int err;
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
err=sangoma_tdm_read_rbs(sangoma_dev, &wp_api, rbs_management_ptr->channel, &rbs_management_ptr->ABCD_bits);
|
||||
if (err) {
|
||||
ERR_IFACE( "Error: command WANPIPEMON_GET_RBS_BITS failed!\n");
|
||||
|
@ -736,6 +741,7 @@ char sangoma_interface::set_rbs(rbs_management_t *rbs_management_ptr)
|
|||
{
|
||||
int err;
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
err=sangoma_tdm_write_rbs(sangoma_dev, &wp_api, rbs_management_ptr->channel, rbs_management_ptr->ABCD_bits);
|
||||
if (err) {
|
||||
return 1;
|
||||
|
@ -833,6 +839,17 @@ int sangoma_interface::get_interface_configuration(if_cfg_t *wanif_conf_ptr)
|
|||
}
|
||||
INFO_IFACE( "****************************\n");
|
||||
|
||||
#if 0
|
||||
// Audio Codec can be read for Voice interface.
|
||||
// For Data interface this setting is ignored by the API.
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
sangoma_get_hw_coding(sangoma_dev, &wp_api);
|
||||
if (wp_api.wp_cmd.result == SANG_STATUS_SUCCESS) {
|
||||
INFO_IFACE("Audio Codec: %s\n",
|
||||
WP_CODEC_FORMAT_DECODE(wp_api.wp_cmd.hw_tdm_coding));
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -841,6 +858,7 @@ void sangoma_interface::get_api_driver_version (PDRIVER_VERSION version)
|
|||
|
||||
int err;
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
err=sangoma_get_driver_version(sangoma_dev, &wp_api, version);
|
||||
if(err){
|
||||
ERR_IFACE("Error: command READ_CODE_VERSION failed!\n");
|
||||
|
@ -874,6 +892,7 @@ void sangoma_interface::get_card_customer_id(u_int8_t *customer_id)
|
|||
|
||||
int sangoma_interface::get_open_handles_counter()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_get_open_cnt(sangoma_dev,&wp_api);
|
||||
}
|
||||
|
||||
|
@ -883,12 +902,15 @@ int sangoma_interface::get_open_handles_counter()
|
|||
//receive data until the LAST handel is closed.
|
||||
void sangoma_interface::cleanup()
|
||||
{
|
||||
int i;
|
||||
|
||||
INFO_IFACE("sangoma_interface::cleanup()\n");
|
||||
|
||||
if(sng_wait_obj){
|
||||
sangoma_wait_obj_delete(&sng_wait_obj);
|
||||
for (i = 0; i < SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS; i++) {
|
||||
if(sng_wait_obj[i]){
|
||||
sangoma_wait_obj_delete(&sng_wait_obj[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
if(sangoma_dev != INVALID_HANDLE_VALUE){
|
||||
if(is_rbs_monitoring_enabled == 1){
|
||||
|
@ -924,7 +946,7 @@ int sangoma_interface::tdmv_api_ioctl(wanpipe_api_cmd_t *api_cmd)
|
|||
{
|
||||
int err;
|
||||
|
||||
memset(&wp_api, 0x00, sizeof(wp_api));
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
|
||||
memcpy(&wp_api.wp_cmd, api_cmd, sizeof(wanpipe_api_cmd_t));
|
||||
|
||||
|
@ -937,11 +959,13 @@ int sangoma_interface::tdmv_api_ioctl(wanpipe_api_cmd_t *api_cmd)
|
|||
|
||||
int sangoma_interface::tdm_enable_ring_detect_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_ring_detect_events(sangoma_dev,&wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_disable_ring_detect_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_disable_ring_detect_events(sangoma_dev,&wp_api);
|
||||
}
|
||||
|
||||
|
@ -950,13 +974,15 @@ int sangoma_interface::tdm_disable_ring_detect_events()
|
|||
* 1250 is most used value. To disable flash event set rxflashtime to 0 */
|
||||
int sangoma_interface::tdm_control_flash_events(int rxflashtime)
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_set_rm_rxflashtime(sangoma_dev, &wp_api, rxflashtime);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_control_rm_txgain(int txgain)
|
||||
{
|
||||
#if WP_API_FEATURE_RM_GAIN
|
||||
return sangoma_set_rm_tx_gain(sangoma_dev,&wp_api, txgain);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_set_rm_tx_gain(sangoma_dev, &wp_api, txgain);
|
||||
#else
|
||||
return SANG_STATUS_UNSUPPORTED_FUNCTION;
|
||||
#endif
|
||||
|
@ -965,6 +991,7 @@ int sangoma_interface::tdm_control_rm_txgain(int txgain)
|
|||
int sangoma_interface::tdm_control_rm_rxgain(int rxgain)
|
||||
{
|
||||
#if WP_API_FEATURE_RM_GAIN
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_set_rm_rx_gain(sangoma_dev, &wp_api, rxgain);
|
||||
#else
|
||||
return SANG_STATUS_UNSUPPORTED_FUNCTION;
|
||||
|
@ -973,96 +1000,117 @@ int sangoma_interface::tdm_control_rm_rxgain(int rxgain)
|
|||
|
||||
int sangoma_interface::tdm_enable_ring_trip_detect_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_ring_trip_detect_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_disable_ring_trip_detect_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_disable_ring_trip_detect_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_enable_rm_dtmf_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_rm_dtmf_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_disable_rm_dtmf_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_disable_rm_dtmf_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_enable_dtmf_events(uint8_t channel)
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
wp_api.wp_cmd.chan = channel;
|
||||
return sangoma_tdm_enable_dtmf_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_disable_dtmf_events(uint8_t channel)
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
wp_api.wp_cmd.chan = channel;
|
||||
return sangoma_tdm_disable_dtmf_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_enable_rxhook_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_rxhook_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_disable_rxhook_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_disable_rxhook_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_enable_ring_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_ring_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_disable_ring_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_disable_ring_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_txsig_onhook()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_txsig_onhook(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_txsig_kewl()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_txsig_kewl(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_txsig_onhooktransfer()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_txsig_onhooktransfer(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_set_rm_polarity(int polarity)
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_set_polarity(sangoma_dev, &wp_api, polarity);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_txsig_offhook()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_txsig_offhook(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_enable_tone_events(uint16_t tone_id)
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_tone_events(sangoma_dev, &wp_api, tone_id);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_disable_tone_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_disable_tone_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_enable_bri_bchan_loopback(u_int8_t channel)
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_enable_bri_bchan_loopback(sangoma_dev, &wp_api, channel);
|
||||
}
|
||||
|
||||
int sangoma_interface::tdm_disable_bri_bchan_loopback(u_int8_t channel)
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_disable_bri_bchan_loopback(sangoma_dev, &wp_api, channel);
|
||||
}
|
||||
|
||||
|
@ -1073,49 +1121,57 @@ int sangoma_interface::tdm_disable_bri_bchan_loopback(u_int8_t channel)
|
|||
Valid values are between 20 and 100 (including). */
|
||||
int sangoma_interface::tdm_enable_rbs_events(int polls_per_second)
|
||||
{
|
||||
return sangoma_tdm_enable_rbs_events(sangoma_dev, &wp_api,polls_per_second);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_rbs_events(sangoma_dev, &wp_api, polls_per_second);
|
||||
}
|
||||
|
||||
/* Stop monitoring change in state of RBS bits */
|
||||
int sangoma_interface::tdm_disable_rbs_events()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_disable_rbs_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
/* Activate ISDN BRI line. */
|
||||
int sangoma_interface::tdm_front_end_activate()
|
||||
{
|
||||
return sangoma_set_fe_status(sangoma_dev, &wp_api,WAN_FE_CONNECTED);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_set_fe_status(sangoma_dev, &wp_api, WAN_FE_CONNECTED);
|
||||
}
|
||||
|
||||
/* De-activate ISDN BRI line. */
|
||||
int sangoma_interface::tdm_front_end_deactivate()
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_set_fe_status(sangoma_dev, &wp_api, WAN_FE_DISCONNECTED);
|
||||
}
|
||||
|
||||
/* get current state of the line - is it Connected or Disconnected */
|
||||
int sangoma_interface::tdm_get_front_end_status(unsigned char *status)
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_get_fe_status(sangoma_dev, &wp_api, status);
|
||||
}
|
||||
|
||||
/* Milliseconds interval between receive of Voice Data */
|
||||
int sangoma_interface::tdm_set_user_period(unsigned int usr_period)
|
||||
{
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_set_usr_period(sangoma_dev, &wp_api, usr_period);
|
||||
}
|
||||
|
||||
int sangoma_interface::stop()
|
||||
{
|
||||
int wait_counter = 0;
|
||||
int wait_counter = 0, i;
|
||||
DBG_IFACE("%s()\n", __FUNCTION__);
|
||||
INFO_IFACE("Stopping.");
|
||||
|
||||
terminate_tx_rx_threads = 1;
|
||||
|
||||
if(sng_wait_obj){
|
||||
sangoma_wait_obj_signal(sng_wait_obj);
|
||||
for (i = 0; i < SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS; i++) {
|
||||
if(sng_wait_obj[i]){
|
||||
sangoma_wait_obj_signal(sng_wait_obj[i]);
|
||||
}
|
||||
}
|
||||
|
||||
while(terminate_tx_rx_threads == 1 && wait_counter++ < 5){
|
||||
|
@ -1362,20 +1418,25 @@ void sangoma_interface::TxThreadFunc()
|
|||
void sangoma_interface::RxThreadFunc()
|
||||
{
|
||||
int iResult;
|
||||
u_int32_t input_flags[NUMBER_OF_WAIT_OBJECTS], output_flags[NUMBER_OF_WAIT_OBJECTS];
|
||||
|
||||
input_flags[0] = (POLLIN | POLLPRI);
|
||||
u_int32_t output_flags[SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS];
|
||||
u_int32_t input_flags[SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS];
|
||||
|
||||
input_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT] = (WP_POLLIN | WP_POLLPRI);
|
||||
|
||||
INFO_IFACE("\n%s: %s() - start\n", device_name, __FUNCTION__);
|
||||
#if defined(__WINDOWS__)
|
||||
INFO_IFACE("ThreadID: %d - Start\n", ::GetCurrentThreadId());
|
||||
#endif
|
||||
|
||||
if (program_settings.real_time) {
|
||||
sng_set_thread_priority_to_real_time();
|
||||
}
|
||||
|
||||
while(terminate_tx_rx_threads == 0){
|
||||
iResult = sangoma_waitfor_many(&sng_wait_obj,
|
||||
iResult = sangoma_waitfor_many(sng_wait_obj,
|
||||
input_flags,
|
||||
output_flags,
|
||||
NUMBER_OF_WAIT_OBJECTS,
|
||||
SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS,
|
||||
5000 /* Wait timeout, in milliseconds. Or SANGOMA_INFINITE_API_POLL_WAIT. */
|
||||
);
|
||||
if(terminate_tx_rx_threads){
|
||||
|
@ -1391,21 +1452,22 @@ void sangoma_interface::RxThreadFunc()
|
|||
|
||||
case SANG_STATUS_SUCCESS:
|
||||
/* a wait object was signaled */
|
||||
if(output_flags[0] & POLLIN){
|
||||
if(output_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT] & WP_POLLIN){
|
||||
/* data */
|
||||
if(read_data()){
|
||||
ERR_IFACE("Error in read_data()!\n");
|
||||
}
|
||||
}
|
||||
|
||||
if(output_flags[0] & POLLPRI){
|
||||
if(output_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT] & WP_POLLPRI){
|
||||
if(read_event()){
|
||||
ERR_IFACE("Error in read_event()!\n");
|
||||
}
|
||||
}
|
||||
|
||||
if(!output_flags[0] || (output_flags[0] & (~input_flags[0])) ){
|
||||
WARN_IFACE("\nUnexpected output_flags[0]: 0x%X\n\n", output_flags[0]);
|
||||
if( output_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT] & (~input_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT]) ){
|
||||
ERR_IFACE("\nUnexpected output_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT]: 0x%X\n\n", output_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT]);
|
||||
iResult = SANG_STATUS_IO_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1430,7 +1492,7 @@ int sangoma_interface::read_event()
|
|||
{
|
||||
int err;
|
||||
|
||||
memset(&wp_api, 0, sizeof(wp_api));
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
|
||||
err = sangoma_read_event(sangoma_dev, &wp_api);
|
||||
if(err){
|
||||
|
@ -1481,6 +1543,13 @@ int sangoma_interface::read_data()
|
|||
|
||||
#if DBG_TIMING
|
||||
debug_update_timediff(&wan_debug_rx_timing, __FUNCTION__);
|
||||
if(1){
|
||||
static int dbg_counter = 0;
|
||||
dbg_counter++;
|
||||
if(!(dbg_counter % 100)){
|
||||
debug_print_dbg_struct(&wan_debug_rx_timing, "sangoma_interface::read_data");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
@ -1541,48 +1610,73 @@ int sangoma_interface::write_data(wp_api_hdr_t *hdr, void *tx_buffer)
|
|||
|
||||
int sangoma_interface::transmit(wp_api_hdr_t *hdr, void *data)
|
||||
{
|
||||
int iResult;
|
||||
u_int32_t input_flags[NUMBER_OF_WAIT_OBJECTS], output_flags[NUMBER_OF_WAIT_OBJECTS];
|
||||
int iResult, retry_wait;
|
||||
u_int32_t output_flags[SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS];
|
||||
u_int32_t input_flags[SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS];
|
||||
|
||||
input_flags[0] = (POLLOUT);
|
||||
input_flags[SANGOMA_TX_WAIT_OBJECT] = (WP_POLLOUT);
|
||||
|
||||
iResult = sangoma_waitfor_many(&sng_wait_obj,
|
||||
input_flags,
|
||||
output_flags,
|
||||
NUMBER_OF_WAIT_OBJECTS,
|
||||
2000 /* wait timeout, in milliseconds */);
|
||||
do {
|
||||
|
||||
switch(iResult)
|
||||
{
|
||||
case SANG_STATUS_APIPOLL_TIMEOUT:
|
||||
//Timeout. It is possible line is disconnected.
|
||||
DBG_IFACE("%s: Tx Timeout!\n", device_name);
|
||||
return SANG_STATUS_TX_TIMEOUT;
|
||||
iResult = sangoma_waitfor_many(sng_wait_obj,
|
||||
input_flags,
|
||||
output_flags,
|
||||
SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS,
|
||||
2000 /* wait timeout, in milliseconds */);
|
||||
|
||||
case SANG_STATUS_SUCCESS:
|
||||
/* a wait object was signaled */
|
||||
if(output_flags[0] & POLLOUT){
|
||||
/* POLLOUT bit is set - there is at least one free Tx buffer. */
|
||||
iResult = write_data(hdr, data);
|
||||
if(SANG_ERROR(iResult)){
|
||||
ERR_IFACE("Error in write_data()!\n");
|
||||
retry_wait = 0;
|
||||
switch(iResult)
|
||||
{
|
||||
case SANG_STATUS_APIPOLL_TIMEOUT:
|
||||
//Timeout. It is possible line is disconnected.
|
||||
DBG_IFACE("%s: Tx Timeout!\n", device_name);
|
||||
return SANG_STATUS_TX_TIMEOUT;
|
||||
|
||||
case SANG_STATUS_SUCCESS:
|
||||
/* a wait object was signaled */
|
||||
if(output_flags[SANGOMA_TX_WAIT_OBJECT] & WP_POLLOUT){
|
||||
/* WP_POLLOUT bit is set - there is at least one free Tx buffer. */
|
||||
iResult = write_data(hdr, data);
|
||||
if(SANG_ERROR(iResult)){
|
||||
ERR_IFACE("Error in write_data()! iResult:%d\n", iResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!output_flags[0] || (output_flags[0] & (~input_flags[0])) ){
|
||||
WARN_IFACE("\nUnexpected output_flags[0]: 0x%X\n\n", output_flags[0]);
|
||||
}
|
||||
break;
|
||||
if(!output_flags[SANGOMA_TX_WAIT_OBJECT]){
|
||||
//
|
||||
//For case (1) when there are multiple objects in sng_wait_obj[],
|
||||
//the wait was woken up by another object in the array.
|
||||
//
|
||||
//For case (2) when there is a single object in sng_wait_obj[],
|
||||
//the Tx wait was woken up by Rx Data or Event.
|
||||
//This sitation is possible because for each Interface,
|
||||
//at the kernel-mode driver level, there is a
|
||||
//SINGLE signalling object which can be signalled for THREE reasons:
|
||||
//Rx Data, API Event AND by availability of free Tx buffer.
|
||||
//
|
||||
//For both cases (1) and (2) the right action is to
|
||||
//retry the wait for free Tx buffer.
|
||||
//
|
||||
retry_wait = 1;
|
||||
}
|
||||
|
||||
default:
|
||||
/* error */
|
||||
ERR_IFACE("iResult: %s (%d)\n", SDLA_DECODE_SANG_STATUS(iResult), iResult);
|
||||
if(SANG_STATUS_FAILED_ALLOCATE_MEMORY == iResult){
|
||||
INFO_IFACE("Fatal Error. Press any key to exit the application.\n");
|
||||
_getch();
|
||||
exit(1);
|
||||
}
|
||||
}//switch(iResult)
|
||||
if( output_flags[SANGOMA_TX_WAIT_OBJECT] & (~input_flags[SANGOMA_TX_WAIT_OBJECT]) ){
|
||||
ERR_IFACE("\nUnexpected output_flags[SANGOMA_TX_WAIT_OBJECT]: 0x%X\n\n", output_flags[SANGOMA_TX_WAIT_OBJECT]);
|
||||
iResult = SANG_STATUS_IO_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* error */
|
||||
ERR_IFACE("iResult: %s (%d)\n", SDLA_DECODE_SANG_STATUS(iResult), iResult);
|
||||
if(SANG_STATUS_FAILED_ALLOCATE_MEMORY == iResult){
|
||||
INFO_IFACE("Fatal Error. Press any key to exit the application.\n");
|
||||
_getch();
|
||||
exit(1);
|
||||
}
|
||||
}//switch(iResult)
|
||||
|
||||
} while(retry_wait);
|
||||
|
||||
return iResult;
|
||||
}
|
||||
|
@ -1590,50 +1684,50 @@ int sangoma_interface::transmit(wp_api_hdr_t *hdr, void *data)
|
|||
///////////////////////////////////////////////////////////////////////
|
||||
int sangoma_interface::start_ring_tone()
|
||||
{
|
||||
DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_tone_events(sangoma_dev, &wp_api, WP_API_EVENT_TONE_RING);
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
int sangoma_interface::start_congestion_tone()
|
||||
{
|
||||
DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_tone_events(sangoma_dev, &wp_api, WP_API_EVENT_TONE_CONGESTION);
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
int sangoma_interface::start_busy_tone()
|
||||
{
|
||||
DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_tone_events(sangoma_dev, &wp_api, WP_API_EVENT_TONE_BUSY);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
int sangoma_interface::start_dial_tone()
|
||||
{
|
||||
DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_tone_events(sangoma_dev, &wp_api, WP_API_EVENT_TONE_DIAL);
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
int sangoma_interface::stop_all_tones()
|
||||
{
|
||||
DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_disable_tone_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
int sangoma_interface::start_ringing_phone()
|
||||
{
|
||||
DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_enable_ring_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
int sangoma_interface::stop_ringing_phone()
|
||||
{
|
||||
DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_disable_ring_events(sangoma_dev, &wp_api);
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
int sangoma_interface::fxo_go_off_hook()
|
||||
{
|
||||
DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
|
||||
if(wanif_conf_struct.sub_media != MOD_TYPE_FXO){
|
||||
ERR_IFACE( "%s: The 'Go Off Hook' command valid only for FXO!\n", device_name);
|
||||
|
@ -1645,19 +1739,21 @@ int sangoma_interface::fxo_go_off_hook()
|
|||
///////////////////////////////////////////////////////////////////////
|
||||
int sangoma_interface::fxs_txsig_offhook()
|
||||
{
|
||||
DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__);
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
return sangoma_tdm_txsig_offhook(sangoma_dev,&wp_api);
|
||||
}
|
||||
|
||||
int sangoma_interface::fxo_go_on_hook()
|
||||
{
|
||||
DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__);
|
||||
|
||||
SANGOMA_INIT_TDM_API_CMD(wp_api);
|
||||
|
||||
if(wanif_conf_struct.sub_media != MOD_TYPE_FXO){
|
||||
ERR_IFACE( "%s: The 'Go On Hook' command valid only for FXO!\n", device_name);
|
||||
return 1;
|
||||
}
|
||||
return sangoma_tdm_txsig_onhook(sangoma_dev,&wp_api);
|
||||
return sangoma_tdm_txsig_onhook(sangoma_dev, &wp_api);
|
||||
}
|
||||
|
||||
//set a Telephony interface to it's default state
|
||||
|
@ -1793,7 +1889,7 @@ int sangoma_api_ctrl_dev::init(callback_functions_t *callback_functions_ptr)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj, sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){
|
||||
if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj[0], sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){
|
||||
ERR_IFACE("Failed to create 'sangoma_wait_object' for %s\n", device_name);
|
||||
return 1;
|
||||
}
|
||||
|
@ -1833,7 +1929,7 @@ int sangoma_api_logger_dev::init(callback_functions_t *callback_functions_ptr)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj, sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){
|
||||
if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj[0], sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){
|
||||
ERR_IFACE("Failed to create 'sangoma_wait_object' for %s\n", device_name);
|
||||
return 1;
|
||||
}
|
||||
|
@ -1930,26 +2026,40 @@ int sangoma_api_logger_dev::get_logger_dev_operational_stats(wp_logger_stats_t *
|
|||
memcpy(stats, &logger_cmd.stats, sizeof(*stats));
|
||||
|
||||
INFO_IFACE("*** Logger Device Statistics ***\n");
|
||||
INFO_IFACE("\trx_events\t: %u\n", stats->rx_events);
|
||||
INFO_IFACE("\trx_events_dropped\t: %u\n", stats->rx_events_dropped);
|
||||
INFO_IFACE("\tmax_event_queue_length\t: %u\n", stats->max_event_queue_length);
|
||||
INFO_IFACE("\tcurrent_number_of_events_in_event_queue\t: %u\n", stats->current_number_of_events_in_event_queue);
|
||||
INFO_IFACE("\trx_events\t: %lu\n", stats->rx_events);
|
||||
INFO_IFACE("\trx_events_dropped\t: %lu\n", stats->rx_events_dropped);
|
||||
INFO_IFACE("\tmax_event_queue_length\t: %lu\n", stats->max_event_queue_length);
|
||||
INFO_IFACE("\tcurrent_number_of_events_in_event_queue\t: %lu\n", stats->current_number_of_events_in_event_queue);
|
||||
INFO_IFACE("\n");
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef WP_API_FEATURE_LIBSNG_HWEC
|
||||
|
||||
#define WP_HWEC_USE_OPTIONAL_CHIP_CONFIG_PARAMS 1
|
||||
|
||||
/* NOTE: HWEC must NOT be enabled on a d-channel. The 'in_ulChannelMap' should be
|
||||
* the bitmap of voice channels only. */
|
||||
* the bitmap of voice channel(s) only. */
|
||||
sangoma_status_t config_hwec(char *strDeviceName, unsigned long in_ulChannelMap)
|
||||
{
|
||||
sangoma_status_t rc;
|
||||
#if WP_HWEC_USE_OPTIONAL_CHIP_CONFIG_PARAMS
|
||||
wan_custom_param_t custom_params[1];//Optional paramter(s) for chip-wide initialization
|
||||
#endif
|
||||
|
||||
DBG_IFACE("%s(): strDeviceName: %s, in_ulChannelMap: 0x%X\n", __FUNCTION__, strDeviceName, in_ulChannelMap);
|
||||
|
||||
// Initialize the echo canceller (done once per-physical card)
|
||||
rc = sangoma_hwec_config_init(strDeviceName);
|
||||
// Optionally disable output from HWEC API Library and From API Driver.
|
||||
//sangoma_hwec_config_verbosity(0);
|
||||
|
||||
// Initialize the echo canceller (done once per-port)
|
||||
#if WP_HWEC_USE_OPTIONAL_CHIP_CONFIG_PARAMS
|
||||
sangoma_hwec_initialize_custom_parameter_structure(&custom_params[0], "WANEC_EnableAcousticEcho", "TRUE");
|
||||
rc = sangoma_hwec_config_init(strDeviceName, custom_params, sizeof(custom_params)/sizeof(custom_params[0]));
|
||||
#else
|
||||
rc = sangoma_hwec_config_init(strDeviceName, NULL, 0);
|
||||
#endif
|
||||
if (SANG_STATUS_SUCCESS != rc) {
|
||||
ERR_IFACE( "Failed to initialize echo canceller. rc: %d\n", rc);
|
||||
return rc;
|
||||
|
@ -1982,10 +2092,10 @@ sangoma_status_t config_hwec(char *strDeviceName, unsigned long in_ulChannelMap)
|
|||
}
|
||||
|
||||
#if 0
|
||||
/* "WANEC_SoutAdaptiveNoiseReduction", "WANEC_TailDisplacement", "WANEC_DtmfToneRemoval", "WANEC_AcousticEcho"...*/
|
||||
/* "WANEC_SoutAdaptiveNoiseReduction", "WANEC_TailDisplacement", "WANEC_DtmfToneRemoval", "WANEC_AcousticEcho"...*/
|
||||
|
||||
// Optionally, Enable noise reduction from PSTN
|
||||
rc = sangoma_hwec_config_channel_parameters(strDeviceName,
|
||||
rc = sangoma_hwec_config_channel_parameter(strDeviceName,
|
||||
"WANEC_SoutAdaptiveNoiseReduction",
|
||||
"TRUE",
|
||||
in_ulChannelMap );
|
||||
|
@ -1993,6 +2103,15 @@ sangoma_status_t config_hwec(char *strDeviceName, unsigned long in_ulChannelMap)
|
|||
ERR_IFACE( "Failed to enable noise reduction.\n" );
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = sangoma_hwec_config_channel_parameter(strDeviceName,
|
||||
"WANEC_TailDisplacement",
|
||||
"32",
|
||||
in_ulChannelMap );
|
||||
if (SANG_STATUS_SUCCESS != rc) {
|
||||
ERR_IFACE( "Failed to change HWEC tail displacement.\n" );
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
return SANG_STATUS_SUCCESS;
|
||||
|
|
|
@ -90,6 +90,12 @@
|
|||
# include "libstelephony.h"
|
||||
#endif
|
||||
|
||||
/* sangoma_waitfor_many() can wait on an array of sangoma wait objects.
|
||||
* In this example there is a single object in the array. */
|
||||
#define SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS 1
|
||||
#define SANGOMA_TX_WAIT_OBJECT 0
|
||||
#define SANGOMA_RX_AND_EVENT_WAIT_OBJECT 0
|
||||
|
||||
/*!
|
||||
\class sangoma_interface
|
||||
\brief Sangoma Interface Class that deals with span/chan IO (read/write/events)
|
||||
|
@ -100,8 +106,8 @@ protected:
|
|||
/*! Sangoma IO device descriptor */
|
||||
sng_fd_t sangoma_dev;
|
||||
|
||||
/*! wait object device for an IO device */
|
||||
sangoma_wait_obj_t *sng_wait_obj;
|
||||
/*! wait object for an IO device */
|
||||
sangoma_wait_obj_t *sng_wait_obj[SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS];
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//receive stuff
|
||||
|
@ -275,8 +281,6 @@ public:
|
|||
//remove all data from API driver's transmit queue
|
||||
int flush_tx_buffers (void);
|
||||
|
||||
sng_fd_t open_api_device();
|
||||
|
||||
unsigned char get_adapter_type();
|
||||
unsigned int get_sub_media();
|
||||
void set_fe_debug_mode(sdla_fe_debug_t *fe_debug);
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
#define ERR_CFG if(1)printf("PORT:");if(1)printf
|
||||
#define _ERR_CFG if(1)printf
|
||||
|
||||
#define DEV_NAME_PREFIX "\\\\.\\"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//common functions
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@ -35,15 +33,9 @@ sangoma_port::sangoma_port()
|
|||
sangoma_port::~sangoma_port()
|
||||
{
|
||||
DBG_CFG("%s()\n", __FUNCTION__);
|
||||
|
||||
if(wp_handle != INVALID_HANDLE_VALUE){
|
||||
CloseHandle(wp_handle);
|
||||
wp_handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
cleanup();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int sangoma_port::init(uint16_t wanpipe_number)
|
||||
{
|
||||
DBG_CFG("%s()\n", __FUNCTION__);
|
||||
|
@ -57,6 +49,16 @@ int sangoma_port::init(uint16_t wanpipe_number)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void sangoma_port::cleanup()
|
||||
{
|
||||
DBG_CFG("%s()\n", __FUNCTION__);
|
||||
|
||||
if(wp_handle != INVALID_HANDLE_VALUE){
|
||||
sangoma_close(&wp_handle);
|
||||
wp_handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
int sangoma_port::get_hardware_info(hardware_info_t *hardware_info)
|
||||
{
|
||||
port_management_struct_t port_management;
|
||||
|
@ -179,6 +181,10 @@ int sangoma_port::scan_for_sangoma_cards(wanpipe_instance_info_t *wanpipe_info_a
|
|||
}else{
|
||||
DBG_CFG("Found a Card but Card Model is different from what was searched for.\n");
|
||||
}
|
||||
|
||||
//For each init() there MUST be cleanup(). Otherwise Open Handles will remain to the Port.
|
||||
cleanup();
|
||||
|
||||
}//for()
|
||||
|
||||
return card_counter;
|
||||
|
|
|
@ -74,6 +74,7 @@ public:
|
|||
int start_port();
|
||||
|
||||
int init(uint16_t wanpipe_number);
|
||||
void cleanup();
|
||||
|
||||
sangoma_port();
|
||||
virtual ~sangoma_port();
|
||||
|
@ -82,7 +83,7 @@ public:
|
|||
|
||||
protected:
|
||||
uint16_t wp_number;
|
||||
HANDLE wp_handle;
|
||||
sng_fd_t wp_handle;
|
||||
|
||||
int push_a_card_into_wanpipe_info_array(wanpipe_instance_info_t *wanpipe_info_array,
|
||||
hardware_info_t *new_hw_info);
|
||||
|
|
|
@ -442,7 +442,7 @@ int sangoma_port_configurator::initialize_e1_tdm_span_voice_api_configration_str
|
|||
FE_LCODE(sdla_fe_cfg) = WAN_LCODE_HDB3;
|
||||
FE_FRAME(sdla_fe_cfg) = WAN_FR_CRC4;
|
||||
FE_LINENO(sdla_fe_cfg) = hardware_info->port_number;
|
||||
FE_TDMV_LAW(sdla_fe_cfg) = WAN_TDMV_MULAW;
|
||||
FE_TDMV_LAW(sdla_fe_cfg) = WAN_TDMV_ALAW;
|
||||
FE_NETWORK_SYNC(sdla_fe_cfg) = 0;
|
||||
|
||||
FE_LBO(sdla_fe_cfg) = WAN_E1_120;
|
||||
|
@ -525,6 +525,72 @@ int sangoma_port_configurator::control_analog_rm_lcm(port_cfg_t *port_cfg, int c
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************/
|
||||
/*********** Analog Global Gain Setting Functions**************/
|
||||
/**************************************************************/
|
||||
|
||||
//Note: following gain settings are global. It requires drivers to
|
||||
//restart the card.
|
||||
//It is recommended to use dynamic analog txgain/rxgain functions
|
||||
//from libsangoma library:sangoma_set_rm_tx_gain and sangoma_set_rm_rx_gain
|
||||
|
||||
int sangoma_port_configurator::set_analog_rm_fxo_txgain(port_cfg_t *port_cfg, int txgain)
|
||||
{
|
||||
wandev_conf_t *wandev_conf = &port_cfg->wandev_conf;
|
||||
sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg;
|
||||
|
||||
if(wandev_conf->card_type == WANOPT_AFT_ANALOG){//Only valid for Analog cards
|
||||
sdla_fe_cfg->cfg.remora.fxo_txgain = txgain;
|
||||
} else{
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int sangoma_port_configurator::set_analog_rm_fxo_rxgain(port_cfg_t *port_cfg, int rxgain)
|
||||
{
|
||||
wandev_conf_t *wandev_conf = &port_cfg->wandev_conf;
|
||||
sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg;
|
||||
|
||||
if(wandev_conf->card_type == WANOPT_AFT_ANALOG){//Only valid for Analog cards
|
||||
sdla_fe_cfg->cfg.remora.fxo_rxgain = rxgain;
|
||||
} else{
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sangoma_port_configurator::set_analog_rm_fxs_txgain(port_cfg_t *port_cfg, int txgain)
|
||||
{
|
||||
wandev_conf_t *wandev_conf = &port_cfg->wandev_conf;
|
||||
sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg;
|
||||
|
||||
if(wandev_conf->card_type == WANOPT_AFT_ANALOG){//Only valid for Analog cards
|
||||
sdla_fe_cfg->cfg.remora.fxs_txgain = txgain;
|
||||
} else{
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sangoma_port_configurator::set_analog_rm_fxs_rxgain(port_cfg_t *port_cfg, int rxgain)
|
||||
{
|
||||
wandev_conf_t *wandev_conf = &port_cfg->wandev_conf;
|
||||
sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg;
|
||||
|
||||
if(wandev_conf->card_type == WANOPT_AFT_ANALOG){//Only valid for Analog cards
|
||||
sdla_fe_cfg->cfg.remora.fxs_rxgain = rxgain;
|
||||
} else{
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************/
|
||||
/*********** End of Analog Global Gain Setting Functions ******/
|
||||
/**************************************************************/
|
||||
|
||||
|
||||
int sangoma_port_configurator::set_analog_opermode(port_cfg_t *port_cfg, char *opermode)
|
||||
{
|
||||
wandev_conf_t *wandev_conf = &port_cfg->wandev_conf;
|
||||
|
|
|
@ -56,6 +56,38 @@ public:
|
|||
//opermode valid country name supported by Analog FXO
|
||||
int set_analog_opermode(port_cfg_t *port_cfg, char *opermode);
|
||||
|
||||
|
||||
/**************************************************************/
|
||||
/*********** Analog Global Gain Setting Functions**************/
|
||||
/**************************************************************/
|
||||
|
||||
//Note: following gain settings are global. It requires drivers to
|
||||
//restart the card.
|
||||
//It is recommended to use dynamic analog txgain/rxgain functions
|
||||
//from libsangoma library:sangoma_set_rm_tx_gain and sangoma_set_rm_rx_gain
|
||||
|
||||
|
||||
//Function to set FXO txgain
|
||||
//FXO - txgain value ranges from -150 to 120
|
||||
int set_analog_rm_fxo_txgain(port_cfg_t *port_cfg, int txgain);
|
||||
|
||||
//Function to set FXO rxgain
|
||||
//FXO - rxgain value ranges from -150 to 120
|
||||
int set_analog_rm_fxo_rxgain(port_cfg_t *port_cfg, int rxgain);
|
||||
|
||||
//Function to set FXS txgain
|
||||
//FXO - txgain value can be -35 or 35
|
||||
int set_analog_rm_fxs_txgain(port_cfg_t *port_cfg, int txgain);
|
||||
|
||||
//Function to set FXS rxgain
|
||||
//FXO - rxgain value can be -35 or 35
|
||||
int set_analog_rm_fxs_rxgain(port_cfg_t *port_cfg, int rxgain);
|
||||
|
||||
/**************************************************************/
|
||||
/*********** End of Analog Global Gain Setting Functions ******/
|
||||
/**************************************************************/
|
||||
|
||||
|
||||
//Function to check correctness of 'port_cfg_t' structure.
|
||||
int check_port_cfg_structure(port_cfg_t *port_cfg);
|
||||
|
||||
|
|
|
@ -36,8 +36,7 @@ $(SDK_LIB_PATH)\uuid.lib \
|
|||
$(SDK_LIB_PATH)\comctl32.lib \
|
||||
$(SDK_LIB_PATH)\Setupapi.lib \
|
||||
$(SANG_WP_DEVEL)\libsangoma\$(O)\libsangoma.lib \
|
||||
$(SANG_WP_DEVEL)\stelephony\$(O)\stelephony.lib \
|
||||
$(SANG_WP_DEVEL)\wanpipe_common\wantools\wanec_apilib\$(O)\waneclib.lib
|
||||
$(SANG_WP_DEVEL)\stelephony\$(O)\stelephony.lib
|
||||
|
||||
|
||||
SOURCES=sample.cpp \
|
||||
|
|
|
@ -11,7 +11,7 @@ USE_LIBCMT=1
|
|||
DLLDEF=libsangoma.def
|
||||
|
||||
############################################################################################
|
||||
C_DEFINES=$(C_DEFINES) /D__WINDOWS__ /D__COMPILING_LIBSANGOMA__
|
||||
C_DEFINES=$(C_DEFINES) /D__WINDOWS__ /D__COMPILING_LIBSANGOMA__ /DWP_PREVENT_WINSOCK_NAME_CONFLICT
|
||||
############################################################################################
|
||||
|
||||
INCLUDES=$(SDK_INC_PATH);\
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 33
|
||||
/svn/stelephony/!svn/ver/59/trunk
|
||||
/svn/stelephony/!svn/ver/60/trunk
|
||||
END
|
||||
stelephony.h
|
||||
K 25
|
||||
|
@ -175,7 +175,7 @@ PToneDecoder.cpp
|
|||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 50
|
||||
/svn/stelephony/!svn/ver/54/trunk/PToneDecoder.cpp
|
||||
/svn/stelephony/!svn/ver/60/trunk/PToneDecoder.cpp
|
||||
END
|
||||
stelephony.vcproj
|
||||
K 25
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
8
|
||||
|
||||
dir
|
||||
59
|
||||
60
|
||||
http://www.sangomapbx.com/svn/stelephony/trunk
|
||||
http://www.sangomapbx.com/svn/stelephony
|
||||
|
||||
|
||||
|
||||
2010-03-15T22:33:02.724320Z
|
||||
59
|
||||
davidr
|
||||
2010-05-03T18:04:24.253105Z
|
||||
60
|
||||
davidy
|
||||
has-props
|
||||
|
||||
svn:special svn:externals svn:needs-lock
|
||||
|
@ -377,10 +377,10 @@ file
|
|||
|
||||
|
||||
|
||||
2009-12-21T23:17:41.000000Z
|
||||
afc68f8adeeec8bacd42fc2c6ac7d380
|
||||
2009-12-18T18:47:54.309491Z
|
||||
54
|
||||
2010-05-18T21:28:05.000000Z
|
||||
86e9b97797f181a857e7a57a0bbaa367
|
||||
2010-05-03T18:04:24.253105Z
|
||||
60
|
||||
davidy
|
||||
|
||||
stelephony.vcproj
|
||||
|
|
|
@ -107,6 +107,7 @@ int PhoneToneDecoder::WaveStreamInputExFSK(int16_t* slinData, int dataLength, in
|
|||
case MDMF_DATETIME:
|
||||
strncpy(DateTime, sp, mlen-1);
|
||||
break;
|
||||
case MDMF_DDN:
|
||||
case MDMF_PHONE_NUM:
|
||||
strncpy(CallerNumber, sp, mlen-1);
|
||||
break;
|
||||
|
|
|
@ -107,6 +107,7 @@ int PhoneToneDecoder::WaveStreamInputExFSK(int16_t* slinData, int dataLength, in
|
|||
case MDMF_DATETIME:
|
||||
strncpy(DateTime, sp, mlen-1);
|
||||
break;
|
||||
case MDMF_DDN:
|
||||
case MDMF_PHONE_NUM:
|
||||
strncpy(CallerNumber, sp, mlen-1);
|
||||
break;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
8
|
||||
|
||||
dir
|
||||
59
|
||||
60
|
||||
http://www.sangomapbx.com/svn/stelephony/trunk/stel_tone
|
||||
http://www.sangomapbx.com/svn/stelephony
|
||||
|
||||
|
|
|
@ -322,7 +322,7 @@ void process_con_rx(void)
|
|||
slot->hdlc_eng->decoder.stats.abort,
|
||||
slot->hdlc_eng->decoder.stats.frame_overflow);
|
||||
//sangoma_get_full_cfg(slot->sock, &tdm_api);
|
||||
wanpipe_hdlc_dump_ring(slot->hdlc_eng);
|
||||
//wanpipe_hdlc_dump_ring(slot->hdlc_eng);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,25 @@ int dev_fd;
|
|||
FILE *tx_fd=NULL,*rx_fd=NULL;
|
||||
wanpipe_tdm_api_t tdm_api;
|
||||
|
||||
void print_packet(unsigned char *buf, int len)
|
||||
{
|
||||
int x;
|
||||
|
||||
if (buf[0]==126 && buf[1]==126) {
|
||||
return;
|
||||
}
|
||||
|
||||
printf("{ | ");
|
||||
for (x=0;x<len;x++){
|
||||
if (x && x%24 == 0){
|
||||
printf("\n ");
|
||||
}
|
||||
if (x && x%8 == 0)
|
||||
printf(" | ");
|
||||
printf("%02d ",buf[x]);
|
||||
}
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
static int sample_time_test(void){
|
||||
|
||||
|
@ -180,7 +199,7 @@ void handle_span_chan(void)
|
|||
* by deafult incrementing number starting from 0 */
|
||||
for (i=0;i<Tx_length;i++){
|
||||
if (tx_data == -1){
|
||||
api_tx_el->data[i] = (unsigned char)i;
|
||||
api_tx_el->data[i] = (unsigned char)(i%24);
|
||||
}else{
|
||||
#if 0
|
||||
api_tx_el->data[i] = (unsigned char)tx_data+(i%4);
|
||||
|
@ -190,6 +209,8 @@ void handle_span_chan(void)
|
|||
}
|
||||
}
|
||||
|
||||
print_packet(api_tx_el->data,Tx_length);
|
||||
|
||||
/* Main Rx Tx OOB routine */
|
||||
for(;;) {
|
||||
|
||||
|
@ -254,13 +275,13 @@ void handle_span_chan(void)
|
|||
Rx_data,
|
||||
sizeof(wp_tdm_api_rx_hdr_t),
|
||||
&Rx_data[sizeof(wp_tdm_api_rx_hdr_t)],
|
||||
MAX_RX_DATA, 0);
|
||||
70, 0);
|
||||
|
||||
if (!read_enable){
|
||||
goto bitstrm_skip_read;
|
||||
}
|
||||
|
||||
sample_time_test();
|
||||
//sample_time_test();
|
||||
|
||||
/* err indicates bytes received */
|
||||
if(err <= 0) {
|
||||
|
@ -294,12 +315,17 @@ void handle_span_chan(void)
|
|||
++Rx_count;
|
||||
|
||||
if (verbose){
|
||||
printf("Received %i Length = %i\n",
|
||||
Rx_count,Rx_lgth);
|
||||
// printf("Received %i Length = %i\n",
|
||||
// Rx_count,Rx_lgth);
|
||||
#if 1
|
||||
printf("Data: ");
|
||||
print_packet(api_rx_el->data,Rx_lgth);
|
||||
#else
|
||||
//printf("Data: \n");
|
||||
for(i=0;i<Rx_lgth; i ++) {
|
||||
printf("0x%02X ", api_rx_el->data[i]);
|
||||
if (i && i%24==0) {
|
||||
printf("\n");
|
||||
}
|
||||
printf("%02d ", api_rx_el->data[i]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
# ============================================================================
|
||||
# Makefile Make script for building SS7 MTP2 API
|
||||
# ----------------------------------------------------------------------------
|
||||
# Author: Nenad Corbic <ncorbic@sangoma.com>
|
||||
# Copyright (c) 2008 Sangoma Technologies Inc. All Rights Reserved.
|
||||
# ============================================================================
|
||||
|
||||
####### MACROS ###############################################################
|
||||
|
||||
# Build options.
|
||||
OS_TYPE = __LINUX__
|
||||
DEBUG = 2
|
||||
|
||||
SYSINC=$(shell if [ -f ../../.sysinclude ]; then cat ../../.sysinclude; else echo ""; fi)
|
||||
ifeq "$(SYSINC)" ""
|
||||
SYSINC=/usr/src/linux/include
|
||||
endif
|
||||
VPATH = $(SYSINC)
|
||||
|
||||
# Tools options.
|
||||
CFLAGS = -Wall -O0 -g -D$(OS_TYPE) -D_DEBUG_=$(DEBUG) -D_GNUC_ -I$(SYSINC)
|
||||
|
||||
TARGETS=mtp2api
|
||||
|
||||
####### RULES ################################################################
|
||||
|
||||
all: $(TARGETS)
|
||||
@echo "Ok."
|
||||
|
||||
mtp2api: mtp2api.c libxmtp2.c
|
||||
$(CC) $(CFLAGS) -o $@ $^
|
||||
|
||||
clean:
|
||||
rm -f $(TARGETS)
|
||||
rm -f *.o
|
||||
rm -f *.*~
|
||||
rm -f diff
|
|
@ -0,0 +1,224 @@
|
|||
MTP2 API
|
||||
|
||||
For Latest Info Visit
|
||||
http://wiki.sangoma.com/wanpipe-aft-ss7-mtp2-api
|
||||
|
||||
|
||||
|
||||
Introduction
|
||||
|
||||
|
||||
The Wanpipe MTP2 API provides a custom ss7 developer access to Sangoma's Kernel SS7 MTP2 stack that runs over Sangoma AFT Series T1/E1 cards. The MTP2 API is written as a library in C and works in conjunction with wanpipe mtp2 kernel drivers.
|
||||
|
||||
|
||||
MTP2 API contains the following files:
|
||||
|
||||
mtp2api.c -> example main code
|
||||
libxmtp2.c -> mtp2 api library
|
||||
libxmtp2.y -> mtp2 api library header
|
||||
|
||||
|
||||
|
||||
Architecture
|
||||
|
||||
mtp2api # custom ss7 application
|
||||
|
|
||||
/dev/xmtp20 # kernel device
|
||||
|
|
||||
| xmtp2km | # MTP2 Stack / kernel module
|
||||
|
|
||||
| wanpipe | # Wanpipe Device Driver - Core
|
||||
|
|
||||
| AFT | # Sangoma AFT T1/E1 Hardware
|
||||
|
||||
|
||||
|
||||
|
||||
Installation
|
||||
|
||||
1. Download latest Wanpipe MTP2 Release From:
|
||||
-> ftp.sangoma.com/linux/custom/mtp2api
|
||||
|
||||
2. Untar wanpipe-<version>.tgz
|
||||
|
||||
3. cd wanpipe-<version>
|
||||
|
||||
4. ./Setup install
|
||||
-> proceed with default options until COMPILATION
|
||||
-> specify compilation mode 4 (SMG/SS7)
|
||||
-> proceed with default options for rest of installation
|
||||
|
||||
5. To confirm successful install
|
||||
-> wanrouter hwprobe
|
||||
|
||||
6. Download MTP2API Library / Sample code from
|
||||
-> ftp.sangoma.com/linux/custom/mtp2api
|
||||
|
||||
|
||||
Configuration
|
||||
|
||||
From the above architectural diagram one needs to configure the following:
|
||||
|
||||
1. Wanpipe AFT T1/E1 timeslot configuration per devices per link
|
||||
|
||||
Each T1/E1 port/timeslot is configued using /etc/wanpipe/wanpipe#.conf configuration file.
|
||||
The wanpipe#.conf configuration files are created using wancfg_smg configurator.
|
||||
|
||||
The AFT T1/E1 cards be configured for
|
||||
-> MTP2 API T1/E1 channels Only
|
||||
-> MTP2 API T1/E1 channels + TDM API Voice Channels
|
||||
|
||||
2. MTP2 Stack configuration for each mtp2 link
|
||||
|
||||
The MTP2 stack configuration is done via MTP2 API, in custom ss7 application
|
||||
|
||||
|
||||
Configuration Sequence
|
||||
|
||||
1. Configure wanpipe device driver + AFT hardware T1/E1 time slots
|
||||
-> use: wancfg_smg configurator
|
||||
|
||||
2. Develop mtp2api custom application that will configure the xmtp2km kernel stack
|
||||
for each mtp2 link that is associated to the T1/E1 time slot.
|
||||
|
||||
|
||||
|
||||
Wanpipe AFT T1/E1 time slot configuration
|
||||
|
||||
|
||||
MTP2 API T1/E1 channels only
|
||||
|
||||
1. Use: wancfg_smg configurator
|
||||
-> wancfg_smg
|
||||
-> For each port specify T1/E1/Clocking
|
||||
-> Select XMTP2 Only Configuration
|
||||
-> MTP2 channels for each T1/E1 timeslot
|
||||
|
||||
2. Please consult your telco on line configuration.
|
||||
|
||||
3. The wanpipe configuration files will be saved in
|
||||
-> /etc/wanpipe/wanpipe#.conf where # = { 1, 2, 3 .. }
|
||||
|
||||
|
||||
MTP2 API T1/E1 channels + TDM API Voice Channels
|
||||
|
||||
1. Run wancfg_smg configurator
|
||||
-> wancfg_smg
|
||||
-> For each port specify T1/E1/Clocking
|
||||
-> Select XMTP2 + Voice Configuration
|
||||
-> MTP2 channels for each T1/E1 timeslot
|
||||
|
||||
2. Please consult your telco on line configuration.
|
||||
|
||||
3. The wanpipe configuration files will be saved in
|
||||
-> /etc/wanpipe/wanpipe#.conf where # = { 1, 2, 3 .. }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Operation
|
||||
|
||||
Once the wanpipe devices are configured for MTP2, for each T1/E1 time slot, one must develop the mtp2api application to configure each MTP2 link in the kernel xmtp2km stack.
|
||||
|
||||
The mtp2api application MUST be started before starting wanpipe devices! The reason for this is that MTP2 links must be configured before physical devics are started.
|
||||
|
||||
1. Edit mtp2api.c file and configure the XMTP2 ports based on above wancfg_smg configuration.
|
||||
|
||||
2. Search for: /* MTP2 Configuration based on wancfg_smg configurator */
|
||||
You will see MTP2 configuration for each link and each wanpipe card device.
|
||||
|
||||
/* MTP2 Configuration based on wancfg_smg configuration */
|
||||
for (i=0;i<16;i++) {
|
||||
|
||||
/* Initialize Local MTP2 Device Structure: Likset 0 Link 0 */
|
||||
mtp2dev = &mtp2_dev_idx[MTP2_DEV_KEY(0,i)];
|
||||
|
||||
memset(mtp2dev,0,sizeof(mtp2_dev_t));
|
||||
|
||||
mtp2dev->init=1;
|
||||
mtp2dev->state=LINK_NOT_CONNECTED;
|
||||
|
||||
mtp2dev->cfg.card=1; /* Number corresponding to wanpipe config file number: wanpipe1.conf */
|
||||
mtp2dev->cfg.slot=i; /* T1/E1 timeslot/interface number -> corresponds to interface number
|
||||
in wanpipe interface name - w1g1 in wanpipe1.conf */
|
||||
mtp2dev->cfg.clear_ch=1; /* 1=8bit hdlc 0=7bit hdlc */
|
||||
mtp2dev->cfg.linkset=0; /* LinkSet number */
|
||||
mtp2dev->cfg.link=i; /* Link in LinkSet */
|
||||
mtp2dev->cfg.mtu=80*1; /* Block size per timeslot configured */
|
||||
|
||||
/* Configure MTP2 Timters */
|
||||
mtp2dev->cfg.cfg_T1 = MTP2_SEC_MS(13.0);
|
||||
mtp2dev->cfg.cfg_T2 = MTP2_SEC_MS(11.5);
|
||||
mtp2dev->cfg.cfg_T3 = MTP2_SEC_MS(11.5);
|
||||
mtp2dev->cfg.cfg_T4Pe = MTP2_SEC_MS(0.6);
|
||||
mtp2dev->cfg.cfg_T4Pn = MTP2_SEC_MS(2.30);
|
||||
mtp2dev->cfg.cfg_T5 = MTP2_SEC_MS(0.12);
|
||||
mtp2dev->cfg.cfg_T6 = MTP2_SEC_MS(3.0);
|
||||
mtp2dev->cfg.cfg_T7 = MTP2_SEC_MS(1.0);
|
||||
|
||||
mtp2dev->rx_msu=mtp2_rx_msu;
|
||||
mtp2dev->state_change=mtp2_state_change;
|
||||
mtp2dev->fd=fd;
|
||||
|
||||
/* Stop current MTP2 Link */
|
||||
err=xmtp2_stop_link (fd, &mtp2dev->cfg);
|
||||
if (err) {
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Configure MTP2 Link */
|
||||
err=xmtp2_conf_link (fd, &mtp2dev->cfg);
|
||||
if (err) {
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Power ON MTP2 Link */
|
||||
err=xmtp2_cmd (fd, mtp2dev->cfg.linkset, mtp2dev->cfg.link, LSC_CAUSE_POWER_ON, MGMT);
|
||||
if (err) {
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Start physical T1/E1 channel for the configured MTP2 Link
|
||||
If the port is already running this command will be skipped,
|
||||
The /etc/wanpipe/wanpipe#.conf file must be properly configured */
|
||||
err=xmtp2_start_facility(mtp2dev->cfg.card,mtp2dev->cfg.slot);
|
||||
if (err) {
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
mtp2dev=NULL;
|
||||
}
|
||||
|
||||
3. The above configuration must match for each wanpipe#.conf file created
|
||||
using wancfg_smg.
|
||||
|
||||
Based on above configuration mtp2api.c will start each wanpipe channel device
|
||||
on application start. This done in:
|
||||
|
||||
/* Stop wanpipe devices associated with MTP2 Links */
|
||||
xmtp2_start_facility(card,slot);
|
||||
|
||||
section of the code.
|
||||
|
||||
|
||||
Once the mtp2api.c application starts it will
|
||||
|
||||
1. Load xmtp2km module
|
||||
2. Configure each linkset and link in the module
|
||||
3. Start all wanpipe devices related to linkset and link
|
||||
4. Once the T1/E1 link comes up
|
||||
5. The mtp2api will try to bring the links into SERVICE
|
||||
6. Once Link is in SERVICE mtp2api will start transmitting
|
||||
MSU of 10 bytes long every 10 seconds on each MTP2 linkset/link.
|
||||
|
||||
|
||||
Based on this application one can develop other SS7 Stacks over the XMTP2 API.
|
||||
|
||||
|
||||
Contact
|
||||
=======
|
||||
|
||||
For more info contact
|
||||
|
||||
Nenad Corbic
|
|
@ -0,0 +1,636 @@
|
|||
/*****************************************************************************
|
||||
* libxmtp2.c SS7 MTP2 API Library
|
||||
*
|
||||
* Author(s): Mike Mueller <ss7box@gmail.com
|
||||
* Nenad Corbic <ncorbic@sangoma.com>
|
||||
*
|
||||
*
|
||||
* Copyright: (c) 2010 Xygnada Technologies
|
||||
* Sangoma Technologies Inc.
|
||||
*
|
||||
* ============================================================================
|
||||
* 1.6 Nenad Corbic <ncorbic@sangoma.com>
|
||||
* May 28 2010
|
||||
* Updated for 8 E1 worth of links.
|
||||
* Synched up with latest xmtp2 code
|
||||
*
|
||||
* 1.5 Nenad Corbic <ncorbic@sangoma.com>
|
||||
* Sep 02 2009
|
||||
* Updated for full t1/e1 config
|
||||
* update freame_per_packet to cfg->mtu
|
||||
*
|
||||
* 1.4 Nenad Corbic <ncorbic@sangoma.com>
|
||||
* Aug 19 2009
|
||||
* Updated for full t1/e1 config
|
||||
*
|
||||
* 1.3 Nenad Corbic <ncorbic@sangoma.com>
|
||||
* Jun 3 2008
|
||||
* Fixed spelling mistake in function names
|
||||
* xmtp2_restart_facility
|
||||
* xmtp2_start_facility
|
||||
*
|
||||
* 1.2 Nenad Corbic <ncorbic@sangoma.com>
|
||||
* May 21 2008
|
||||
* Updated so mtp2 links can be configured and
|
||||
* reconfigured on the fly.
|
||||
*
|
||||
* 1.1 Nenad Corbic <ncorbic@sangoma.com>
|
||||
* May 1 2008
|
||||
* Updated MTP2 Timer configuration
|
||||
*
|
||||
* 1.0 Nenad Corbic <ncorbic@sangoma.com>
|
||||
* May 1 2008
|
||||
* Initial Version
|
||||
*/
|
||||
|
||||
#include "libxmtp2.h"
|
||||
|
||||
static t_fac_Sangoma_v2 fac_Sangoma[MAX_FACILITIES];
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
void info_u (
|
||||
const char * object,
|
||||
const char * location,
|
||||
int group,
|
||||
const char * cause,
|
||||
const unsigned int detail
|
||||
)
|
||||
{
|
||||
printf ("I:%s:%s:%s:%u\n",
|
||||
object,
|
||||
location,
|
||||
cause,
|
||||
detail);
|
||||
|
||||
}
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
void xmtp2_link_util_report (
|
||||
const unsigned int ls,
|
||||
const unsigned int link,
|
||||
const unsigned int msu_octet_count,
|
||||
const unsigned int total_octet_count
|
||||
)
|
||||
{
|
||||
int util;
|
||||
if (total_octet_count != 0)
|
||||
{
|
||||
util = 100 * (msu_octet_count / total_octet_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
util = -1;
|
||||
}
|
||||
printf ("R:link util:ls %d:link %d:msu oc %u:tot oc %u:util %d\n",
|
||||
ls,
|
||||
link,
|
||||
msu_octet_count,
|
||||
total_octet_count,
|
||||
util);
|
||||
}
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
int xmtp2_load(void)
|
||||
{
|
||||
int r = system ("./xmtp2km_in");
|
||||
|
||||
if (r < 0) {
|
||||
info_u (__FILE__, __FUNCTION__,0,
|
||||
"failed to start xmtp2km:return value follows", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
int xmtp2_unload(void)
|
||||
{
|
||||
int rc=system ("modprobe -r xmtp2km");
|
||||
//printf("%s:%d: RC=%i\n",__FUNCTION__,__LINE__,rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
int xmtp2_init(void)
|
||||
{
|
||||
memset(&fac_Sangoma,0,sizeof(fac_Sangoma));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
int xmtp2_open (void)
|
||||
{
|
||||
/* install and open /dev/xmtp2km */
|
||||
int xmtp2km_fd;
|
||||
|
||||
xmtp2km_fd = open ("/dev/xmtp2km0", O_RDWR, 0);
|
||||
if (xmtp2km_fd < 0) {
|
||||
info_u (__FILE__, __FUNCTION__,0,
|
||||
"failed:open /dev/xmtp2km:xmtp2km_fd follows", xmtp2km_fd);
|
||||
}
|
||||
|
||||
return xmtp2km_fd;
|
||||
}
|
||||
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
int xmtp2_close(int fd)
|
||||
{
|
||||
if (fd >= 0) {
|
||||
close(fd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
static int xmtp2_config (int xmtp2km_fd)
|
||||
{
|
||||
/* pass /dev/xmtp2km its configuration parms */
|
||||
|
||||
int r = ioctl (xmtp2km_fd, XMTP2KM_IOCS_OPSPARMS, &fac_Sangoma);
|
||||
if (r) {
|
||||
info_u (__FILE__, __FUNCTION__,0,
|
||||
"failed:ioctl XMTP2KM_IOCS_OPSPARMS:retval follows", r);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
static int xmtp2_unconfig (int xmtp2km_fd)
|
||||
{
|
||||
/* pass /dev/xmtp2km its configuration parms */
|
||||
|
||||
int r = ioctl (xmtp2km_fd, XMTP2KM_IOCS_STOP_FAC, &fac_Sangoma);
|
||||
if (r) {
|
||||
info_u (__FILE__, __FUNCTION__,0,
|
||||
"failed:ioctl XMTP2KM_IOCS_OPSPARMS:retval follows", r);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
|
||||
int xmtp2_stop_link (int fd, xmtp_cfg_link_info_t *cfg)
|
||||
{
|
||||
/* enter the fi and si into the mtp2_link_info table for use later during init */
|
||||
int fi = cfg->card-1;
|
||||
int si = cfg->slot;
|
||||
|
||||
memset(fac_Sangoma,0,sizeof(fac_Sangoma));
|
||||
|
||||
fac_Sangoma[fi].card_name_number=cfg->card;
|
||||
sprintf (fac_Sangoma[fi].card_name, "wanpipe%u", fac_Sangoma[fi].card_name_number);
|
||||
|
||||
fac_Sangoma[fi].frames_in_packet= cfg->mtu ? cfg->mtu : 80;
|
||||
fac_Sangoma[fi].clear_channel= cfg->clear_ch;
|
||||
fac_Sangoma[fi].configured = MARK;
|
||||
|
||||
/* derived interface name: wXgY where X is the numeral in the card name
|
||||
* and Y is si + 1 */
|
||||
sprintf (fac_Sangoma[fi].link_cfg[si].if_name, "w%ug%u", fac_Sangoma[fi].card_name_number, si + 1);
|
||||
|
||||
/* get linkset and link index */
|
||||
fac_Sangoma[fi].link_cfg[si].linkset = cfg->linkset;
|
||||
fac_Sangoma[fi].link_cfg[si].link = cfg->link;
|
||||
|
||||
/* read and apply timer values */
|
||||
fac_Sangoma[fi].link_cfg[si].cfg_T1 = cfg->cfg_T1 ? cfg->cfg_T1 : MTP2_SEC_MS(13.0);
|
||||
fac_Sangoma[fi].link_cfg[si].cfg_T2 = cfg->cfg_T2 ? cfg->cfg_T2 : MTP2_SEC_MS(11.5);
|
||||
fac_Sangoma[fi].link_cfg[si].cfg_T3 = cfg->cfg_T3 ? cfg->cfg_T3 : MTP2_SEC_MS(11.5);
|
||||
fac_Sangoma[fi].link_cfg[si].cfg_T4Pe = cfg->cfg_T4Pe ? cfg->cfg_T4Pe : MTP2_SEC_MS(0.6);
|
||||
fac_Sangoma[fi].link_cfg[si].cfg_T4Pn = cfg->cfg_T4Pn ? cfg->cfg_T4Pn : MTP2_SEC_MS(2.3);
|
||||
fac_Sangoma[fi].link_cfg[si].cfg_T5 = cfg->cfg_T5 ? cfg->cfg_T5 : MTP2_SEC_MS(0.12);
|
||||
fac_Sangoma[fi].link_cfg[si].cfg_T6 = cfg->cfg_T6 ? cfg->cfg_T6 : MTP2_SEC_MS(3.0);
|
||||
fac_Sangoma[fi].link_cfg[si].cfg_T7 = cfg->cfg_T7 ? cfg->cfg_T7 : MTP2_SEC_MS(1.0);
|
||||
|
||||
fac_Sangoma[fi].link_cfg[si].configured = MARK;
|
||||
|
||||
printf("Stopping fi=%i si=%i linkset=%i link=%i\n",
|
||||
fi,si,cfg->linkset,cfg->link);
|
||||
|
||||
cfg->facility=fi;
|
||||
|
||||
return xmtp2_unconfig (fd);
|
||||
}
|
||||
|
||||
|
||||
int xmtp2_conf_link (int fd, xmtp_cfg_link_info_t *cfg)
|
||||
{
|
||||
/* enter the fi and si into the mtp2_link_info table for use later during init */
|
||||
int fi = cfg->card-1;
|
||||
int si = cfg->slot;
|
||||
|
||||
memset(fac_Sangoma,0,sizeof(fac_Sangoma));
|
||||
|
||||
fac_Sangoma[fi].card_name_number=cfg->card;
|
||||
sprintf (fac_Sangoma[fi].card_name, "wanpipe%u", fac_Sangoma[fi].card_name_number);
|
||||
|
||||
fac_Sangoma[fi].frames_in_packet=cfg->mtu;
|
||||
fac_Sangoma[fi].clear_channel= cfg->clear_ch;
|
||||
fac_Sangoma[fi].configured = MARK;
|
||||
|
||||
|
||||
/* derived interface name: wXgY where X is the numeral in the card name
|
||||
* and Y is si + 1 */
|
||||
sprintf (fac_Sangoma[fi].link_cfg[si].if_name, "w%ug%u", fac_Sangoma[fi].card_name_number, si + 1);
|
||||
|
||||
/* get linkset and link index */
|
||||
fac_Sangoma[fi].link_cfg[si].linkset = cfg->linkset;
|
||||
fac_Sangoma[fi].link_cfg[si].link = cfg->link;
|
||||
|
||||
/* read and apply timer values */
|
||||
fac_Sangoma[fi].link_cfg[si].cfg_T1 = cfg->cfg_T1 ? cfg->cfg_T1 : MTP2_SEC_MS(13.0);
|
||||
fac_Sangoma[fi].link_cfg[si].cfg_T2 = cfg->cfg_T2 ? cfg->cfg_T2 : MTP2_SEC_MS(11.5);
|
||||
fac_Sangoma[fi].link_cfg[si].cfg_T3 = cfg->cfg_T3 ? cfg->cfg_T3 : MTP2_SEC_MS(11.5);
|
||||
fac_Sangoma[fi].link_cfg[si].cfg_T4Pe = cfg->cfg_T4Pe ? cfg->cfg_T4Pe : MTP2_SEC_MS(0.6);
|
||||
fac_Sangoma[fi].link_cfg[si].cfg_T4Pn = cfg->cfg_T4Pn ? cfg->cfg_T4Pn : MTP2_SEC_MS(2.3);
|
||||
fac_Sangoma[fi].link_cfg[si].cfg_T5 = cfg->cfg_T5 ? cfg->cfg_T5 : MTP2_SEC_MS(0.12);
|
||||
fac_Sangoma[fi].link_cfg[si].cfg_T6 = cfg->cfg_T6 ? cfg->cfg_T6 : MTP2_SEC_MS(3.0);
|
||||
fac_Sangoma[fi].link_cfg[si].cfg_T7 = cfg->cfg_T7 ? cfg->cfg_T7 : MTP2_SEC_MS(1.0);
|
||||
|
||||
fac_Sangoma[fi].link_cfg[si].configured = MARK;
|
||||
|
||||
printf("Configuring fi=%i si=%i linkset=%i link=%i\n",
|
||||
fi,si,cfg->linkset,cfg->link);
|
||||
|
||||
cfg->facility=fi;
|
||||
|
||||
return xmtp2_config (fd);
|
||||
}
|
||||
|
||||
|
||||
/*===================================================================
|
||||
* xmtp2_cmd
|
||||
*==================================================================*/
|
||||
int xmtp2_cmd (
|
||||
int xmtp2km_fd,
|
||||
const unsigned int linkset,
|
||||
const unsigned int link,
|
||||
const unsigned int cause,
|
||||
const unsigned int caller)
|
||||
{
|
||||
unsigned int cmd = 0;
|
||||
int r=-1;
|
||||
|
||||
t_linkset_link linkset_link;
|
||||
|
||||
linkset_link.linkset = linkset;
|
||||
linkset_link.link = link;
|
||||
linkset_link.caller = caller;
|
||||
|
||||
switch (cause)
|
||||
{
|
||||
case LSC_CAUSE_POWER_ON:
|
||||
cmd = XMTP2KM_IOCS_PWR_ON;
|
||||
break;
|
||||
case LSC_CAUSE_EMERGENCY:
|
||||
cmd = XMTP2KM_IOCS_EMERGENCY;
|
||||
break;
|
||||
case LSC_CAUSE_EMERGENCY_CEASES:
|
||||
cmd = XMTP2KM_IOCS_EMERGENCY_CEASES;
|
||||
break;
|
||||
case LSC_CAUSE_START:
|
||||
cmd = XMTP2KM_IOCS_STARTLINK;
|
||||
break;
|
||||
case LSC_CAUSE_STOP:
|
||||
cmd = XMTP2KM_IOCS_STOPLINK;
|
||||
break;
|
||||
default:
|
||||
info_u (__FILE__, __FUNCTION__,0, "lsc invalid cause ",cause);
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = ioctl (xmtp2km_fd, cmd, &linkset_link);
|
||||
if (r)
|
||||
{
|
||||
info_u (__FILE__, __FUNCTION__,0,
|
||||
"ioctl failed:retval/cause follows", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
info_u (__FILE__, __FUNCTION__, 3,
|
||||
"cause follows", cause);
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
int xmtp2_power_on_links (int fd)
|
||||
{
|
||||
int i;
|
||||
int err=-1;
|
||||
for (i = 0; i < MAX_FACILITIES; i++)
|
||||
{
|
||||
if (!fac_Sangoma[i].configured) continue;
|
||||
|
||||
info_u (__FILE__, __FUNCTION__, 0,
|
||||
"facility configured:facility index follows", i);
|
||||
int j;
|
||||
for (j=0; j<E1_CHANNELS_IN_FRAME; j++)
|
||||
{
|
||||
if (fac_Sangoma[i].link_cfg[j].configured)
|
||||
{
|
||||
int ls = fac_Sangoma[i].link_cfg[j].linkset;
|
||||
int lnk = fac_Sangoma[i].link_cfg[j].link;
|
||||
err = xmtp2_cmd (fd, ls, lnk, LSC_CAUSE_POWER_ON, MGMT);
|
||||
if (err) {
|
||||
printf("Error: Failed power on i=%i j=%i ls=%i lnk=%i\n",
|
||||
i,j,ls,lnk);
|
||||
return err;
|
||||
}
|
||||
printf("Power on i=%i j=%i ls=%i lnk=%i\n",
|
||||
i, j, ls,lnk);
|
||||
#if 0
|
||||
info_u (__FILE__, __FUNCTION__, 0,
|
||||
"link being powered on:facility/channel/linkset/link follow", lnk);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
int xmtp2_sangoma_start (int fi)
|
||||
{
|
||||
char cmd_string_start[64]="wanrouter start ";
|
||||
strcat (cmd_string_start, fac_Sangoma[fi].card_name);
|
||||
return system (cmd_string_start);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
int xmtp2_start_facilities (void)
|
||||
{
|
||||
int i;
|
||||
int err;
|
||||
for (i = 0; i < MAX_FACILITIES; i++)
|
||||
{
|
||||
if (! fac_Sangoma[i].configured) {
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("Starting Facility %i\n",
|
||||
i);
|
||||
|
||||
err=xmtp2_sangoma_start (i);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int xmtp2_restart_facility (int card, int slot)
|
||||
{
|
||||
char cmd_string_start[64];
|
||||
|
||||
/* Interface not running */
|
||||
sprintf(cmd_string_start,"wanrouter stop w%ig%i",card,slot+1);
|
||||
system (cmd_string_start);
|
||||
|
||||
sprintf(cmd_string_start,"wanrouter start w%ig%i",card,slot+1);
|
||||
return system (cmd_string_start);
|
||||
}
|
||||
|
||||
int xmtp2_start_facility (int card, int slot)
|
||||
{
|
||||
char cmd_string_ifstatus[64];
|
||||
char cmd_string_start[64];
|
||||
int err;
|
||||
|
||||
sprintf(cmd_string_ifstatus,"ifconfig w%ig%i 2> /dev/null > /dev/null",card,slot+1);
|
||||
err=system (cmd_string_ifstatus);
|
||||
if (err) {
|
||||
/* Interface not running */
|
||||
sprintf(cmd_string_start,"wanrouter start wanpipe%i w%ig%i",card,card,slot+1);
|
||||
system (cmd_string_start);
|
||||
|
||||
return system (cmd_string_ifstatus);
|
||||
} else {
|
||||
/* Interface already running */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
void xmtp2_sangoma_stop (int fi)
|
||||
{
|
||||
char cmd_string_stop[64]="wanrouter stop ";
|
||||
strcat (cmd_string_stop, fac_Sangoma[fi].card_name);
|
||||
system (cmd_string_stop);
|
||||
}
|
||||
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
void xmtp2_stop_facilities (void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_FACILITIES; i++)
|
||||
{
|
||||
if (! fac_Sangoma[i].configured) continue;
|
||||
xmtp2_sangoma_stop (i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
int xmtp2_report_link_load (int xmtp2km_fd, t_link_opm *opm_table)
|
||||
{
|
||||
opm_table[0].ls = -1;
|
||||
|
||||
int r = ioctl (xmtp2km_fd, XMTP2KM_IOCG_GETOPM, (uint8_t *)opm_table);
|
||||
if (r < 0)
|
||||
{
|
||||
info_u (__FILE__, __FUNCTION__,0,
|
||||
"failed:ioctl XMTP2KM_IOCG_GETOPM,:retval follows", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i=0; i < MAX_MTP2LINKS; i++)
|
||||
{
|
||||
if (opm_table[i].ls < 0) break;
|
||||
xmtp2_link_util_report (
|
||||
opm_table[i].ls,
|
||||
opm_table[i].link,
|
||||
opm_table[i].msu_octet_count,
|
||||
opm_table[i].total_octet_count);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
int xmtp2_retrieve_bsnt (
|
||||
int xmtp2km_fd,
|
||||
const unsigned int linkset,
|
||||
const unsigned int link,
|
||||
const unsigned int caller)
|
||||
{
|
||||
t_bsnt retrieve_bsnt_msg;
|
||||
|
||||
retrieve_bsnt_msg.ls = linkset;
|
||||
retrieve_bsnt_msg.link = link;
|
||||
|
||||
int r = ioctl (xmtp2km_fd, XMTP2KM_IOCX_GETBSNT, (uint8_t *)&retrieve_bsnt_msg);
|
||||
if (r < 0)
|
||||
{
|
||||
info_u (__FILE__, __FUNCTION__,0,
|
||||
"failed:ioctl XMTP2KM_IOCX_GETBSNT:retval follows", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (retrieve_bsnt_msg.bsnt_retrieved == BSNT_RETRIEVED) {
|
||||
/* local bsnt retrieved */
|
||||
|
||||
} else {
|
||||
/* local bsnt canceled */
|
||||
|
||||
}
|
||||
|
||||
/* retrieve_bsnt_msg.bsnt; */
|
||||
|
||||
return retrieve_bsnt_msg.bsnt_retrieved;
|
||||
}
|
||||
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
int xmtp2_send_msu (int xmtp2km_fd, t_su_buf * p_msu)
|
||||
{
|
||||
int r = ioctl (xmtp2km_fd, XMTP2KM_IOCS_PUTMSU, p_msu);
|
||||
if (r < 0)
|
||||
{
|
||||
info_u (__FILE__, __FUNCTION__,0,
|
||||
"failed:ioctl XMTP2KM_IOCS_PUTMSU:retval follows", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
int xmtp2_read_msu(int xmtp2km_fd, t_su_buf * p_msu)
|
||||
{
|
||||
int r = ioctl (xmtp2km_fd, XMTP2KM_IOCG_GETMSU, p_msu);
|
||||
if (r < 0){
|
||||
info_u (__FILE__, __FUNCTION__,0,
|
||||
"failed:ioctl XMTP2KM_IOCG_GETMSU:retval and p_msu follow", r);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
void xmtp2_print_mem_hex_ascii (FILE * p_fd, uint8_t *buff, int len)
|
||||
{
|
||||
int i=0, j=0, c=0, printnext = 1;
|
||||
|
||||
fprintf (p_fd, "\tMARK < >\n");
|
||||
fprintf (p_fd, "-------------------------------------------------------------------------\n");
|
||||
if (len)
|
||||
{
|
||||
if (len % 16) c = len + (16 - len % 16);
|
||||
else c = len;
|
||||
}
|
||||
else c = len;
|
||||
|
||||
for (i = 0; i < c; i++)
|
||||
{
|
||||
if (printnext) { printnext--; fprintf (p_fd, "%.4x ", i & 0xffff); }
|
||||
|
||||
if (i < len) fprintf (p_fd, "%3.2x", buff[i]&0xff);
|
||||
else fprintf (p_fd, " ");
|
||||
|
||||
if (!((i+1)%8))
|
||||
{
|
||||
if ((i+1)%16) fprintf (p_fd, " -");
|
||||
else
|
||||
{
|
||||
fprintf (p_fd, " ");
|
||||
|
||||
for(j = i - 15; j <= i; j++)
|
||||
{
|
||||
if (j < len)
|
||||
{
|
||||
if ( (buff[j] & 0xff) >= 0x20 && (buff[j] & 0xff) <= 0x7e)
|
||||
fprintf (p_fd, "%c", buff[j]&0xff);
|
||||
else fprintf (p_fd, ".");
|
||||
}
|
||||
else fprintf (p_fd, " ");
|
||||
}
|
||||
|
||||
fprintf (p_fd, "\n");
|
||||
printnext = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf (p_fd, "-------------------------------------------------------------------------\n\n");
|
||||
}
|
||||
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
void xmtp2_print_msu (t_su_buf * p_msu2)
|
||||
{
|
||||
xmtp2_print_mem_hex_ascii (stdout, p_msu2->su_buf, p_msu2->hdr.su_octet_count);
|
||||
fflush (stdout);
|
||||
}
|
||||
|
|
@ -0,0 +1,481 @@
|
|||
/*****************************************************************************
|
||||
* libxmtp2.h SS7 MTP2 API Library
|
||||
*
|
||||
* Author(s): Mike Mueller <ss7box@gmail.com
|
||||
* Nenad Corbic <ncorbic@sangoma.com>
|
||||
*
|
||||
*
|
||||
* Copyright: (c) 2008 Xygnada Technologies
|
||||
* Sangoma Technologies Inc.
|
||||
*
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
#ifndef _LIBXMTP2_
|
||||
#define _LIBXMTP2_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <linux/if.h>
|
||||
|
||||
#define MARK 1
|
||||
#define MTP2_SEC_MS(sec) (sec*1000000)
|
||||
|
||||
#define XMTP2_VERSION 1.6
|
||||
|
||||
/*=================================================================
|
||||
* Ioctl definitions
|
||||
*===============================================================*/
|
||||
|
||||
/* needed for the _IOW etc stuff used later */
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
/* Use '7' as magic number */
|
||||
#define XMTP2KM_IOC_MAGIC '7'
|
||||
|
||||
#define XMTP2KM_IOCRESET _IO(XMTP2KM_IOC_MAGIC, 0)
|
||||
|
||||
/*
|
||||
* S means "Set" through a ptr,
|
||||
* T means "Tell" directly with the argument value
|
||||
* G means "Get": reply by setting through a pointer
|
||||
* Q means "Query": response is on the return value
|
||||
* X means "eXchange": G and S atomically
|
||||
* H means "sHift": T and Q atomically
|
||||
*/
|
||||
|
||||
#define XMTP2KM_IOCS_BINIT _IOW (XMTP2KM_IOC_MAGIC, 1, uint8_t *)
|
||||
#define XMTP2KM_IOCS_OPSPARMS _IOW (XMTP2KM_IOC_MAGIC, 2, uint8_t *)
|
||||
#define XMTP2KM_IOCS_PWR_ON _IOW (XMTP2KM_IOC_MAGIC, 3, uint8_t *)
|
||||
#define XMTP2KM_IOCS_EMERGENCY _IOW (XMTP2KM_IOC_MAGIC, 4, uint8_t *)
|
||||
#define XMTP2KM_IOCS_EMERGENCY_CEASES _IOW (XMTP2KM_IOC_MAGIC, 5, uint8_t *)
|
||||
#define XMTP2KM_IOCS_STARTLINK _IOW (XMTP2KM_IOC_MAGIC, 6, uint8_t *)
|
||||
#define XMTP2KM_IOCG_GETMSU _IOR (XMTP2KM_IOC_MAGIC, 7, uint8_t *)
|
||||
#define XMTP2KM_IOCS_PUTMSU _IOW (XMTP2KM_IOC_MAGIC, 8, uint8_t *)
|
||||
#define XMTP2KM_IOCX_GETTBQ _IOWR(XMTP2KM_IOC_MAGIC, 9, uint8_t *)
|
||||
#define XMTP2KM_IOCS_LNKRCVY _IOW (XMTP2KM_IOC_MAGIC, 10, uint32_t)
|
||||
#define XMTP2KM_IOCX_GETBSNT _IOWR(XMTP2KM_IOC_MAGIC, 11, uint8_t *)
|
||||
#define XMTP2KM_IOCS_STOPLINK _IOW (XMTP2KM_IOC_MAGIC, 12, uint8_t *)
|
||||
#define XMTP2KM_IOCG_GETOPM _IOR (XMTP2KM_IOC_MAGIC, 13, uint8_t *)
|
||||
#define XMTP2KM_IOCS_STOP_FAC _IOR (XMTP2KM_IOC_MAGIC, 14, uint8_t *)
|
||||
|
||||
/*
|
||||
* The other entities only have "Tell" and "Query", because they're
|
||||
* not printed in the book, and there's no need to have all six.
|
||||
* (The previous stuff was only there to show different ways to do it.
|
||||
*/
|
||||
/* ... more to come */
|
||||
#define XMTP2KM_IOCHARDRESET _IO(XMTP2KM_IOC_MAGIC, 15) /* debugging tool */
|
||||
|
||||
#define XMTP2KM_IOC_MAXNR 15
|
||||
|
||||
/*=================================================================
|
||||
* Config defines
|
||||
*===============================================================*/
|
||||
|
||||
enum e_parser_controls
|
||||
{
|
||||
NEW_LINE,
|
||||
CURRENT_LINE,
|
||||
};
|
||||
|
||||
enum e_protocol_types
|
||||
{
|
||||
PT_MTP3 = 1,
|
||||
PT_M3UA = 2,
|
||||
};
|
||||
|
||||
enum facility_types
|
||||
{
|
||||
FACILITY_TYPE_NONE = 0,
|
||||
FACILITY_TYPE_T1 = 1,
|
||||
FACILITY_TYPE_E1 = 2,
|
||||
FACILITY_TYPE_DDS = 3,
|
||||
FACILITY_TYPE_UDP = 4,
|
||||
FACILITY_TYPE_ATMII = 5,
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*=================================================================
|
||||
* Facilities defines
|
||||
*===============================================================*/
|
||||
|
||||
#define MAX_CHANNELS_IN_FRAME 32
|
||||
#define T1_CHANNELS_IN_FRAME 24
|
||||
#define E1_CHANNELS_IN_FRAME 31
|
||||
#define DDS_CHANNELS_IN_FRAME 1
|
||||
|
||||
#define MAX_RX_DATA 1024 * 16
|
||||
|
||||
#define CARD_IF_NAME_LEN 31
|
||||
|
||||
#define NUM_CHAN_T1 24
|
||||
#define NUM_CHAN_E1 31
|
||||
#define MAX_TRUNK_GROUPS 16
|
||||
#define MAX_SPAN_PER_TG 16
|
||||
#define MAX_CHANS_PER_SPAN NUM_CHAN_E1
|
||||
#define MAX_CHAN_INDEX MAX_CHANS_PER_SPAN - 1
|
||||
#define MAX_SPANS 16
|
||||
#define MAX_SPAN_INDEX MAX_SPANS - 1
|
||||
#define MAX_CHANS MAX_CHANS_PER_SPAN * MAX_SPANS
|
||||
|
||||
//#define MAX_NON_VOICE_CHAN_PER_SPAN 10
|
||||
//#define NUM_CHAN_T3 672
|
||||
//#define NUM_CHAN_E3 512
|
||||
//#define MAX_SPANS MAX_SPAN_PER_TG * MAX_TRUNK_GROUPS
|
||||
//#define DOUBLE_MAX_CHAN MAX_CHAN * 2
|
||||
|
||||
enum ss7box_system_limits
|
||||
{
|
||||
MAX_FACILITIES = 8,
|
||||
MAX_MTP2LINKS = 248, /* 8 E1 fully loaded with signalling */
|
||||
MAX_MTP3LINKSETS = 248,
|
||||
MAX_PATHS = 248,
|
||||
MAX_MTP3SLS = 32,
|
||||
MAX_MTP3_LINKS_IN_LSET = 16,
|
||||
MAX_ROUTEPATHS = 248,
|
||||
MAX_ROUTES = 248,
|
||||
MAX_UDPLINKS = 2,
|
||||
};
|
||||
|
||||
/* for each link define 128 buffers for rx, 128 for tx, and 128 for retransmission */
|
||||
#define NUM_BFRS_PER_LINK 3 * 128
|
||||
/* double the buffer pool size: one pool each for MTP3 and MTP2 */
|
||||
#define B_POOL_SIZE 2 * MAX_MTP2LINKS * NUM_BFRS_PER_LINK
|
||||
|
||||
|
||||
|
||||
/*=================================================================
|
||||
* Facilities definitions
|
||||
*===============================================================*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t configured;
|
||||
uint32_t linkset;
|
||||
uint32_t link;
|
||||
char if_name[CARD_IF_NAME_LEN];
|
||||
uint32_t cfg_T1;
|
||||
uint32_t cfg_T2;
|
||||
uint32_t cfg_T3;
|
||||
uint32_t cfg_T4Pn;
|
||||
uint32_t cfg_T4Pe;
|
||||
uint32_t cfg_T5;
|
||||
uint32_t cfg_T6;
|
||||
uint32_t cfg_T7;
|
||||
} t_link_cfg_v2;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int linkset;
|
||||
int link;
|
||||
int caller;
|
||||
} t_linkset_link;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int enabled;
|
||||
void *dev;
|
||||
int (*frame)(void *ptr, int slot, int dir, unsigned char *data, int len);
|
||||
}t_fac_trace_tap;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int configured;
|
||||
int status;
|
||||
int delay;
|
||||
int distress_counter;
|
||||
int type;
|
||||
int frames_in_packet;
|
||||
//int channels_in_frame;
|
||||
int clear_channel;
|
||||
int card_name_number;
|
||||
char card_name[CARD_IF_NAME_LEN];
|
||||
t_link_cfg_v2 link_cfg[E1_CHANNELS_IN_FRAME];
|
||||
unsigned int bs_block_lost_warning_limit;
|
||||
t_fac_trace_tap tap; /* For internal use not to be used by api */
|
||||
int pcr_error_correction; /* Enable pcr error correction */
|
||||
} t_fac_Sangoma_v2;
|
||||
|
||||
enum e_link_recovery_commands
|
||||
{
|
||||
LNKRCVY_ON = -1,
|
||||
LNKRCVY_OFF = 0
|
||||
};
|
||||
|
||||
enum e_bsnt_retrieved_indicators
|
||||
{
|
||||
BSNT_RETRIEVED =2,
|
||||
BSNT_NOT_RETRIEVED =3
|
||||
};
|
||||
|
||||
#pragma pack(1)
|
||||
/* PACKED STRUCTURE */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t cmd ;
|
||||
uint8_t fi ;
|
||||
uint8_t si ;
|
||||
uint8_t spare ;
|
||||
} t_lnkrcvy;
|
||||
|
||||
/* PACKED STRUCTURE */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t ls ;
|
||||
uint8_t link ;
|
||||
uint8_t bsnt ;
|
||||
uint8_t bsnt_retrieved ;
|
||||
} t_bsnt;
|
||||
#pragma pack()
|
||||
|
||||
|
||||
|
||||
/*=================================================================
|
||||
* SU Buffer definitions
|
||||
*===============================================================*/
|
||||
|
||||
#define SU_BFR_SIZE 300
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int facility;
|
||||
unsigned int slot;
|
||||
unsigned int linkset;
|
||||
unsigned int link;
|
||||
unsigned int clear_ch;
|
||||
unsigned int card;
|
||||
unsigned int mtu;
|
||||
uint32_t cfg_T1;
|
||||
uint32_t cfg_T2;
|
||||
uint32_t cfg_T3;
|
||||
uint32_t cfg_T4Pn;
|
||||
uint32_t cfg_T4Pe;
|
||||
uint32_t cfg_T5;
|
||||
uint32_t cfg_T6;
|
||||
uint32_t cfg_T7;
|
||||
}xmtp_cfg_link_info_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* if anything is changed from here to... */
|
||||
void * p_next; /* buffer pool linked list pointer */
|
||||
int inuse;
|
||||
int from_crosslink;
|
||||
char ac[48];
|
||||
unsigned int facility;
|
||||
unsigned int slot;
|
||||
unsigned int linkset;
|
||||
unsigned int link;
|
||||
unsigned int called;
|
||||
unsigned int caller;
|
||||
unsigned int msg_type; /* see e_mtp2_mtp3_interface_causes below */
|
||||
unsigned int su_octet_count; /* includes the BSN, FSN , LI and
|
||||
CHKSUM (2 bytes) = 5 bytes */
|
||||
} t_su_buf_hdr;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
t_su_buf_hdr hdr;
|
||||
uint8_t su_buf[SU_BFR_SIZE];
|
||||
} t_su_buf;
|
||||
|
||||
enum e_functional_entities
|
||||
{
|
||||
MGMT = -1,
|
||||
L3 = 1,
|
||||
LSC = 2,
|
||||
IAC = 3,
|
||||
RXC = 4,
|
||||
TXC = 5,
|
||||
DAEDR = 6,
|
||||
DAEDT = 7,
|
||||
SUERM = 8,
|
||||
AERM = 9,
|
||||
TIMER = 10,
|
||||
FAC_SANGOMA = 11,
|
||||
TXC_1 = 12,
|
||||
FAC_ADAX = 13,
|
||||
ATM_SAAL = 14
|
||||
};
|
||||
|
||||
enum e_mtp2_mtp3_interface_causes
|
||||
{
|
||||
/* MTP3->MTP2 Generic values */
|
||||
TX_MESSAGE =100,
|
||||
EMERGENCY =101,
|
||||
EMERGENCY_CEASE =102,
|
||||
START =103,
|
||||
STOP =104,
|
||||
RETRIEVE_BSNT =105,
|
||||
RETRIEVAL_REQUEST_AND_FSNC =106,
|
||||
RESUME =107,
|
||||
CLEAR_BUFFERS =108,
|
||||
|
||||
/* MTP2->MTP3 Generic values */
|
||||
IN_SERVICE =300,
|
||||
OUT_OF_SERVICE =301,
|
||||
REMOTE_PROCESSOR_OUTAGE =302,
|
||||
REMOTE_PROCESSOR_RECOVERED =303,
|
||||
RTB_CLEARED =304,
|
||||
RX_MESSAGE =305,
|
||||
RX_BUF_CLEARED =306,
|
||||
BSNT =307,
|
||||
RETRIEVED_MESSAGES =308,
|
||||
RETRIEVAL_COMPLETE =309,
|
||||
LINK_CONGESTION_ONSET_TX =310,
|
||||
LINK_CONGESTION_ONSET_RX =311,
|
||||
LINK_CONGESTION_CEASE_TX =312,
|
||||
LINK_CONGESTION_CEASE_RX =313,
|
||||
LINK_CONNECTED =314,
|
||||
LINK_NOT_CONNECTED =315,
|
||||
};
|
||||
|
||||
enum e_mtp2_lsc_causes
|
||||
{
|
||||
LSC_CAUSE_POWER_ON = 0,
|
||||
LSC_CAUSE_START = 1,
|
||||
LSC_CAUSE_STOP = 2,
|
||||
LSC_CAUSE_RETRIEVE_BSNT = 3,
|
||||
LSC_CAUSE_RETRIEVAL_REQUEST_AND_FSNC = 4,
|
||||
LSC_CAUSE_EMERGENCY = 5,
|
||||
LSC_CAUSE_EMERGENCY_CEASES = 6,
|
||||
LSC_CAUSE_LOCAL_PROCESSOR_OUTAGE = 7,
|
||||
LSC_CAUSE_RESUME = 8,
|
||||
LSC_CAUSE_CLEAR_BUFFERS = 9,
|
||||
LSC_CAUSE_ALIGNMENT_COMPLETE = 10,
|
||||
LSC_CAUSE_ALIGNMENT_NOT_POSSIBLE = 11,
|
||||
LSC_CAUSE_LINK_FAILURE = 12,
|
||||
LSC_CAUSE_FISU_MSU_RECEIVED = 13,
|
||||
LSC_CAUSE_SIPO = 14,
|
||||
LSC_CAUSE_SIO = 15,
|
||||
LSC_CAUSE_SIN = 16,
|
||||
LSC_CAUSE_SIE = 17,
|
||||
LSC_CAUSE_SIOS = 18,
|
||||
LSC_CAUSE_T1_EXPIRY = 19,
|
||||
LSC_CAUSE_CLEAR_RTB = 20,
|
||||
LSC_CAUSE_CLEAR_RTB_COMPLETE = 21,
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int32_t ls;
|
||||
int32_t link;
|
||||
uint32_t total_octet_count;
|
||||
uint32_t msu_octet_count;
|
||||
} t_link_opm;
|
||||
|
||||
|
||||
enum e_mtp3_entities
|
||||
{
|
||||
/* SMH */
|
||||
HMDC = 0 + 100,
|
||||
HMDT = 1 + 100,
|
||||
HMRT = 2 + 100,
|
||||
HMCG = 3 + 100,
|
||||
/* STM */
|
||||
TSFC = 4 + 100,
|
||||
TCRC = 5 + 100,
|
||||
TFRC = 6 + 100,
|
||||
TRCC = 7 + 100,
|
||||
TCBC = 8 + 100,
|
||||
TCOC = 9 + 100,
|
||||
TPRC = 10 + 100,
|
||||
TSRC = 11 + 100,
|
||||
TLAC = 12 + 100,
|
||||
/* SLM */
|
||||
LLSC = 13 + 100,
|
||||
LSAC = 14 + 100,
|
||||
#if 0
|
||||
LSLA = 15 + 100, /* not used in this implementation */
|
||||
LSLR = 16 + 100, /* not used in this implementation */
|
||||
LSLD = 17 + 100, /* not used in this implementation */
|
||||
LSDA = 18 + 100, /* not used in this implementation */
|
||||
LSTA = 19 + 100, /* not used in this implementation */
|
||||
#endif
|
||||
/* SRM */
|
||||
RTRC = 20 + 100,
|
||||
RTPC = 21 + 100,
|
||||
RSRT = 22 + 100,
|
||||
RTAC = 23 + 100,
|
||||
/* SLTC */
|
||||
SLTC = 24 + 100,
|
||||
/* Level 4 */
|
||||
LVL4 = 25 + 100,
|
||||
/* MTP3 timer facility */
|
||||
MTP3_TIMER = 26 + 100,
|
||||
/* Crosslink */
|
||||
CROSSLINK = 27 + 100,
|
||||
};
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int fi;
|
||||
int si;
|
||||
} mtp2link_info_t;
|
||||
|
||||
|
||||
/*=================================================================
|
||||
* Prototypes
|
||||
*===============================================================*/
|
||||
|
||||
void info_u (
|
||||
const char * object,
|
||||
const char * location,
|
||||
int group,
|
||||
const char * cause,
|
||||
const unsigned int detail
|
||||
);
|
||||
void xmtp2_link_util_report (
|
||||
const unsigned int ls,
|
||||
const unsigned int link,
|
||||
const unsigned int msu_octet_count,
|
||||
const unsigned int total_octet_count
|
||||
);
|
||||
int xmtp2_init(void);
|
||||
int xmtp2_load(void);
|
||||
int xmtp2_open (void);
|
||||
int xmtp2_conf_link (int fd, xmtp_cfg_link_info_t *cfg);
|
||||
int xmtp2_stop_link (int fd, xmtp_cfg_link_info_t *cfg);
|
||||
|
||||
int xmtp2_cmd (
|
||||
int xmtp2km_fd,
|
||||
const unsigned int linkset,
|
||||
const unsigned int link,
|
||||
const unsigned int cause,
|
||||
const unsigned int caller);
|
||||
int xmtp2_power_on_links (int fd);
|
||||
int xmtp2_sangoma_start (int fi);
|
||||
int xmtp2_start_facilities (void);
|
||||
void xmtp2_sangoma_stop (int fi);
|
||||
void xmtp2_stop_facilities (void);
|
||||
int xmtp2_start_facility (int card, int slot);
|
||||
int xmtp2_restart_facility (int card, int slot);
|
||||
|
||||
int xmtp2_report_link_load (int xmtp2km_fd, t_link_opm *opm_table);
|
||||
|
||||
int xmtp2_retrieve_bsnt (int xmtp2km_fd, const unsigned int linkset,
|
||||
const unsigned int link, const unsigned int caller);
|
||||
int xmtp2_send_msu (int xmtp2km_fd, t_su_buf * p_msu);
|
||||
int xmtp2_read_msu(int xmtp2km_fd, t_su_buf * p_msu);
|
||||
void xmtp2_print_msu (t_su_buf * p_msu2);
|
||||
int xmtp2_unload(void);
|
||||
int xmtp2_close(int fd);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,634 @@
|
|||
/*****************************************************************************
|
||||
* mpt2api.c SS7 MTP2 API Example Code
|
||||
*
|
||||
* Author(s): Nenad Corbic <ncorbic@sangoma.com>
|
||||
* Michael Mueller <mmueller@gmail.com>
|
||||
*
|
||||
* Copyright: (c) 2003-2010 Sangoma Technologies Inc.
|
||||
* Xygnada Technologies.
|
||||
* ============================================================================
|
||||
*
|
||||
* 1.6 Nenad Corbic <ncorbic@sangoma.com>
|
||||
* May 28 2010
|
||||
* Updated for 8 E1 worth of links.
|
||||
* Synched up with latest xmtp2 code
|
||||
*
|
||||
* 1.5 Nenad Corbic <ncorbic@sangoma.com>
|
||||
* Sep 02 2009
|
||||
* Updated for full t1/e1 config
|
||||
*
|
||||
* 1.4 Nenad Corbic <ncorbic@sangoma.com>
|
||||
* Aug 19 2009
|
||||
* Updated for full t1/e1 config
|
||||
*
|
||||
* 1.2 Nenad Corbic <ncorbic@sangoma.com>
|
||||
* May 21 2008
|
||||
* Updated so mtp2 links can be configured and
|
||||
* reconfigured on the fly.
|
||||
*
|
||||
* 1.1 Nenad Corbic <ncorbic@sangoma.com>
|
||||
* May 1 2008
|
||||
* Updated MTP2 Timer configuration
|
||||
*
|
||||
* 1.0 Nenad Corbic <ncorbic@sangoma.com>
|
||||
* May 1 2008
|
||||
* Initial Version
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <linux/if.h>
|
||||
#include "libxmtp2.h"
|
||||
|
||||
|
||||
/*===================================================================
|
||||
* Local Defines
|
||||
*==================================================================*/
|
||||
static int mtp2api_exit=0;
|
||||
static int mtp2api_reconfig=0;
|
||||
|
||||
#define MAX_MTP2_DEVS 0xFFFF
|
||||
|
||||
#define MTP2_DEV_KEY(_lset,_link) ((_lset&0xFF) << 8 | (_link&0xFF))
|
||||
|
||||
typedef struct mtp2_dev
|
||||
{
|
||||
xmtp_cfg_link_info_t cfg;
|
||||
|
||||
int state;
|
||||
int init;
|
||||
int fd;
|
||||
|
||||
int (*rx_msu)(struct mtp2_dev *dev, t_su_buf * p_msu);
|
||||
int (*state_change)(struct mtp2_dev *dev, int state);
|
||||
|
||||
} mtp2_dev_t;
|
||||
|
||||
mtp2_dev_t mtp2_dev_idx[MAX_MTP2_DEVS];
|
||||
|
||||
|
||||
|
||||
/*===================================================================
|
||||
* state_change : callback function
|
||||
*
|
||||
* Change of MTP2 State
|
||||
*
|
||||
*==================================================================*/
|
||||
int mtp2_state_change (struct mtp2_dev *dev, int state)
|
||||
{
|
||||
printf("MTP2 LinkSet %i Link %i State Change %i\n",
|
||||
dev->cfg.linkset, dev->cfg.link, state);
|
||||
|
||||
|
||||
/* FIXME: Do something with state change */
|
||||
|
||||
dev->state = state;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*===================================================================
|
||||
* rx_msu : callback function
|
||||
*
|
||||
* Received MSU packet.
|
||||
* Return 0: This function takes control over p_msu
|
||||
* Return Non 0: Lower layer will free p_msu
|
||||
*==================================================================*/
|
||||
int mtp2_rx_msu (struct mtp2_dev *dev, t_su_buf * p_msu)
|
||||
{
|
||||
int data_len;
|
||||
unsigned char *data;
|
||||
|
||||
printf("MTP2 LinkSet %i Link %i Received MSU Len=%i\n",
|
||||
dev->cfg.linkset, dev->cfg.link,p_msu->hdr.su_octet_count);
|
||||
|
||||
/* The su_octet_count contains 3 bytes header and 2 bytes crc
|
||||
* To get true data len we must decrement the octet_cout by 5 */
|
||||
data_len = p_msu->hdr.su_octet_count - 5;
|
||||
|
||||
/* First 3 bytes are mtp2 header and last 2 are crc */
|
||||
data = (unsigned char*)&p_msu->su_buf[3];
|
||||
|
||||
/* FIXME: Do something with received MSU */
|
||||
|
||||
xmtp2_print_msu(p_msu);
|
||||
|
||||
free(p_msu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*===================================================================
|
||||
* transfer_L2_to_L3
|
||||
*
|
||||
* Read xmtp2 packets and determine the packet type
|
||||
*==================================================================*/
|
||||
int transfer_L2_to_L3 (int xmtp2km_fd)
|
||||
{
|
||||
t_su_buf * p_msu;
|
||||
int r;
|
||||
mtp2_dev_t *mtp2dev;
|
||||
|
||||
X4_MTP2_TO_MTP3:
|
||||
|
||||
p_msu = malloc(sizeof(t_su_buf));
|
||||
if (!p_msu) {
|
||||
return -1;
|
||||
}
|
||||
memset(p_msu,0,sizeof(t_su_buf));
|
||||
|
||||
r = xmtp2_read_msu(xmtp2km_fd,p_msu);
|
||||
if (r < 0){
|
||||
info_u (__FILE__, __FUNCTION__,0,
|
||||
"failed:ioctl XMTP2KM_IOCG_GETMSU:retval and p_msu follow", r);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (r == 0){
|
||||
free (p_msu);
|
||||
return r;
|
||||
}
|
||||
|
||||
mtp2dev = &mtp2_dev_idx[MTP2_DEV_KEY(p_msu->hdr.linkset,p_msu->hdr.link)];
|
||||
|
||||
if (!mtp2dev->init) {
|
||||
printf("Error: Device for Linkset %i and Link %i Not inialized!\n",
|
||||
p_msu->hdr.linkset,p_msu->hdr.link);
|
||||
free (p_msu);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* distribute messages and indicators from L2 to L3 */
|
||||
switch (p_msu->hdr.msg_type)
|
||||
{
|
||||
case LINK_CONNECTED:
|
||||
info_u (__FILE__, __FUNCTION__,0,
|
||||
"facility LINK_CONNECTED:facility/slot follow", p_msu->hdr.facility);
|
||||
|
||||
if (mtp2dev->state_change) {
|
||||
mtp2dev->state_change(mtp2dev,p_msu->hdr.msg_type);
|
||||
}
|
||||
xmtp2_cmd (xmtp2km_fd, p_msu->hdr.linkset, p_msu->hdr.link, LSC_CAUSE_START, LSAC);
|
||||
break;
|
||||
|
||||
case LINK_NOT_CONNECTED:
|
||||
info_u (__FILE__, __FUNCTION__,0,
|
||||
"facility LINK_NOT_CONNECTED:facility/slot follow", p_msu->hdr.facility);
|
||||
if (mtp2dev->state_change) {
|
||||
mtp2dev->state_change(mtp2dev,p_msu->hdr.msg_type);
|
||||
}
|
||||
break;
|
||||
|
||||
case IN_SERVICE:
|
||||
info_u (__FILE__, __FUNCTION__,0,
|
||||
"facility IN_SERVICE:facility/slot follow", p_msu->hdr.facility);
|
||||
if (mtp2dev->state_change) {
|
||||
mtp2dev->state_change(mtp2dev,p_msu->hdr.msg_type);
|
||||
}
|
||||
break;
|
||||
|
||||
case OUT_OF_SERVICE:
|
||||
info_u (__FILE__, __FUNCTION__,0,
|
||||
"facility OUT_OF_SERVICE:facility/slot follow", p_msu->hdr.facility);
|
||||
if (mtp2dev->state_change) {
|
||||
mtp2dev->state_change(mtp2dev,p_msu->hdr.msg_type);
|
||||
}
|
||||
xmtp2_cmd (xmtp2km_fd, p_msu->hdr.linkset, p_msu->hdr.link, LSC_CAUSE_START, LSAC);
|
||||
break;
|
||||
|
||||
case REMOTE_PROCESSOR_OUTAGE:
|
||||
info_u (__FILE__, __FUNCTION__,0,
|
||||
"facility REMOTE_PROCESSOR_OUTAGE:facility/slot follow", p_msu->hdr.facility);
|
||||
if (mtp2dev->state_change) {
|
||||
mtp2dev->state_change(mtp2dev,p_msu->hdr.msg_type);
|
||||
}
|
||||
break;
|
||||
|
||||
case REMOTE_PROCESSOR_RECOVERED:
|
||||
info_u (__FILE__, __FUNCTION__,0,
|
||||
"facility REMOTE_PROCESSOR_RECOVERED:facility/slot follow", p_msu->hdr.facility);
|
||||
if (mtp2dev->state_change) {
|
||||
mtp2dev->state_change(mtp2dev,p_msu->hdr.msg_type);
|
||||
}
|
||||
break;
|
||||
|
||||
case RTB_CLEARED:
|
||||
info_u ( __FILE__, __FUNCTION__,0,
|
||||
"RTB_CLEARED msg :fac/slot/ls/link follow",
|
||||
p_msu->hdr.facility);
|
||||
break;
|
||||
|
||||
case RX_MESSAGE:
|
||||
info_u ( __FILE__, __FUNCTION__,0,
|
||||
"RX_MESSAGE msg :fac/slot/ls/link follow",
|
||||
p_msu->hdr.facility);
|
||||
|
||||
if (mtp2dev->rx_msu) {
|
||||
int err=mtp2dev->rx_msu(mtp2dev,p_msu);
|
||||
if (err == 0) {
|
||||
/* The higher layer has the p_msu */
|
||||
p_msu=NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case RX_BUF_CLEARED:
|
||||
info_u ( __FILE__, __FUNCTION__,0,
|
||||
"RX_BUF_CLEARED msg :fac/slot/ls/link follow",
|
||||
p_msu->hdr.facility);
|
||||
|
||||
break;
|
||||
case BSNT:
|
||||
info_u ( __FILE__, __FUNCTION__,0,
|
||||
"BSNT msg not handled with reply msg:fac/slot/ls/link follow",
|
||||
p_msu->hdr.facility);
|
||||
/* ERROR */
|
||||
break;
|
||||
case RETRIEVED_MESSAGES:
|
||||
info_u ( __FILE__, __FUNCTION__,0,
|
||||
"RETRIEVED_MESSAGES msg not handled with reply msg:fac/slot/ls/link follow",
|
||||
p_msu->hdr.facility);
|
||||
/* ERROR */
|
||||
break;
|
||||
|
||||
case RETRIEVAL_COMPLETE:
|
||||
info_u ( __FILE__, __FUNCTION__,0,
|
||||
"RETRIEVAL_COMPLETE msg :fac/slot/ls/link follow",
|
||||
p_msu->hdr.facility);
|
||||
break;
|
||||
|
||||
case LINK_CONGESTION_ONSET_TX:
|
||||
info_u ( __FILE__, __FUNCTION__,0,
|
||||
"LINK_CONGESTION_ONSET_TX msg :fac/slot/ls/link follow",
|
||||
p_msu->hdr.facility);
|
||||
break;
|
||||
|
||||
case LINK_CONGESTION_ONSET_RX:
|
||||
info_u ( __FILE__, __FUNCTION__,0,
|
||||
"LINK_CONGESTION_ONSET_RX msg :fac/slot/ls/link follow",
|
||||
p_msu->hdr.facility);
|
||||
break;
|
||||
|
||||
case LINK_CONGESTION_CEASE_TX:
|
||||
info_u ( __FILE__, __FUNCTION__,0,
|
||||
"LINK_CONGESTION_CEASE_TX msg :fac/slot/ls/link follow",
|
||||
p_msu->hdr.facility);
|
||||
break;
|
||||
|
||||
case LINK_CONGESTION_CEASE_RX:
|
||||
info_u ( __FILE__, __FUNCTION__,0,
|
||||
"LINK_CONGESTION_CEASE_RX msg :fac/slot/ls/link follow",
|
||||
p_msu->hdr.facility);
|
||||
break;
|
||||
default:
|
||||
info_u ( __FILE__, __FUNCTION__,0,
|
||||
"msg invalid msg :fac/slot/ls/link follow",
|
||||
p_msu->hdr.msg_type);
|
||||
/* ERROR */
|
||||
break;
|
||||
} /* switch */
|
||||
|
||||
if (p_msu) {
|
||||
free (p_msu);
|
||||
}
|
||||
goto X4_MTP2_TO_MTP3;
|
||||
}
|
||||
|
||||
/*===================================================================
|
||||
*
|
||||
*==================================================================*/
|
||||
int wait_for_input (int fd, int ms)
|
||||
{
|
||||
struct timeval t;
|
||||
|
||||
//FD_ZERO (&read_socks);
|
||||
//FD_ZERO (&write_socks);
|
||||
//FD_ZERO (&oob_socks);
|
||||
|
||||
/* blocking select */
|
||||
|
||||
t.tv_sec = 0;
|
||||
t.tv_usec = ms*1000;
|
||||
//select(maxsock + 1, &read_socks, &write_socks, &oob_socks, &t);
|
||||
select(fd + 1, NULL, NULL, NULL, &t);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*===================================================================
|
||||
* tx_msu
|
||||
*
|
||||
* Example of how to send msu packet
|
||||
*==================================================================*/
|
||||
int tx_msu(struct mtp2_dev *dev)
|
||||
{
|
||||
int i;
|
||||
t_su_buf t_msu;
|
||||
int data_len=10;
|
||||
memset(&t_msu,0,sizeof(t_msu));
|
||||
|
||||
|
||||
if (dev->state != IN_SERVICE) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Specify where the msu is going */
|
||||
t_msu.hdr.facility =dev->cfg.facility;
|
||||
t_msu.hdr.slot =dev->cfg.slot;
|
||||
t_msu.hdr.linkset =dev->cfg.linkset;
|
||||
t_msu.hdr.link =dev->cfg.link;
|
||||
|
||||
/* Specify msu len and data
|
||||
* First 3 bytes will be overwritten by lower layer
|
||||
* start data on the 4th octet */
|
||||
t_msu.hdr.su_octet_count=data_len;
|
||||
for (i=0;i<t_msu.hdr.su_octet_count;i++) {
|
||||
t_msu.su_buf[i+3]=i;
|
||||
}
|
||||
|
||||
/* We must add 5 bytes to octet count to account for
|
||||
* 3 byte header and 2 byte crc tail -> this is explained in libxmtp2.h */
|
||||
t_msu.hdr.su_octet_count+=5;
|
||||
|
||||
printf("LINK TX MSU f=%i,slot=%i,ls=%i,l=%i,mt=%i\n",
|
||||
t_msu.hdr.facility,t_msu.hdr.slot,t_msu.hdr.linkset,
|
||||
t_msu.hdr.link,t_msu.hdr.msg_type);
|
||||
|
||||
|
||||
/* Transmit MSU */
|
||||
return xmtp2_send_msu(dev->fd,&t_msu);
|
||||
}
|
||||
|
||||
|
||||
/*===================================================================
|
||||
* Signal Handlers
|
||||
*
|
||||
* Example of how to send msu packet
|
||||
*==================================================================*/
|
||||
static int do_shut(int sig)
|
||||
{
|
||||
mtp2api_exit=1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_ignore(int sig)
|
||||
{
|
||||
mtp2api_reconfig=1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*===================================================================
|
||||
* Main Code
|
||||
*==================================================================*/
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int fd;
|
||||
int err;
|
||||
int cnt=0;
|
||||
int i;
|
||||
mtp2_dev_t *mtp2dev;
|
||||
|
||||
/* FIXME: Used to obain full link status reports */
|
||||
t_link_opm opm_table[MAX_MTP2LINKS];
|
||||
memset(opm_table,0,sizeof(opm_table));
|
||||
|
||||
(void) signal(SIGINT,(void *) do_shut);
|
||||
(void) signal(SIGPIPE,(void *) do_ignore);
|
||||
(void) signal(SIGUSR1,(void *) do_ignore);
|
||||
(void) signal(SIGHUP,(void *) do_shut);
|
||||
|
||||
|
||||
xmtp2_init();
|
||||
|
||||
err=xmtp2_load();
|
||||
if (err < 0) {
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
fd = xmtp2_open();
|
||||
if (fd < 0) {
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
reconfig:
|
||||
|
||||
/* MTP2 Configuration based on wancfg_smg configurator */
|
||||
|
||||
#if 1
|
||||
/* Configuration per T1/E1 timeslot, where a mtp2 link exists
|
||||
on a singel timeslot of a T1/E1 port. In this example
|
||||
we are configuring 16 mtp2 links. However, this example
|
||||
can be rewritten per user config
|
||||
Sample wanpipe config file: wanpipe/wanpipe1.conf.16_channels_e1
|
||||
*/
|
||||
for (i=0;i<16;i++) {
|
||||
|
||||
/* Initialize Local MTP2 Device Structure: Likset 0 Link 0 */
|
||||
mtp2dev = &mtp2_dev_idx[MTP2_DEV_KEY(0,i)];
|
||||
|
||||
memset(mtp2dev,0,sizeof(mtp2_dev_t));
|
||||
|
||||
mtp2dev->init=1;
|
||||
mtp2dev->state=LINK_NOT_CONNECTED;
|
||||
mtp2dev->cfg.card=1; /* Number corresponding to wanpipe config file number: wanpipe1.conf */
|
||||
mtp2dev->cfg.slot=i; /* T1/E1 timeslot/interface number -> corresponds to interface number
|
||||
in wanpipe interface name - w1g1 in wanpipe1.conf */
|
||||
mtp2dev->cfg.clear_ch=1; /* 1=8bit hdlc 0=7bit hdlc */
|
||||
mtp2dev->cfg.linkset=0; /* LinkSet number */
|
||||
mtp2dev->cfg.link=i; /* Link in LinkSet */
|
||||
mtp2dev->cfg.mtu=80*1; /* Block size per timeslot configured */
|
||||
|
||||
/* Configure MTP2 Timters */
|
||||
mtp2dev->cfg.cfg_T1 = MTP2_SEC_MS(13.0);
|
||||
mtp2dev->cfg.cfg_T2 = MTP2_SEC_MS(11.5);
|
||||
mtp2dev->cfg.cfg_T3 = MTP2_SEC_MS(11.5);
|
||||
mtp2dev->cfg.cfg_T4Pe = MTP2_SEC_MS(0.6);
|
||||
mtp2dev->cfg.cfg_T4Pn = MTP2_SEC_MS(2.30);
|
||||
mtp2dev->cfg.cfg_T5 = MTP2_SEC_MS(0.12);
|
||||
mtp2dev->cfg.cfg_T6 = MTP2_SEC_MS(3.0);
|
||||
mtp2dev->cfg.cfg_T7 = MTP2_SEC_MS(1.0);
|
||||
|
||||
mtp2dev->rx_msu=mtp2_rx_msu;
|
||||
mtp2dev->state_change=mtp2_state_change;
|
||||
mtp2dev->fd=fd;
|
||||
|
||||
/* Stop current MTP2 Link */
|
||||
err=xmtp2_stop_link (fd, &mtp2dev->cfg);
|
||||
if (err) {
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Configure MTP2 Link */
|
||||
err=xmtp2_conf_link (fd, &mtp2dev->cfg);
|
||||
if (err) {
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Power ON MTP2 Link */
|
||||
err=xmtp2_cmd (fd, mtp2dev->cfg.linkset, mtp2dev->cfg.link, LSC_CAUSE_POWER_ON, MGMT);
|
||||
if (err) {
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Start physical T1/E1 channel for the configured MTP2 Link
|
||||
If the port is already running this command will be skipped,
|
||||
The /etc/wanpipe/wanpipe#.conf file must be properly configured */
|
||||
err=xmtp2_start_facility(mtp2dev->cfg.card,mtp2dev->cfg.slot);
|
||||
if (err) {
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
mtp2dev=NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Configuration for FULL T1/E1 port, where a mtp2 link exists
|
||||
on all timeslot of a T1/E1 port. In this example
|
||||
we are configuring 1 mtp2 link over full T1/E1.
|
||||
Sample wanpipe config file: wanpipe/wanpipe1.conf.full_e1
|
||||
*/
|
||||
for (i=0;i<1;i++) {
|
||||
|
||||
/* Initialize Local MTP2 Device Structure: Likset 0 Link 0 */
|
||||
mtp2dev = &mtp2_dev_idx[MTP2_DEV_KEY(0,i)];
|
||||
|
||||
memset(mtp2dev,0,sizeof(mtp2_dev_t));
|
||||
|
||||
mtp2dev->init=1;
|
||||
mtp2dev->state=LINK_NOT_CONNECTED;
|
||||
mtp2dev->cfg.card=1; /* Number corresponding to wanpipe config file number: wanpipe1.conf */
|
||||
mtp2dev->cfg.slot=i; /* T1/E1 timeslot/interface number -> corresponds to interface number
|
||||
in wanpipe interface name - w1g1 in wanpipe1.conf */
|
||||
mtp2dev->cfg.clear_ch=1; /* 1=8bit hdlc 0=7bit hdlc */
|
||||
mtp2dev->cfg.linkset=0; /* LinkSet number */
|
||||
mtp2dev->cfg.link=i; /* Link in LinkSet */
|
||||
mtp2dev->cfg.mtu=80*31; /* Block size per timeslot configured.
|
||||
In this example its all 31 timeslosts
|
||||
IMPORTANTA: wanpipe1.conf must be configured with ACTIVE_CH=ALL */
|
||||
|
||||
/* Configure MTP2 Timters */
|
||||
mtp2dev->cfg.cfg_T1 = MTP2_SEC_MS(13.0);
|
||||
mtp2dev->cfg.cfg_T2 = MTP2_SEC_MS(11.5);
|
||||
mtp2dev->cfg.cfg_T3 = MTP2_SEC_MS(11.5);
|
||||
mtp2dev->cfg.cfg_T4Pe = MTP2_SEC_MS(0.6);
|
||||
mtp2dev->cfg.cfg_T4Pn = MTP2_SEC_MS(2.30);
|
||||
mtp2dev->cfg.cfg_T5 = MTP2_SEC_MS(0.12);
|
||||
mtp2dev->cfg.cfg_T6 = MTP2_SEC_MS(3.0);
|
||||
mtp2dev->cfg.cfg_T7 = MTP2_SEC_MS(1.0);
|
||||
|
||||
mtp2dev->rx_msu=mtp2_rx_msu;
|
||||
mtp2dev->state_change=mtp2_state_change;
|
||||
mtp2dev->fd=fd;
|
||||
|
||||
/* Stop current MTP2 Link */
|
||||
err=xmtp2_stop_link (fd, &mtp2dev->cfg);
|
||||
if (err) {
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Configure MTP2 Link */
|
||||
err=xmtp2_conf_link (fd, &mtp2dev->cfg);
|
||||
if (err) {
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Power ON MTP2 Link */
|
||||
err=xmtp2_cmd (fd, mtp2dev->cfg.linkset, mtp2dev->cfg.link, LSC_CAUSE_POWER_ON, MGMT);
|
||||
if (err) {
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Start physical T1/E1 channel for the configured MTP2 Link
|
||||
If the port is already running this command will be skipped,
|
||||
The /etc/wanpipe/wanpipe#.conf file must be properly configured */
|
||||
err=xmtp2_start_facility(mtp2dev->cfg.card,mtp2dev->cfg.slot);
|
||||
if (err) {
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
mtp2dev=NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Print out full link Report */
|
||||
err=xmtp2_report_link_load(fd,opm_table);
|
||||
if (err) {
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
/* Start the Main Loop */
|
||||
|
||||
for (;;) {
|
||||
|
||||
/* Check for any MTP2 events */
|
||||
err=transfer_L2_to_L3(fd);
|
||||
if (err < 0) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Delay 100ms */
|
||||
wait_for_input (fd,100);
|
||||
|
||||
/* Print out link report every 10 sec */
|
||||
if (++cnt % 100 == 0) {
|
||||
cnt=0;
|
||||
xmtp2_report_link_load(fd,opm_table);
|
||||
|
||||
/* FIXME: This is just an example one would spawn a tx thread
|
||||
or put the tx_msu function as part of higher state machine */
|
||||
|
||||
mtp2dev = &mtp2_dev_idx[MTP2_DEV_KEY(0,0)];
|
||||
if (mtp2dev->init) {
|
||||
tx_msu(mtp2dev);
|
||||
}
|
||||
mtp2dev = &mtp2_dev_idx[MTP2_DEV_KEY(1,0)];
|
||||
if (mtp2dev->init) {
|
||||
tx_msu(mtp2dev);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Transmit each time */
|
||||
mtp2dev = &mtp2_dev_idx[MTP2_DEV_KEY(0,0)];
|
||||
if (mtp2dev->init) {
|
||||
tx_msu(mtp2dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mtp2api_exit){
|
||||
break;
|
||||
}
|
||||
|
||||
if (mtp2api_reconfig){
|
||||
mtp2api_reconfig=0;
|
||||
goto reconfig;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
xmtp2_close(fd);
|
||||
#if 0
|
||||
xmtp2_stop_facilities();
|
||||
xmtp2_unload();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
#================================================
|
||||
# WANPIPE1 Configuration File
|
||||
#================================================
|
||||
#
|
||||
# Date: Tue Apr 29 09:32:38 UYT 2008
|
||||
#
|
||||
# Note: This file was generated automatically
|
||||
# by /usr/sbin/wancfg program.
|
||||
#
|
||||
# If you want to edit this file, it is
|
||||
# recommended that you use wancfg program
|
||||
# to do so.
|
||||
#================================================
|
||||
# Sangoma Technologies Inc.
|
||||
#================================================
|
||||
|
||||
[devices]
|
||||
wanpipe1 = WAN_AFT_TE1, Comment
|
||||
|
||||
[interfaces]
|
||||
w1g1 = wanpipe1, , XMTP2_API, Comment
|
||||
|
||||
[wanpipe1]
|
||||
CARD_TYPE = AFT
|
||||
S514CPU = A
|
||||
CommPort = PRI
|
||||
AUTO_PCISLOT = NO
|
||||
PCISLOT = 4
|
||||
PCIBUS = 5
|
||||
FE_MEDIA = E1
|
||||
FE_LCODE = HDB3
|
||||
FE_FRAME = NCRC4
|
||||
FE_LINE = 1
|
||||
TE_CLOCK = MASTER
|
||||
TE_REF_CLOCK = 0
|
||||
TE_HIGHIMPEDANCE = NO
|
||||
TE_RX_SLEVEL = 120
|
||||
LBO = 120OH
|
||||
TE_SIG_MODE = CCS
|
||||
FE_TXTRISTATE = NO
|
||||
MTU = 80
|
||||
UDPPORT = 9000
|
||||
TTL = 255
|
||||
IGNORE_FRONT_END = NO
|
||||
TDMV_HW_DTMF = NO
|
||||
|
||||
[w1g1]
|
||||
HDLC_STREAMING = NO
|
||||
ACTIVE_CH = 1
|
||||
MTU = 80
|
||||
MRU = 80
|
||||
DATA_MUX = NO
|
||||
TDMV_HWEC = NO
|
||||
TRUE_ENCODING_TYPE = NO
|
||||
|
||||
|
|
@ -0,0 +1,238 @@
|
|||
#================================================
|
||||
# WANPIPE1 Configuration File
|
||||
#================================================
|
||||
#
|
||||
# Date: Tue Apr 29 09:32:38 UYT 2008
|
||||
#
|
||||
# Note: This file was generated automatically
|
||||
# by /usr/sbin/wancfg program.
|
||||
#
|
||||
# If you want to edit this file, it is
|
||||
# recommended that you use wancfg program
|
||||
# to do so.
|
||||
#================================================
|
||||
# Sangoma Technologies Inc.
|
||||
#================================================
|
||||
|
||||
[devices]
|
||||
wanpipe1 = WAN_AFT_TE1, Comment
|
||||
|
||||
[interfaces]
|
||||
w1g1 = wanpipe1, , XMTP2_API, Comment
|
||||
|
||||
w1g2 = wanpipe1, , XMTP2_API, Comment
|
||||
|
||||
w1g3 = wanpipe1, , XMTP2_API, Comment
|
||||
|
||||
w1g4 = wanpipe1, , XMTP2_API, Comment
|
||||
|
||||
w1g5 = wanpipe1, , XMTP2_API, Comment
|
||||
|
||||
w1g6 = wanpipe1, , XMTP2_API, Comment
|
||||
|
||||
w1g7 = wanpipe1, , XMTP2_API, Comment
|
||||
|
||||
w1g8 = wanpipe1, , XMTP2_API, Comment
|
||||
|
||||
w1g9 = wanpipe1, , XMTP2_API, Comment
|
||||
|
||||
w1g10 = wanpipe1, , XMTP2_API, Comment
|
||||
|
||||
w1g11 = wanpipe1, , XMTP2_API, Comment
|
||||
|
||||
w1g12 = wanpipe1, , XMTP2_API, Comment
|
||||
|
||||
w1g13 = wanpipe1, , XMTP2_API, Comment
|
||||
|
||||
w1g14 = wanpipe1, , XMTP2_API, Comment
|
||||
|
||||
w1g15 = wanpipe1, , XMTP2_API, Comment
|
||||
|
||||
w1g16 = wanpipe1, , XMTP2_API, Comment
|
||||
|
||||
|
||||
[wanpipe1]
|
||||
CARD_TYPE = AFT
|
||||
S514CPU = A
|
||||
CommPort = PRI
|
||||
AUTO_PCISLOT = NO
|
||||
PCISLOT = 4
|
||||
PCIBUS = 5
|
||||
FE_MEDIA = E1
|
||||
FE_LCODE = HDB3
|
||||
FE_FRAME = NCRC4
|
||||
FE_LINE = 1
|
||||
TE_CLOCK = MASTER
|
||||
TE_REF_CLOCK = 0
|
||||
TE_HIGHIMPEDANCE = NO
|
||||
TE_RX_SLEVEL = 120
|
||||
LBO = 120OH
|
||||
TE_SIG_MODE = CCS
|
||||
FE_TXTRISTATE = NO
|
||||
MTU = 80
|
||||
UDPPORT = 9000
|
||||
TTL = 255
|
||||
IGNORE_FRONT_END = NO
|
||||
TDMV_HW_DTMF = NO
|
||||
|
||||
[w1g24.xmtp2]
|
||||
|
||||
[w1g1]
|
||||
HDLC_STREAMING = NO
|
||||
ACTIVE_CH = 1
|
||||
MTU = 80
|
||||
MRU = 80
|
||||
DATA_MUX = NO
|
||||
TDMV_HWEC = NO
|
||||
TRUE_ENCODING_TYPE = NO
|
||||
|
||||
|
||||
[w1g2]
|
||||
HDLC_STREAMING = NO
|
||||
ACTIVE_CH = 2
|
||||
MTU = 80
|
||||
MRU = 80
|
||||
DATA_MUX = NO
|
||||
TDMV_HWEC = NO
|
||||
TRUE_ENCODING_TYPE = NO
|
||||
|
||||
|
||||
[w1g3]
|
||||
HDLC_STREAMING = NO
|
||||
ACTIVE_CH = 3
|
||||
MTU = 80
|
||||
MRU = 80
|
||||
DATA_MUX = NO
|
||||
TDMV_HWEC = NO
|
||||
TRUE_ENCODING_TYPE = NO
|
||||
|
||||
|
||||
[w1g4]
|
||||
HDLC_STREAMING = NO
|
||||
ACTIVE_CH = 4
|
||||
MTU = 80
|
||||
MRU = 80
|
||||
DATA_MUX = NO
|
||||
TDMV_HWEC = NO
|
||||
TRUE_ENCODING_TYPE = NO
|
||||
|
||||
|
||||
[w1g5]
|
||||
HDLC_STREAMING = NO
|
||||
ACTIVE_CH = 5
|
||||
MTU = 80
|
||||
MRU = 80
|
||||
DATA_MUX = NO
|
||||
TDMV_HWEC = NO
|
||||
TRUE_ENCODING_TYPE = NO
|
||||
|
||||
|
||||
[w1g6]
|
||||
HDLC_STREAMING = NO
|
||||
ACTIVE_CH = 6
|
||||
MTU = 80
|
||||
MRU = 80
|
||||
DATA_MUX = NO
|
||||
TDMV_HWEC = NO
|
||||
TRUE_ENCODING_TYPE = NO
|
||||
|
||||
|
||||
[w1g7]
|
||||
HDLC_STREAMING = NO
|
||||
ACTIVE_CH = 7
|
||||
MTU = 80
|
||||
MRU = 80
|
||||
DATA_MUX = NO
|
||||
TDMV_HWEC = NO
|
||||
TRUE_ENCODING_TYPE = NO
|
||||
|
||||
|
||||
[w1g8]
|
||||
HDLC_STREAMING = NO
|
||||
ACTIVE_CH = 8
|
||||
MTU = 80
|
||||
MRU = 80
|
||||
DATA_MUX = NO
|
||||
TDMV_HWEC = NO
|
||||
TRUE_ENCODING_TYPE = NO
|
||||
|
||||
|
||||
[w1g9]
|
||||
HDLC_STREAMING = NO
|
||||
ACTIVE_CH = 9
|
||||
MTU = 80
|
||||
MRU = 80
|
||||
DATA_MUX = NO
|
||||
TDMV_HWEC = NO
|
||||
TRUE_ENCODING_TYPE = NO
|
||||
|
||||
|
||||
[w1g10]
|
||||
HDLC_STREAMING = NO
|
||||
ACTIVE_CH = 10
|
||||
MTU = 80
|
||||
MRU = 80
|
||||
DATA_MUX = NO
|
||||
TDMV_HWEC = NO
|
||||
TRUE_ENCODING_TYPE = NO
|
||||
|
||||
|
||||
[w1g11]
|
||||
HDLC_STREAMING = NO
|
||||
ACTIVE_CH = 11
|
||||
MTU = 80
|
||||
MRU = 80
|
||||
DATA_MUX = NO
|
||||
TDMV_HWEC = NO
|
||||
TRUE_ENCODING_TYPE = NO
|
||||
|
||||
|
||||
[w1g12]
|
||||
HDLC_STREAMING = NO
|
||||
ACTIVE_CH = 12
|
||||
MTU = 80
|
||||
MRU = 80
|
||||
DATA_MUX = NO
|
||||
TDMV_HWEC = NO
|
||||
TRUE_ENCODING_TYPE = NO
|
||||
|
||||
|
||||
[w1g13]
|
||||
HDLC_STREAMING = NO
|
||||
ACTIVE_CH = 13
|
||||
MTU = 80
|
||||
MRU = 80
|
||||
DATA_MUX = NO
|
||||
TDMV_HWEC = NO
|
||||
TRUE_ENCODING_TYPE = NO
|
||||
|
||||
|
||||
[w1g14]
|
||||
HDLC_STREAMING = NO
|
||||
ACTIVE_CH = 14
|
||||
MTU = 80
|
||||
MRU = 80
|
||||
DATA_MUX = NO
|
||||
TDMV_HWEC = NO
|
||||
TRUE_ENCODING_TYPE = NO
|
||||
|
||||
|
||||
[w1g15]
|
||||
HDLC_STREAMING = NO
|
||||
ACTIVE_CH = 15
|
||||
MTU = 80
|
||||
MRU = 80
|
||||
DATA_MUX = NO
|
||||
TDMV_HWEC = NO
|
||||
TRUE_ENCODING_TYPE = NO
|
||||
|
||||
|
||||
[w1g16]
|
||||
HDLC_STREAMING = NO
|
||||
ACTIVE_CH = 16
|
||||
MTU = 80
|
||||
MRU = 80
|
||||
DATA_MUX = NO
|
||||
TDMV_HWEC = NO
|
||||
TRUE_ENCODING_TYPE = NO
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
#================================================
|
||||
# WANPIPE1 Configuration File
|
||||
#================================================
|
||||
#
|
||||
# Date: Tue Apr 29 09:32:38 UYT 2008
|
||||
#
|
||||
# Note: This file was generated automatically
|
||||
# by /usr/sbin/wancfg program.
|
||||
#
|
||||
# If you want to edit this file, it is
|
||||
# recommended that you use wancfg program
|
||||
# to do so.
|
||||
#================================================
|
||||
# Sangoma Technologies Inc.
|
||||
#================================================
|
||||
|
||||
[devices]
|
||||
wanpipe1 = WAN_AFT_TE1, Comment
|
||||
|
||||
[interfaces]
|
||||
w1g1 = wanpipe1, , XMTP2_API, Comment
|
||||
|
||||
[wanpipe1]
|
||||
CARD_TYPE = AFT
|
||||
S514CPU = A
|
||||
CommPort = PRI
|
||||
AUTO_PCISLOT = NO
|
||||
PCISLOT = 4
|
||||
PCIBUS = 5
|
||||
FE_MEDIA = E1
|
||||
FE_LCODE = HDB3
|
||||
FE_FRAME = NCRC4
|
||||
FE_LINE = 1
|
||||
TE_CLOCK = MASTER
|
||||
TE_REF_CLOCK = 0
|
||||
TE_HIGHIMPEDANCE = NO
|
||||
TE_RX_SLEVEL = 120
|
||||
LBO = 120OH
|
||||
TE_SIG_MODE = CCS
|
||||
FE_TXTRISTATE = NO
|
||||
MTU = 80
|
||||
UDPPORT = 9000
|
||||
TTL = 255
|
||||
IGNORE_FRONT_END = NO
|
||||
TDMV_HW_DTMF = NO
|
||||
|
||||
[w1g1]
|
||||
HDLC_STREAMING = NO
|
||||
ACTIVE_CH = ALL
|
||||
MTU = 2480
|
||||
MRU = 2480
|
||||
DATA_MUX = NO
|
||||
TDMV_HWEC = NO
|
||||
TRUE_ENCODING_TYPE = NO
|
||||
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
#================================================
|
||||
# WANPIPE1 Configuration File
|
||||
#================================================
|
||||
#
|
||||
# Date: Tue Apr 29 09:32:38 UYT 2008
|
||||
#
|
||||
# Note: This file was generated automatically
|
||||
# by /usr/sbin/wancfg program.
|
||||
#
|
||||
# If you want to edit this file, it is
|
||||
# recommended that you use wancfg program
|
||||
# to do so.
|
||||
#================================================
|
||||
# Sangoma Technologies Inc.
|
||||
#================================================
|
||||
|
||||
[devices]
|
||||
wanpipe1 = WAN_AFT_TE1, Comment
|
||||
|
||||
[interfaces]
|
||||
w1g1 = wanpipe1, , XMTP2_API, Comment
|
||||
|
||||
[wanpipe1]
|
||||
CARD_TYPE = AFT
|
||||
S514CPU = A
|
||||
CommPort = PRI
|
||||
AUTO_PCISLOT = NO
|
||||
PCISLOT = 4
|
||||
PCIBUS = 5
|
||||
FE_MEDIA = E1
|
||||
FE_LCODE = HDB3
|
||||
FE_FRAME = NCRC4
|
||||
FE_LINE = 1
|
||||
TE_CLOCK = MASTER
|
||||
TE_REF_CLOCK = 0
|
||||
TE_HIGHIMPEDANCE = NO
|
||||
TE_RX_SLEVEL = 120
|
||||
LBO = 120OH
|
||||
TE_SIG_MODE = CCS
|
||||
FE_TXTRISTATE = NO
|
||||
MTU = 80
|
||||
UDPPORT = 9000
|
||||
TTL = 255
|
||||
IGNORE_FRONT_END = NO
|
||||
TDMV_HW_DTMF = NO
|
||||
|
||||
[w1g1]
|
||||
HDLC_STREAMING = NO
|
||||
ACTIVE_CH = 1
|
||||
MTU = 80
|
||||
MRU = 80
|
||||
DATA_MUX = NO
|
||||
TDMV_HWEC = NO
|
||||
TRUE_ENCODING_TYPE = NO
|
||||
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
#================================================
|
||||
# WANPIPE1 Configuration File
|
||||
#================================================
|
||||
#
|
||||
# Date: Tue June 12 18:18:28 EST 2007
|
||||
#
|
||||
# Note: This file was generated automatically
|
||||
# by /usr/sbin/wancfg program.
|
||||
#
|
||||
# If you want to edit this file, it is
|
||||
# recommended that you use wancfg program
|
||||
# to do so.
|
||||
#================================================
|
||||
# Sangoma Technologies Inc.
|
||||
#================================================
|
||||
|
||||
[devices]
|
||||
wanpipe2 = WAN_AFT_TE1, Comment
|
||||
|
||||
[interfaces]
|
||||
w2g1 = wanpipe2, , TDM_VOICE_API, Comment
|
||||
w2g24 = wanpipe2, , XMTP2_API, Comment
|
||||
|
||||
[wanpipe2]
|
||||
CARD_TYPE = AFT
|
||||
S514CPU = A
|
||||
CommPort = PRI
|
||||
AUTO_PCISLOT = NO
|
||||
PCISLOT = 4
|
||||
PCIBUS = 5
|
||||
FE_MEDIA = T1
|
||||
FE_LCODE = B8ZS
|
||||
FE_FRAME = ESF
|
||||
FE_LINE = 2
|
||||
TE_CLOCK = MASTER
|
||||
TE_REF_CLOCK = 0
|
||||
|
||||
TE_HIGHIMPEDANCE = NO
|
||||
LBO = 0DB
|
||||
FE_TXTRISTATE = NO
|
||||
MTU = 1500
|
||||
UDPPORT = 9000
|
||||
TTL = 255
|
||||
IGNORE_FRONT_END = NO
|
||||
TDMV_SPAN = 2
|
||||
TDMV_DCHAN = 0
|
||||
|
||||
[w2g1]
|
||||
ACTIVE_CH = 1-23
|
||||
TDMV_ECHO_OFF = NO
|
||||
TDMV_HWEC = no
|
||||
MTU = 80
|
||||
|
||||
|
||||
[w2g24]
|
||||
ACTIVE_CH = 24
|
||||
MTU = 80
|
||||
MRU = 80
|
||||
TDMV_ECHO_OFF = NO
|
||||
TDMV_HWEC = NO
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# xmtp2km_in: xmtp2km installer
|
||||
#
|
||||
# Derivation: Copyright (C) 2005 Xygnada Technology, Inc.
|
||||
# Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
|
||||
# Copyright (C) 2001 O'Reilly & Associates
|
||||
#
|
||||
# The source code in this file can be freely used, adapted,
|
||||
# and redistributed in source or binary form, so long as an
|
||||
# acknowledgment appears in derived source files. The citation
|
||||
# should list that the code comes from the book "Linux Device
|
||||
# Drivers" by Alessandro Rubini and Jonathan Corbet, published
|
||||
# by O'Reilly & Associates. No warranty is attached;
|
||||
# we cannot take responsibility for errors or fitness for use.
|
||||
#
|
||||
#
|
||||
# $Id: xmtp2km_in,v 1.1 2005/12/05 17:48:45 mike01 Exp $
|
||||
module="xmtp2km"
|
||||
device="xmtp2km"
|
||||
mode="664"
|
||||
path=/lib/modules/`uname -r`/kernel/drivers/net/wan
|
||||
|
||||
# Group: since distributions do it differently, look for wheel or use staff
|
||||
if grep -q '^staff:' /etc/group; then
|
||||
group="staff"
|
||||
else
|
||||
group="wheel"
|
||||
fi
|
||||
|
||||
# invoke insmod with all arguments we got
|
||||
# and use a pathname, as insmod doesn't look in . by default
|
||||
#/sbin/insmod ./$module.ko $* || exit 1
|
||||
#/sbin/insmod /usr/src/xmtp2km/$module.ko $* || exit 1
|
||||
/sbin/insmod $path/$module.ko $* || exit 1
|
||||
|
||||
# retrieve major number
|
||||
major=$(awk "\$2==\"$module\" {print \$1}" /proc/devices)
|
||||
|
||||
# Remove stale nodes and replace them, then give gid and perms
|
||||
|
||||
rm -f /dev/${device}0
|
||||
mknod /dev/${device}0 c $major 0
|
||||
ln -sf ${device}0 /dev/${device}
|
||||
chgrp $group /dev/${device}0
|
||||
chmod $mode /dev/${device}0
|
||||
|
||||
exit 23
|
|
@ -1,5 +1,5 @@
|
|||
Package: wanpipe
|
||||
Version: 3.5.11-0
|
||||
Version: 3.5.12-0
|
||||
Section: networking
|
||||
Priority: optional
|
||||
Architecture: all
|
||||
|
|
|
@ -525,6 +525,7 @@ void aft_background_timer_expire(unsigned long pcard);
|
|||
#endif
|
||||
|
||||
int aft_fe_loop_back_status(sdla_t *card);
|
||||
int aft_hdlc_repeat_mangle(sdla_t *card,private_area_t *chan, netskb_t *skb, wp_api_hdr_t *tx_hdr, netskb_t **rkb);
|
||||
|
||||
#endif /* WAN_KERNEL */
|
||||
|
||||
|
|
|
@ -89,6 +89,8 @@ enum {
|
|||
WP_FIFO_ERROR_BIT,
|
||||
WP_CRC_ERROR_BIT,
|
||||
WP_ABORT_ERROR_BIT,
|
||||
WP_FRAME_ERROR_BIT,
|
||||
WP_DMA_ERROR_BIT
|
||||
};
|
||||
|
||||
/*================================================================
|
||||
|
@ -474,14 +476,26 @@ typedef struct aft_driver_performance_stats {
|
|||
#define POLL_EVENT_OOB (1 << 2) /* Out-Of-Band events such as Line Connect/Disconnect,
|
||||
RBS change, Ring, On/Off Hook, DTMF... */
|
||||
|
||||
#define POLLIN POLL_EVENT_RX_DATA
|
||||
#define POLLOUT POLL_EVENT_TX_READY
|
||||
#define POLLPRI POLL_EVENT_OOB
|
||||
#define POLLHUP POLLPRI
|
||||
#define POLLERR POLLPRI
|
||||
#if !defined(WP_PREVENT_WINSOCK_NAME_CONFLICT)
|
||||
/* Old definitions - conflicting with winsock2.h.
|
||||
* Kept for backward compatibility. */
|
||||
# define POLLIN POLL_EVENT_RX_DATA
|
||||
# define POLLOUT POLL_EVENT_TX_READY
|
||||
# define POLLPRI POLL_EVENT_OOB
|
||||
# define POLLHUP POLLPRI
|
||||
# define POLLERR POLLPRI
|
||||
# define POLLWRNORM 0
|
||||
# define POLLRDNORM 0
|
||||
#endif
|
||||
|
||||
#define POLLWRNORM 0
|
||||
#define POLLRDNORM 0
|
||||
/* New definitions. Should be used in all new code. */
|
||||
#define WP_POLLIN POLL_EVENT_RX_DATA
|
||||
#define WP_POLLOUT POLL_EVENT_TX_READY
|
||||
#define WP_POLLPRI POLL_EVENT_OOB
|
||||
#define WP_POLLHUP WP_POLLPRI
|
||||
#define WP_POLLERR WP_POLLPRI
|
||||
#define WP_POLLWRNORM 0
|
||||
#define WP_POLLRDNORM 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
// Command to Set data in Idle Transmit buffer of the driver:
|
||||
|
@ -517,7 +531,7 @@ typedef struct _REGISTER_EVENT
|
|||
u_int8_t operation_status; // operation completion status
|
||||
u_int32_t user_flags_bitmap; // bitmap of events API user is interested to
|
||||
// receive when hEvent is signalled
|
||||
HANDLE hEvent;
|
||||
HANDLE *WP_POINTER_64 hEvent;
|
||||
} REGISTER_EVENT , *PREGISTER_EVENT ;
|
||||
|
||||
#define SIZEOF_REGISTER_EVENT sizeof(REGISTER_EVENT)
|
||||
|
@ -552,17 +566,17 @@ static void print_poll_event_bitmap(u_int32_t bitmap)
|
|||
{
|
||||
char known_event = 0;
|
||||
|
||||
if(bitmap & POLLIN){
|
||||
if(bitmap & WP_POLLIN){
|
||||
known_event = 1;
|
||||
PRINT_BITMAP("POLLIN\n");
|
||||
PRINT_BITMAP("WP_POLLIN\n");
|
||||
}
|
||||
if(bitmap & POLLOUT){
|
||||
if(bitmap & WP_POLLOUT){
|
||||
known_event = 1;
|
||||
PRINT_BITMAP("POLLOUT\n");
|
||||
PRINT_BITMAP("WP_POLLOUT\n");
|
||||
}
|
||||
if(bitmap & POLLPRI){
|
||||
if(bitmap & WP_POLLPRI){
|
||||
known_event = 1;
|
||||
PRINT_BITMAP("POLLPRI\n");
|
||||
PRINT_BITMAP("WP_POLLPRI\n");
|
||||
}
|
||||
if(known_event == 0){
|
||||
PRINT_BITMAP("Unknown event!\n");
|
||||
|
@ -578,7 +592,15 @@ static void print_poll_event_bitmap(u_int32_t bitmap)
|
|||
#define IoctlLoggerApiCommand \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, WANPIPE_IOCTL_LOGGER_CMD, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#endif /* __WINDOWS__ */
|
||||
#else /* __WINDOWS__ */
|
||||
# define WP_POLLIN POLLIN
|
||||
# define WP_POLLOUT POLLOUT
|
||||
# define WP_POLLPRI POLLPRI
|
||||
# define WP_POLLHUP POLLHUP
|
||||
# define WP_POLLERR POLLERR
|
||||
# define WP_POLLWRNORM POLLWRNORM
|
||||
# define WP_POLLRDNORM POLLRDNORM
|
||||
#endif
|
||||
|
||||
/*
|
||||
#define MEM_TEST_BUFFER_LEN 100
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*******************************************************************************
|
||||
* ** sdla_b800_remora.h
|
||||
* **
|
||||
* ** Author: David Yat Sin <dyatsin@sangoma.com>
|
||||
* **
|
||||
* ** Copyright: (c) 2005 Sangoma Technologies Inc.
|
||||
* **
|
||||
* ** This program is free software; you can redistribute it and/or
|
||||
* ** modify it under the terms of the GNU General Public License
|
||||
* ** as published by the Free Software Foundation; either version
|
||||
* ** 2 of the License, or (at your option) any later version.
|
||||
* ** ============================================================================
|
||||
* ** Nov , 2008 David Yat Sin Initial version
|
||||
* *******************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef __SDLA_B800_REMORA_H
|
||||
#define __SDLA_B800_REMORA_H
|
||||
|
||||
|
||||
#define AFT_B800_BASE_REG_OFF 0x0000
|
||||
#define B800_REG_OFF(reg) reg+AFT_B800_BASE_REG_OFF
|
||||
|
||||
#define B800_SPI_REG_RESET_BIT 28
|
||||
#define B800_SPI_REG_READ_ENABLE_BIT 29 /* 1 for read, 0 for write */
|
||||
#define B800_SPI_REG_CHAN_TYPE_FXS_BIT 30 /* 0 for FXO, 1 for FXS */
|
||||
#define B800_SPI_REG_SPI_BUSY_BIT 31 /* 1 busy, 0 ready */
|
||||
#define B800_SPI_REG_START_BIT 31
|
||||
|
||||
#define NUM_B800_ANALOG_PORTS 16
|
||||
|
||||
#define IS_B800(fe) (((sdla_t*)(fe->card))->adptr_type == AFT_ADPTR_B800)
|
||||
#define IS_B800_CARD(card) (card->adptr_type == AFT_ADPTR_B800)
|
||||
|
||||
#endif /* __SDLA_B800_REMORA_H */
|
|
@ -219,7 +219,7 @@ typedef struct {
|
|||
unsigned char tx_tristate_mode;
|
||||
unsigned int tdmv_law;
|
||||
unsigned char poll_mode;
|
||||
int network_sync;
|
||||
int network_sync;
|
||||
|
||||
union {
|
||||
sdla_te_cfg_t te_cfg;
|
||||
|
@ -236,6 +236,8 @@ typedef struct {
|
|||
/*sdla_te_pmon_t te_pmon;*/
|
||||
sdla_te3_pmon_t te3_pmon;
|
||||
} u;
|
||||
u_int32_t tx_alarms;
|
||||
u_int32_t tx_maint_alarms;
|
||||
#define te_pmon u.te1_stats.pmon
|
||||
} sdla_fe_stats_t;
|
||||
|
||||
|
@ -559,7 +561,7 @@ typedef struct {
|
|||
/* Set extra T1/E1 configuration */
|
||||
int (*reconfig)(sdla_fe_t*);
|
||||
int (*unconfig)(void *fe);
|
||||
int (*pre_release)(void*);
|
||||
int (*post_unconfig)(void*);
|
||||
int (*if_config)(void *fe, u32, u8);
|
||||
int (*if_unconfig)(void *fe, u32, u8);
|
||||
int (*disable_irq)(void *fe);
|
||||
|
@ -568,6 +570,7 @@ typedef struct {
|
|||
int (*isr)(sdla_fe_t *fe);
|
||||
int (*process_udp)(sdla_fe_t *fe, void*, unsigned char*);
|
||||
u_int32_t (*read_alarm)(sdla_fe_t *fe, int);
|
||||
|
||||
int (*read_pmon)(sdla_fe_t *fe, int);
|
||||
int (*flush_pmon)(sdla_fe_t *fe);
|
||||
/* Set Front-End alarm (T1/E1) */
|
||||
|
@ -626,6 +629,7 @@ typedef struct {
|
|||
int (*isdn_bri_dchan_rx)(sdla_fe_t*, void*, unsigned int);
|
||||
/* Enable/Disable Clock recovery from the line */
|
||||
int (*clock_ctrl)(sdla_fe_t*, u_int8_t /* WANOPT_NO/WANOPT_YES */);
|
||||
u_int32_t (*read_tx_alarm)(sdla_fe_t *fe, int);
|
||||
} sdla_fe_iface_t;
|
||||
|
||||
/*
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
# include "aft_core_options.h"
|
||||
# include "sdla_a600_remora.h"
|
||||
# include "sdla_b800_remora.h"
|
||||
# include "sdla_remora_proslic.h"
|
||||
# include "wanpipe_events.h"
|
||||
|
||||
|
|
|
@ -278,6 +278,7 @@
|
|||
#define TE_CONFIGURED 0x06
|
||||
#define TE_TIMER_EVENT_PENDING 0x07
|
||||
#define TE_TIMER_EVENT_INPROGRESS 0x08
|
||||
#define TE_AIS_TX_STARTUP 0x09
|
||||
|
||||
/* TE1 sw irq types */
|
||||
enum {
|
||||
|
@ -453,6 +454,7 @@ typedef struct sdla_te_cfg {
|
|||
u_int8_t te_ref_clock;
|
||||
u_int8_t sig_mode;
|
||||
u_int8_t ignore_yel_alarm;
|
||||
u_int8_t ais_maintenance;
|
||||
} sdla_te_cfg_t;
|
||||
|
||||
/* Performamce monitor counters */
|
||||
|
@ -784,6 +786,9 @@ typedef struct {
|
|||
wan_ticks_t bert_start;
|
||||
sdla_te_bert_cfg_t bert_cfg;
|
||||
sdla_te_bert_stats_t bert_stats;
|
||||
|
||||
uint8_t tx_ais_alarm;
|
||||
wan_ticks_t tx_ais_startup_timeout;
|
||||
|
||||
} sdla_te_param_t;
|
||||
|
||||
|
|
|
@ -168,6 +168,7 @@ enum {
|
|||
#define SDLA_MAGIC_RC(hw,rc) WAN_ASSERT_RC((hw)->magic != SDLADRV_MAGIC, (rc))
|
||||
#define SDLA_MAGIC_VOID(hw) WAN_ASSERT_VOID((hw)->magic != SDLADRV_MAGIC)
|
||||
|
||||
#define WAN_BUS_ID_SIZE 20
|
||||
|
||||
/*
|
||||
******************************************************************
|
||||
|
@ -385,6 +386,7 @@ typedef struct sdlahw_pci_
|
|||
#define SDLA_USB_OPMODE_VOICE 0x01
|
||||
#define SDLA_USB_OPMODE_API 0x02
|
||||
|
||||
#define SDLA_URB_STATUS_READY 1
|
||||
struct wan_urb {
|
||||
void *pvt;
|
||||
int id;
|
||||
|
@ -428,22 +430,26 @@ typedef struct {
|
|||
int tx_overrun_cnt;
|
||||
int tx_notready_cnt;
|
||||
|
||||
unsigned char fifo_status;
|
||||
unsigned char uart_status;
|
||||
unsigned char hostif_status;
|
||||
unsigned char dev_fifo_status;
|
||||
unsigned char dev_uart_status;
|
||||
unsigned char dev_hostif_status;
|
||||
int dev_sync_err_cnt;
|
||||
|
||||
} sdla_usb_comm_err_stats_t;
|
||||
|
||||
|
||||
typedef struct sdlahw_usb_
|
||||
{
|
||||
int opmode; /* Voice or API Data protocol */
|
||||
unsigned char hw_rev; /* hardware (pcb) revision */
|
||||
|
||||
# if defined(__LINUX__)
|
||||
char bus_id[WAN_BUS_ID_SIZE];
|
||||
struct usb_device *usb_dev;
|
||||
struct usb_interface *usb_intf;
|
||||
# endif
|
||||
|
||||
|
||||
unsigned char reg_cpu_ctrl; /* Reg 0x03 */
|
||||
int urbcount_read;
|
||||
int urb_read_ind;
|
||||
struct wan_urb dataread[MAX_READ_URB_COUNT];
|
||||
|
@ -458,6 +464,7 @@ typedef struct sdlahw_usb_
|
|||
|
||||
wan_spinlock_t cmd_lock;
|
||||
wan_spinlock_t lock;
|
||||
wan_spinlock_t tx_lock;
|
||||
|
||||
int rxtx_len; /* number of data bytes in record */
|
||||
int rxtx_count; /* number records in single transcation */
|
||||
|
@ -468,13 +475,14 @@ typedef struct sdlahw_usb_
|
|||
int write_buf_len; /* size of write cycle buffer */
|
||||
|
||||
int rx_sync;
|
||||
int tx_sync;
|
||||
int next_rx_ind;
|
||||
int next_read_ind;
|
||||
char readbuf[MAX_READ_BUF_LEN+MAX_USB_RX_LEN+10]; // 10 for safety
|
||||
char *readbuf;
|
||||
|
||||
int next_tx_ind;
|
||||
int next_write_ind;
|
||||
char writebuf[MAX_WRITE_BUF_LEN+MAX_USB_TX_LEN+10]; // 10 for safety
|
||||
char *writebuf;
|
||||
|
||||
char idlebuf[MAX_USB_TX_LEN+1];
|
||||
|
||||
|
@ -484,6 +492,8 @@ typedef struct sdlahw_usb_
|
|||
|
||||
unsigned int status;
|
||||
|
||||
wan_ticks_t tx_cmd_start;
|
||||
|
||||
wan_skb_queue_t tx_cmd_list;
|
||||
wan_skb_queue_t tx_cmd_free_list;
|
||||
wan_skb_queue_t rx_cmd_list;
|
||||
|
@ -504,6 +514,7 @@ typedef struct sdlahw_usb_
|
|||
/* This structure keeps common parameters per physical card */
|
||||
typedef struct sdlahw_card {
|
||||
int internal_used;
|
||||
unsigned char name[SDLA_NAME_SIZE]; /* Card name */
|
||||
unsigned int hw_type; /* ISA/PCI */
|
||||
unsigned int type; /* S50x/S514/ADSL/SDLA_AFT */
|
||||
unsigned char cfg_type; /* Config card type WANOPT_XXX */
|
||||
|
@ -712,21 +723,23 @@ typedef struct sdlahw_iface
|
|||
char* (*hwec_name)(void *phw);
|
||||
int (*get_hwec_index)(void *phw);
|
||||
|
||||
/* usb function interface (FIXME) */
|
||||
/* usb function interface (FIXME) */
|
||||
int (*usb_cpu_read)(void *phw, unsigned char off, unsigned char *data);
|
||||
int (*usb_cpu_write)(void *phw, unsigned char off, unsigned char data);
|
||||
int (*usb_write_poll)(void *phw, unsigned char off, unsigned char data);
|
||||
int (*usb_read_poll)(void *phw, unsigned char off, unsigned char *data);
|
||||
int (*usb_hwec_enable)(void *phw, int, int);
|
||||
int (*usb_rxevent_enable)(void *phw, int, int);
|
||||
int (*usb_rxevent)(void *phw, int, u8*, int);
|
||||
int (*usb_rxtx_data_init)(void *phw, int, unsigned char**, unsigned char**);
|
||||
int (*usb_rxdata_enable)(void *phw, int enable);
|
||||
int (*usb_rxdata)(void *phw, unsigned char*, int);
|
||||
int (*usb_txdata)(void *phw, unsigned char*, int);
|
||||
int (*usb_txdata_ready)(void *phw);
|
||||
int (*usb_fwupdate_enable)(void *phw);
|
||||
int (*usb_txdata_raw)(void *phw, unsigned char*, int);
|
||||
int (*usb_txdata_raw_ready)(void *phw);
|
||||
int (*usb_rxdata_raw)(void *phw, unsigned char*, int);
|
||||
int (*usb_err_stats)(void *phw, void*, int);
|
||||
int (*usb_flush_err_stats)(void *phw);
|
||||
void (*reset_fe)(void*);
|
||||
void (*reset_fe)(void*);
|
||||
|
||||
} sdlahw_iface_t;
|
||||
|
||||
|
@ -746,13 +759,14 @@ typedef struct sdla_hw_type_cnt
|
|||
unsigned char aft_a600_adapters;
|
||||
unsigned char aft_b601_adapters;
|
||||
unsigned char aft_a700_adapters;
|
||||
unsigned char aft_b800_adapters;
|
||||
|
||||
unsigned char aft_x_adapters;
|
||||
unsigned char usb_adapters;
|
||||
}sdla_hw_type_cnt_t;
|
||||
|
||||
typedef struct sdladrv_callback_ {
|
||||
int (*add_device)(char*, void*);
|
||||
int (*add_device)(void);
|
||||
int (*delete_device)(char*);
|
||||
} sdladrv_callback_t;
|
||||
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
/**
|
||||
* \file sdladrv_usb.h
|
||||
* \brief SDLADRV USB Interface
|
||||
*
|
||||
* Authors: Alex Feldman <alex@sangoma.com>
|
||||
*
|
||||
* Copyright (c) 2008-09, Sangoma Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* * Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Sangoma Technologies nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Sangoma Technologies ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Sangoma Technologies BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* ===============================================================================
|
||||
*/
|
||||
|
||||
#if !defined(__SDLADRV_USB_H)
|
||||
# define __SDLADRV_USB_H
|
||||
|
||||
/* Internal USB-FXO CPU registers */
|
||||
#define SDLA_USB_CPU_REG_DEVICEID 0x00
|
||||
#define SDLA_USB_DEVICEID 0x55
|
||||
|
||||
#define SDLA_USB_CPU_REG_HARDWAREVER 0x01
|
||||
|
||||
#define SDLA_USB_CPU_REG_FIRMWAREVER 0x02
|
||||
|
||||
#define SDLA_USB_CPU_REG_CTRL 0x03
|
||||
#define SDLA_USB_CPU_BIT_CTRL_RESET 0x80
|
||||
#define SDLA_USB_CPU_BIT_CTRL_FWUPDATE 0x40
|
||||
#define SDLA_USB_CPU_BIT_CTRL_TS1_HWEC_EN 0x08
|
||||
#define SDLA_USB_CPU_BIT_CTRL_TS0_HWEC_EN 0x04
|
||||
#define SDLA_USB_CPU_BIT_CTRL_TS1_EVENT_EN 0x02
|
||||
#define SDLA_USB_CPU_BIT_CTRL_TS0_EVENT_EN 0x01
|
||||
|
||||
#define SDLA_USB_CPU_REG_FIFO_STATUS 0x04
|
||||
#define SDLA_USB_CPU_BIT_FIFO_STATUS_TS1_TX_UF 0x80
|
||||
#define SDLA_USB_CPU_BIT_FIFO_STATUS_TS1_TX_OF 0x40
|
||||
#define SDLA_USB_CPU_BIT_FIFO_STATUS_TS0_TX_UF 0x20
|
||||
#define SDLA_USB_CPU_BIT_FIFO_STATUS_TS0_TX_OF 0x10
|
||||
#define SDLA_USB_CPU_BIT_FIFO_STATUS_TS1_RX_UF 0x08
|
||||
#define SDLA_USB_CPU_BIT_FIFO_STATUS_TS1_RX_OF 0x04
|
||||
#define SDLA_USB_CPU_BIT_FIFO_STATUS_TS0_RX_UF 0x02
|
||||
#define SDLA_USB_CPU_BIT_FIFO_STATUS_TS0_RX_OF 0x01
|
||||
|
||||
#define SDLA_USB_CPU_REG_UART_STATUS 0x05
|
||||
#define SDLA_USB_CPU_BIT_UART_STATUS_LOST_SYNC 0x10
|
||||
#define SDLA_USB_CPU_BIT_UART_STATUS_CMD_UNKNOWN 0x10
|
||||
#define SDLA_USB_CPU_BIT_UART_STATUS_RX_UF 0x08
|
||||
#define SDLA_USB_CPU_BIT_UART_STATUS_RX_OF 0x04
|
||||
#define SDLA_USB_CPU_BIT_UART_STATUS_TX_UF 0x02
|
||||
#define SDLA_USB_CPU_BIT_UART_STATUS_TX_OF 0x01
|
||||
|
||||
#define SDLA_USB_CPU_REG_HOSTIF_STATUS 0x06
|
||||
#define SDLA_USB_CPU_BIT_HOSTIF_STATUS_RX_UF 0x08
|
||||
#define SDLA_USB_CPU_BIT_HOSTIF_STATUS_RX_OF 0x04
|
||||
#define SDLA_USB_CPU_BIT_HOSTIF_STATUS_TX_UF 0x02
|
||||
#define SDLA_USB_CPU_BIT_HOSTIF_STATUS_TX_OF 0x01
|
||||
|
||||
#define SDLA_USB_CPU_REG_LED_CONTROL 0x07
|
||||
#define SDLA_USB_CPU_BIT_LED_CONTROL_TS1_GRN 0x08
|
||||
#define SDLA_USB_CPU_BIT_LED_CONTROL_TS1_RED 0x04
|
||||
#define SDLA_USB_CPU_BIT_LED_CONTROL_TS0_GRN 0x02
|
||||
#define SDLA_USB_CPU_BIT_LED_CONTROL_TS0_RED 0x01
|
||||
|
||||
#define SDLA_USB_CPU_REG_DEBUG 0x08
|
||||
#define SDLA_USB_CPU_BIT_DEBUG_WEN_ACK 0x08
|
||||
#define SDLA_USB_CPU_BIT_DEBUG_DTMF 0x04
|
||||
#define SDLA_USB_CPU_BIT_DEBUG_LOCAL_LB 0x02
|
||||
#define SDLA_USB_CPU_BIT_DEBUG_LINE_LB 0x01
|
||||
|
||||
#define SDLA_USB_CPU_REG_EC_NUM 0x09
|
||||
|
||||
#define SDLA_USB_CPU_REG_FWUPDATE_MAGIC 0x0A
|
||||
#define SDLA_USB_CPU_BITS_FWUPDATE_MAGIC 0x5A
|
||||
|
||||
|
||||
#if defined(WAN_KERNEL)
|
||||
|
||||
# include "sdladrv.h"
|
||||
|
||||
extern int sdla_usb_init(void);
|
||||
extern int sdla_usb_exit(void);
|
||||
extern int sdla_usb_setup(sdlahw_card_t*, int);
|
||||
extern int sdla_usb_down(sdlahw_card_t*, int force);
|
||||
|
||||
/*usb interface */
|
||||
extern int sdla_usb_cpu_read(void *phw, unsigned char off, unsigned char *data);
|
||||
extern int sdla_usb_cpu_write(void *phw, unsigned char off, unsigned char data);
|
||||
extern int sdla_usb_write_poll(void *phw, unsigned char off, unsigned char data);
|
||||
extern int sdla_usb_read_poll(void *phw, unsigned char off, unsigned char *data);
|
||||
extern int sdla_usb_hwec_enable(void *phw, int mod_no, int enable);
|
||||
extern int sdla_usb_rxevent_enable(void *phw, int mod_no, int enable);
|
||||
extern int sdla_usb_rxevent(void *phw, int mod_no, u8 *regs, int);
|
||||
extern int sdla_usb_rxtx_data_init(void *phw, int, unsigned char **, unsigned char **);
|
||||
extern int sdla_usb_rxdata_enable(void *phw, int enable);
|
||||
extern int sdla_usb_fwupdate_enable(void *phw);
|
||||
extern int sdla_usb_txdata_raw(void *phw, unsigned char*, int);
|
||||
extern int sdla_usb_txdata_raw_ready(void *phw);
|
||||
extern int sdla_usb_rxdata_raw(void *phw, unsigned char*, int);
|
||||
extern int sdla_usb_set_intrhand(void*, wan_pci_ifunc_t*, void*, int);
|
||||
extern int sdla_usb_restore_intrhand(void*, int);
|
||||
extern int sdla_usb_err_stats(void*,void*,int);
|
||||
extern int sdla_usb_flush_err_stats(void*);
|
||||
|
||||
#endif /* WAN_KERNEL */
|
||||
|
||||
#endif /* __SDLADRV_USB_H */
|
|
@ -88,6 +88,9 @@
|
|||
#define AFT_A600_SUBSYS_VENDOR 0xA600 /* AFT-600 Series board */
|
||||
#define AFT_B601_SUBSYS_VENDOR 0xA601 /* AFT-600 Series board */
|
||||
|
||||
/* DAVIDY change to B800 ID when B800 ID is ready */
|
||||
#define AFT_B800_SUBSYS_VENDOR 0xB800 /* AFT-800 Series board */
|
||||
|
||||
#define AFT_2SERIAL_V35X21_SUBSYS_VENDOR 0xA031 /* AFT-A142 2 Port V.35/X.21 board */
|
||||
#define AFT_4SERIAL_V35X21_SUBSYS_VENDOR 0xA032 /* AFT-A144 4 Port V.35/X.21 board */
|
||||
#define AFT_2SERIAL_RS232_SUBSYS_VENDOR 0xA033 /* AFT-A142 2 Port RS232 board */
|
||||
|
|
|
@ -146,6 +146,7 @@ enum {
|
|||
U100_ADPTR, /* USB board */
|
||||
AFT_ADPTR_A600, /* AFT-A600 board */
|
||||
AFT_ADPTR_B601, /* AFT-B601 board */
|
||||
AFT_ADPTR_B800, /* AFT-B800 board */
|
||||
AFT_ADPTR_FLEXBRI, /* AFT-A700 FlexBRI board */
|
||||
|
||||
AFT_ADPTR_LAST /* NOTE: Keep it as a last line */
|
||||
|
@ -304,6 +305,7 @@ enum {
|
|||
(adapter_type == U100_ADPTR) ? "U100" : \
|
||||
(adapter_type == AFT_ADPTR_A600) ? "AFT-B600" : \
|
||||
(adapter_type == AFT_ADPTR_B601) ? "AFT-B601" : \
|
||||
(adapter_type == AFT_ADPTR_B800) ? "AFT-B800" : \
|
||||
(adapter_type == AFT_ADPTR_FLEXBRI) ? "AFT-B700" : \
|
||||
"UNKNOWN"
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue