wanpipe-3.5.12.tgz

This commit is contained in:
Harald Welte 2021-12-29 18:42:17 +01:00
parent fbb8feccef
commit c6acb46c69
241 changed files with 16177 additions and 5684 deletions

0
.openzap Normal file
View File

View File

@ -1 +1 @@
wanpipe-3.5.11
wanpipe-3.5.12

View File

@ -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
===================================================================

View File

@ -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)

9
OSLEC/echo/Kconfig Normal file
View File

@ -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.

1
OSLEC/echo/Makefile Normal file
View File

@ -0,0 +1 @@
obj-$(CONFIG_ECHO) += echo.o

10
OSLEC/echo/TODO Normal file
View File

@ -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>

228
OSLEC/echo/bit_operations.h Normal file
View File

@ -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 ------------------------------------------------------------*/

638
OSLEC/echo/echo.c Normal file
View 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");

172
OSLEC/echo/echo.h Normal file
View File

@ -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 */

295
OSLEC/echo/fir.h Normal file
View File

@ -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 ------------------------------------------------------------*/

281
OSLEC/echo/mmx.h Normal file
View 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 */

86
OSLEC/echo/oslec.h Normal file
View File

@ -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
View File

@ -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.
@ -4797,6 +4799,10 @@ function install_ssmg_ss7()
return 0
fi
if [ $NO_SMG_INSTALL -eq 1 ]; then
return 0
fi
banner
check_sctp_utility
@ -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;

View File

@ -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.

1
api/legacy/file Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;
@ -2343,6 +2337,28 @@ int _LIBSNG_CALL sangoma_tdm_read_rbs(sng_fd_t fd, wanpipe_api_t *tdm_api, int c
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
@ -2440,6 +2458,9 @@ int _LIBSNG_CALL sangoma_read_event(sng_fd_t fd, wanpipe_api_t *tdm_api)
break;
}
#endif
return 0;
#else
printf("Error: Read Event not supported!\n");
@ -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);

View File

@ -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 */

View File

@ -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"

View File

@ -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" );
if (number_of_custom_params >= 1 && number_of_custom_params <= 4) {
config.conf.param_no = 1;
config.conf.params = &custom_parms;
#endif
wan_custom_param_t *custom_parms_ptr;
unsigned int i, custom_params_memory_size;
/* Load firmware on EC chip */
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,13 +223,9 @@ 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;

View File

@ -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);\

View File

@ -1,7 +1,7 @@
8
dir
273
293
https://www.sangomapbx.com/svn/libsangoma/trunk/docs
https://www.sangomapbx.com/svn/libsangoma

View File

@ -1,7 +1,7 @@
8
dir
273
293
https://www.sangomapbx.com/svn/libsangoma/trunk/docs/doxygen
https://www.sangomapbx.com/svn/libsangoma

View File

@ -1,7 +1,7 @@
8
dir
273
293
https://www.sangomapbx.com/svn/libsangoma/trunk/examples
https://www.sangomapbx.com/svn/libsangoma

View File

@ -1,7 +1,7 @@
8
dir
273
293
https://www.sangomapbx.com/svn/libsangoma/trunk/examples/hptdm_api
https://www.sangomapbx.com/svn/libsangoma

View File

@ -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

View File

@ -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

View File

@ -1,7 +1,7 @@
8
dir
273
293
https://www.sangomapbx.com/svn/libsangoma/trunk/examples/priserver
https://www.sangomapbx.com/svn/libsangoma

View File

@ -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;

View File

@ -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;
@ -2343,6 +2337,28 @@ int _LIBSNG_CALL sangoma_tdm_read_rbs(sng_fd_t fd, wanpipe_api_t *tdm_api, int c
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
@ -2440,6 +2458,9 @@ int _LIBSNG_CALL sangoma_read_event(sng_fd_t fd, wanpipe_api_t *tdm_api)
break;
}
#endif
return 0;
#else
printf("Error: Read Event not supported!\n");
@ -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);

View File

@ -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 */

View File

@ -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"

View File

@ -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" );
if (number_of_custom_params >= 1 && number_of_custom_params <= 4) {
config.conf.param_no = 1;
config.conf.params = &custom_parms;
#endif
wan_custom_param_t *custom_parms_ptr;
unsigned int i, custom_params_memory_size;
/* Load firmware on EC chip */
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,13 +223,9 @@ 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;

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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];

View File

@ -77,13 +77,14 @@ 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 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__
@ -103,12 +104,16 @@ void TerminateHandler(int);
\param datalen size of data buffer
\return void
*/
void print_rxdata(unsigned char *data, int datalen); /* dont remove prototype, gcc complains */
void print_rxdata(unsigned char *data, int datalen)
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;
printf("Data: (Len=%i)\n",datalen);
#ifdef WP_API_FEATURE_RX_TX_ERRS
err=hdr->wp_api_rx_hdr_errors;
#endif
printf("Data: (Len=%i,Errs=%i)\n",datalen,err);
for(i = 0; i < datalen; i++) {
if((i % 20 == 0)){
if(i){
@ -127,6 +132,94 @@ void print_rxdata(unsigned char *data, int datalen)
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
@ -161,8 +254,36 @@ int read_data(uint32_t dev_index, wp_api_hdr_t *rx_hdr, void *rx_buffer, int rx_
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
Rx_count++;
if (verbose){
print_rxdata(rx_buffer, Rx_lgth);
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: */
@ -192,27 +313,33 @@ int read_data(uint32_t dev_index, wp_api_hdr_t *rx_hdr, void *rx_buffer, int rx_
}
/*!
\fn int write_data(uint32_t dev_index, wp_api_hdr_t *tx_hdr, void *tx_data)
\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 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_hdr->data_length, /* DATA size */
tx_len, /* DATA size */
0);
if (err <= 0){
@ -224,21 +351,22 @@ int write_data(uint32_t dev_index, wp_api_hdr_t *tx_hdr, void *tx_buffer)
Tx_count++;
if (verbose){
printf("Packet sent: counter: %i, len: %i\n", Tx_count, err);
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 0
if(Tx_count >= tx_cnt){
#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);
//sangoma_wait_objects[dev_index].flags_in &= (~POLLOUT);
return 1;
}
#endif
return 0;
@ -255,6 +383,7 @@ int write_data(uint32_t dev_index, wp_api_hdr_t *tx_hdr, void *tx_buffer)
int handle_data(uint32_t dev_index, int flags_out)
{
wp_api_hdr_t rxhdr;
int err=0;
memset(&rxhdr, 0, sizeof(rxhdr));
@ -267,7 +396,7 @@ int handle_data(uint32_t dev_index, int flags_out)
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);
return write_data(dev_index, &rxhdr, rxdata,rxhdr.data_length);
}
}
}
@ -283,11 +412,12 @@ int handle_data(uint32_t dev_index, int flags_out)
/* set data which will be transmitted */
memset(txdata, tx_test_byte, txhdr.data_length);
if(write_data(dev_index, &txhdr, txdata) == 0){
err = write_data(dev_index, &txhdr, txdata, tx_size);
if (err== 0) {
tx_test_byte++;
}
}
return 0;
return err;
}
/*!
@ -422,11 +552,15 @@ void handle_span_chan(int open_device_counter)
input_flags,
output_flags,
open_device_counter /* number of wait objects */,
2000 /* wait timeout, in milliseconds */);
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;
@ -438,6 +572,8 @@ void handle_span_chan(int open_device_counter)
/* got tdm api event */
if(handle_tdm_event(i)){
printf("Error in handle_tdm_event()!\n");
application_termination_flag=1;
break;
}
}
@ -445,6 +581,8 @@ void handle_span_chan(int open_device_counter)
/* 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() */
@ -670,6 +808,13 @@ int open_sangoma_device()
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),
@ -682,6 +827,11 @@ int open_sangoma_device()
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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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"

View File

@ -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];

View File

@ -77,13 +77,14 @@ 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 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__
@ -103,12 +104,16 @@ void TerminateHandler(int);
\param datalen size of data buffer
\return void
*/
void print_rxdata(unsigned char *data, int datalen); /* dont remove prototype, gcc complains */
void print_rxdata(unsigned char *data, int datalen)
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;
printf("Data: (Len=%i)\n",datalen);
#ifdef WP_API_FEATURE_RX_TX_ERRS
err=hdr->wp_api_rx_hdr_errors;
#endif
printf("Data: (Len=%i,Errs=%i)\n",datalen,err);
for(i = 0; i < datalen; i++) {
if((i % 20 == 0)){
if(i){
@ -127,6 +132,94 @@ void print_rxdata(unsigned char *data, int datalen)
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
@ -161,8 +254,36 @@ int read_data(uint32_t dev_index, wp_api_hdr_t *rx_hdr, void *rx_buffer, int rx_
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
Rx_count++;
if (verbose){
print_rxdata(rx_buffer, Rx_lgth);
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: */
@ -192,27 +313,33 @@ int read_data(uint32_t dev_index, wp_api_hdr_t *rx_hdr, void *rx_buffer, int rx_
}
/*!
\fn int write_data(uint32_t dev_index, wp_api_hdr_t *tx_hdr, void *tx_data)
\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 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_hdr->data_length, /* DATA size */
tx_len, /* DATA size */
0);
if (err <= 0){
@ -224,21 +351,22 @@ int write_data(uint32_t dev_index, wp_api_hdr_t *tx_hdr, void *tx_buffer)
Tx_count++;
if (verbose){
printf("Packet sent: counter: %i, len: %i\n", Tx_count, err);
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 0
if(Tx_count >= tx_cnt){
#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);
//sangoma_wait_objects[dev_index].flags_in &= (~POLLOUT);
return 1;
}
#endif
return 0;
@ -255,6 +383,7 @@ int write_data(uint32_t dev_index, wp_api_hdr_t *tx_hdr, void *tx_buffer)
int handle_data(uint32_t dev_index, int flags_out)
{
wp_api_hdr_t rxhdr;
int err=0;
memset(&rxhdr, 0, sizeof(rxhdr));
@ -267,7 +396,7 @@ int handle_data(uint32_t dev_index, int flags_out)
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);
return write_data(dev_index, &rxhdr, rxdata,rxhdr.data_length);
}
}
}
@ -283,11 +412,12 @@ int handle_data(uint32_t dev_index, int flags_out)
/* set data which will be transmitted */
memset(txdata, tx_test_byte, txhdr.data_length);
if(write_data(dev_index, &txhdr, txdata) == 0){
err = write_data(dev_index, &txhdr, txdata, tx_size);
if (err== 0) {
tx_test_byte++;
}
}
return 0;
return err;
}
/*!
@ -422,11 +552,15 @@ void handle_span_chan(int open_device_counter)
input_flags,
output_flags,
open_device_counter /* number of wait objects */,
2000 /* wait timeout, in milliseconds */);
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;
@ -438,6 +572,8 @@ void handle_span_chan(int open_device_counter)
/* got tdm api event */
if(handle_tdm_event(i)){
printf("Error in handle_tdm_event()!\n");
application_termination_flag=1;
break;
}
}
@ -445,6 +581,8 @@ void handle_span_chan(int open_device_counter)
/* 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() */
@ -670,6 +808,13 @@ int open_sangoma_device()
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),
@ -682,6 +827,11 @@ int open_sangoma_device()
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;
}

View File

@ -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

View File

@ -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

View File

@ -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(&param->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 = &param->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");
}

View File

@ -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,6 +84,30 @@ static void DecodeLastError(LPSTR lpszFunction)
printf("Last Error: %s (GetLastError() returned: %d)\n", (char*)lpMsgBuf, dwLastErr);
// Free the buffer.
LocalFree( lpMsgBuf );
}
#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
}
@ -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. */

View File

@ -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;
@ -590,6 +584,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) {
ERR_IFACE("sangoma_get_stats(() failed (err: %d (0x%X))!\n", err, 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];
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] = (POLLIN | POLLPRI);
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,7 +1739,7 @@ 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);
}
@ -1653,11 +1747,13 @@ 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;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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 \

View File

@ -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(&param->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 = &param->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");
}

View File

@ -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,6 +84,30 @@ static void DecodeLastError(LPSTR lpszFunction)
printf("Last Error: %s (GetLastError() returned: %d)\n", (char*)lpMsgBuf, dwLastErr);
// Free the buffer.
LocalFree( lpMsgBuf );
}
#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
}
@ -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. */

View File

@ -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;
@ -590,6 +584,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) {
ERR_IFACE("sangoma_get_stats(() failed (err: %d (0x%X))!\n", err, 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];
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] = (POLLIN | POLLPRI);
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,7 +1739,7 @@ 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);
}
@ -1653,11 +1747,13 @@ 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;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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 \

View File

@ -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);\

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -1,7 +1,7 @@
8
dir
59
60
http://www.sangomapbx.com/svn/stelephony/trunk/stel_tone
http://www.sangomapbx.com/svn/stelephony

View File

@ -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);
}
}

View File

@ -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

View File

@ -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

224
api/xmtp2api-v1.6/README Normal file
View File

@ -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

View File

@ -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);
}

View File

@ -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

634
api/xmtp2api-v1.6/mtp2api.c Normal file
View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

48
api/xmtp2api-v1.6/xmtp2km_in Executable file
View File

@ -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

View File

@ -1,5 +1,5 @@
Package: wanpipe
Version: 3.5.11-0
Version: 3.5.12-0
Section: networking
Priority: optional
Architecture: all

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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;
/*

View File

@ -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"

View File

@ -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 */
@ -785,6 +787,9 @@ typedef struct {
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;

View File

@ -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,18 +723,20 @@ 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*);
@ -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;

View File

@ -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 */

View File

@ -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 */

View File

@ -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