diff --git a/.openzap b/.openzap new file mode 100644 index 0000000..e69de29 diff --git a/.router_version b/.router_version index 38cd4f5..bb72f1c 100644 --- a/.router_version +++ b/.router_version @@ -1 +1 @@ -wanpipe-3.5.11 +wanpipe-3.5.12 diff --git a/ChangeLog.3.5 b/ChangeLog.3.5 index 078d7ad..451991e 100644 --- a/ChangeLog.3.5 +++ b/ChangeLog.3.5 @@ -3,11 +3,47 @@ WANPIPE TDM VOICE - IP/WAN Package ------------------------------------------------------------------------------ Author: Nenad Corbic -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 - 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 - 3.5.11 =================================================================== diff --git a/Makefile b/Makefile index 3eecffc..9b43d0f 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,7 @@ PWD=$(shell pwd) KBUILD_VERBOSE=0 +CC=gcc EXTRA_CFLAGS= EXTRA_FLAGS= @@ -99,7 +100,15 @@ EXTRA_UTIL_FLAGS += -I$(PWD)/patches/kdrivers/wanec -I$(PWD)/patches/kdrivers/wa ENABLE_WANPIPEMON_ZAP=NO ZAPHDLC_PRIV=/etc/wanpipe/.zaphdlc -EXTRA_CFLAGS += $(EXTRA_FLAGS) +PRODUCT_DEFINES= -DCONFIG_PRODUCT_WANPIPE_BASE -DCONFIG_PRODUCT_WANPIPE_AFT -DCONFIG_PRODUCT_WANPIPE_AFT_CORE +PRODUCT_DEFINES+= -DCONFIG_PRODUCT_WANPIPE_AFT_TE1 -DCONFIG_PRODUCT_WANPIPE_AFT_TE3 -DCONFIG_PRODUCT_WANPIPE_AFT_56K +PRODUCT_DEFINES+= -DCONFIG_WANPIPE_HWEC -DCONFIG_PRODUCT_WANPIPE_SOCK_DATASCOPE -DCONFIG_PRODUCT_WANPIPE_AFT_BRI -DCONFIG_PRODUCT_WANPIPE_AFT_SERIAL +PRODUCT_DEFINES+= -DCONFIG_PRODUCT_WANPIPE_TDM_VOICE_DCHAN -DCONFIG_PRODUCT_WANPIPE_CODEC_SLINEAR_LAW -DCONFIG_PRODUCT_WANPIPE_AFT_RM +PRODUCT_DEFINES+= -DCONFIG_PRODUCT_WANPIPE_USB -DCONFIG_PRODUCT_WANPIPE_A700 -DCONFIG_PRODUCT_A600 -DCONFIG_PRODUCT_WANPIPE_AFT_A600 -DCONFIG_PRODUCT_WANPIPE_AFT_A700 +PRODUCT_DEFINES+= -DCONFIG_PRODUCT_WANPIPE_AFT_B601 -DCONFIG_PRODUCT_WANPIPE_AFT_B800 + +EXTRA_CFLAGS += $(EXTRA_FLAGS) $(PRODUCT_DEFINES) +EXTRA_UTIL_FLAGS += $(PRODUCT_DEFINES) #Check if zaptel exists @@ -170,6 +179,9 @@ openzap: all_src all_lib freetdm: all_src all_lib @touch .all_lib .openzap +g3ti: all_src all_lib + @touch .all_lib .openzap + openzap_ss7: all_src_ss7 all_lib @touch .all_lib @@ -370,6 +382,15 @@ install_pri: @eval "cd ssmg; ./get_sangoma_prid.sh; cd .." $(MAKE) -C ssmg/sangoma_pri/ install SYSINC=$(PWD)/$(WINCLUDE) CC=$(CC) DESTDIR=$(INSTALLPREFIX) +install_pri_freetdm: + @eval "cd ssmg; ./get_sangoma_prid.sh; cd .." + $(MAKE) -C ssmg/sangoma_pri/ install_libs install_freetdm_lib SYSINC=$(PWD)/$(WINCLUDE) CC=$(CC) DESTDIR=$(INSTALLPREFIX) + +install_pri_freetdm_update: + @eval "cd ssmg; ./get_sangoma_prid.sh --update; cd .." + $(MAKE) -C ssmg/sangoma_pri/ install_libs install_freetdm_lib SYSINC=$(PWD)/$(WINCLUDE) CC=$(CC) DESTDIR=$(INSTALLPREFIX) + + install_pri_update: @eval "cd ssmg; ./get_sangoma_prid.sh --update; cd .." $(MAKE) -C ssmg/sangoma_pri/ install SYSINC=$(PWD)/$(WINCLUDE) CC=$(CC) DESTDIR=$(INSTALLPREFIX) diff --git a/OSLEC/echo/Kconfig b/OSLEC/echo/Kconfig new file mode 100644 index 0000000..f1d41ea --- /dev/null +++ b/OSLEC/echo/Kconfig @@ -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. diff --git a/OSLEC/echo/Makefile b/OSLEC/echo/Makefile new file mode 100644 index 0000000..7d4caac --- /dev/null +++ b/OSLEC/echo/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_ECHO) += echo.o diff --git a/OSLEC/echo/TODO b/OSLEC/echo/TODO new file mode 100644 index 0000000..1ca09af --- /dev/null +++ b/OSLEC/echo/TODO @@ -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 and Cc: Steve +Underwood and David Rowe diff --git a/OSLEC/echo/bit_operations.h b/OSLEC/echo/bit_operations.h new file mode 100644 index 0000000..cecdcf3 --- /dev/null +++ b/OSLEC/echo/bit_operations.h @@ -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 + * + * 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 ------------------------------------------------------------*/ diff --git a/OSLEC/echo/echo.c b/OSLEC/echo/echo.c new file mode 100644 index 0000000..fd4007e --- /dev/null +++ b/OSLEC/echo/echo.c @@ -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 + * and David Rowe + * + * 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 /* We're doing kernel work */ +#include +#include + +#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"); diff --git a/OSLEC/echo/echo.h b/OSLEC/echo/echo.h new file mode 100644 index 0000000..9fb9543 --- /dev/null +++ b/OSLEC/echo/echo.h @@ -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 + * and David Rowe + * + * 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 */ diff --git a/OSLEC/echo/fir.h b/OSLEC/echo/fir.h new file mode 100644 index 0000000..5645cb1 --- /dev/null +++ b/OSLEC/echo/fir.h @@ -0,0 +1,295 @@ +/* + * SpanDSP - a series of DSP components for telephony + * + * fir.h - General telephony FIR routines + * + * Written by Steve Underwood + * + * 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 ------------------------------------------------------------*/ diff --git a/OSLEC/echo/mmx.h b/OSLEC/echo/mmx.h new file mode 100644 index 0000000..35412ef --- /dev/null +++ b/OSLEC/echo/mmx.h @@ -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 */ diff --git a/OSLEC/echo/oslec.h b/OSLEC/echo/oslec.h new file mode 100644 index 0000000..bad8523 --- /dev/null +++ b/OSLEC/echo/oslec.h @@ -0,0 +1,86 @@ +/* + * OSLEC - A line echo canceller. This code is being developed + * against and partially complies with G168. Using code from SpanDSP + * + * Written by Steve Underwood + * and David Rowe + * + * 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 */ diff --git a/Setup b/Setup index 68e753c..2676864 100755 --- a/Setup +++ b/Setup @@ -9,7 +9,9 @@ # as published by the Free Software Foundation; either version # 2 of the License, or (at your option) any later version. # ---------------------------------------------------------------------------- -# Oct 29, 2009 Yannick Lam Added --no_woomera option (will not install woomera) +# May 10, 2010 Yannick Lam Added support for OSLEC for DAHDI only (--with-oslec) +# Apr 22, 2010 Yannick Lam Added support for dahdi-2.3 for various chunksize +# Oct 29, 2009 Yannick Lam Added --no_woomera option (will not install woomera) # Jul 29, 2009 Konrad Hammel Added --with-asterisk option # Jul 27, 2009 Konrad Hammel Update to not compile unneeded utilities in # TDM_VOICE mode. @@ -4796,6 +4798,10 @@ function install_ssmg_ss7() if [ $SSMG_SS7 != "YES" ]; then return 0 fi + + if [ $NO_SMG_INSTALL -eq 1 ]; then + return 0 + fi banner @@ -5731,12 +5737,64 @@ function tdmv_apply_zaptel_chunk_patch () { zaptel_modified=1 fi + eval "cat Kbuild | sed 's/^obj-.*+=.*wctdm24xxp.*//g'>$TEMP 2>/dev/null " + if [ $? -ne 0 ]; then + echo " Failed to remove wctdm24xxp from Kbuild" + exit 1 + + else + eval "\mv -f $TEMP Kbuild" + echo " wctdm24xxp module removed from Kbuild successfully" + zaptel_modified=1 + fi + + eval "cat Kbuild | sed 's/^obj-.*+=.*wcte12xp.*//g'>$TEMP 2>/dev/null " + if [ $? -ne 0 ]; then + echo " Failed to remove wcte12xp from Kbuild" + exit 1 + + else + eval "\mv -f $TEMP Kbuild" + echo " wcte12xp module removed from Kbuild successfully" + zaptel_modified=1 + fi + fi cd $lhome return 0; } +function tdmv_apply_oslec_patch () +{ + lhome_tmp=`pwd` + cd .. + lhome=`pwd` + TEMP=tmp + cd $ZAPTEL_SOURCE_DIR + echo "Applying Zaptel/Dahdi OSLEC echocanceler..." + echo " " + + dhname="Zaptel" + isdahdi="no" + if [ -f $ZAPTEL_SOURCE_DIR/dahdi/kernel.h ]; then + filetopatch="$ZAPTEL_SOURCE_DIR/dahdi/kernel.h" + dhname="Dahdi" + isdahdi="yes" + + cd .. + eval "mkdir drivers/staging" + eval "cp -rf $lhome/OSLEC/echo drivers/staging " + sed -i "s|#obj-m += dahdi_echocan_oslec.o|obj-m += dahdi_echocan_oslec.o|" drivers/dahdi/Kbuild + echo 'obj-m += echo.o' > drivers/staging/echo/Kbuild + make + make install + cd $lhome_tmp + + fi +} + + function tdmv_apply_zaptel_echo_debug_patch () { local rc @@ -6761,7 +6819,7 @@ ENDOFTEXT if [ $? -eq 0 ]; then if [ $AFT_TE1_PROT != YES ]; then echo "Enabling the AFT TE1 Support" - PROTOCOL_DEFINES="$PROTOCOL_DEFINES -DCONFIG_PRODUCT_WANPIPE_AFT -DCONFIG_PRODUCT_WANPIPE_AFT_CORE -DCONFIG_PRODUCT_WANPIPE_AFT_TE1 -DCONFIG_PRODUCT_WANPIPE_AFT_56K -DCONFIG_PRODUCT_WANPIPE_AFT_RM -DCONFIG_PRODUCT_WANPIPE_CODEC_SLINEAR_LAW -DCONFIG_PRODUCT_WANPIPE_AFT_BRI -DCONFIG_PRODUCT_WANPIPE_AFT_SERIAL -DCONFIG_PRODUCT_WANPIPE_AFT_A600 -DCONFIG_PRODUCT_WANPIPE_AFT_B601 " + PROTOCOL_DEFINES="$PROTOCOL_DEFINES -DCONFIG_PRODUCT_WANPIPE_AFT -DCONFIG_PRODUCT_WANPIPE_AFT_CORE -DCONFIG_PRODUCT_WANPIPE_AFT_TE1 -DCONFIG_PRODUCT_WANPIPE_AFT_56K -DCONFIG_PRODUCT_WANPIPE_AFT_RM -DCONFIG_PRODUCT_WANPIPE_CODEC_SLINEAR_LAW -DCONFIG_PRODUCT_WANPIPE_AFT_BRI -DCONFIG_PRODUCT_WANPIPE_AFT_SERIAL -DCONFIG_PRODUCT_WANPIPE_AFT_A600 -DCONFIG_PRODUCT_WANPIPE_AFT_B601 -DCONFIG_PRODUCT_WANPIPE_AFT_B800 " if [ $REL != "3.4" ]; then PROTOCOL_DEFINES="$PROTOCOL_DEFINES -DCONFIG_PRODUCT_WANPIPE_AFT_A700 " fi @@ -6949,6 +7007,11 @@ ENDOFTEXT tdmv_apply_zaptel_chunk_patch fi + if [ $OSLEC == "YES" ]; then + tdmv_apply_oslec_patch + fi + + #################################################################### if [ $ENABLE_ECHO_DEBUG -eq 1 ]; then getyn "Compile Echo Debugging Support for Zaptel (not supported for Dahdi yet) ? " @@ -7240,17 +7303,20 @@ or commands: --------- - install : Install/Upgrade WANPIPE - upgrade : Upgrade WANPIPE kernel device drivers - and utilities. (Same as install!) + install : Install/Upgrade General Wanpipe + zaptel : Install Wanpipe for Zaptel + dahdi : Install Wanpipe for Dahdi + xmtp2_api : Install Wanpipe for MTP2 API mode + remove : Uninstall WANPIPE remove_init : Uninstall WANPIPE Boot Startup Scripts install_init : Install WANPIPE Boot Startup Scripts + drivers : Re-install and Re-compile - WANPIPE kernel device drivers ONLY + Wanpipe kernel device drivers only buildrpm : Build the custom WANPIPE RPM binary for the current system. - For further help read README.rpm + For further help read README.rpm helprpm : RPM build help information. builddeb : Build the custom WANPIPE Debian binary : package for current system. @@ -7388,7 +7454,7 @@ KERNEL_UNAME=`uname -r` PKG_NAME=wanpipe DISTR_NAME="WANPIPE" PROD=wanrouter -PROD_VER=3.5.11 +PROD_VER=3.5.12 PROD_HOME=`pwd` META_CONF=$PROD_HOME/$PROD.rc WAN_INTR_DIR=$PROD_HOME/interfaces @@ -7419,6 +7485,7 @@ ZAPTEL_PATH_OP="NO" ZAPTEL_COMPILE_DISABLE="NO" BRI_MODULE_TEST="NO" ZAP_CHUNK_OP="NO" +OSLEC="NO" CMP_LOG=$PROD_HOME/setup_drv_compile.log CMP_BUILD=build.sh CMP_INSTALL=install.sh @@ -7582,6 +7649,7 @@ USR_CC= KBUILD_VERBOSE=0 KBUILD_DISABLE=0 NO_AUTO_START=0 +NO_SMG_INSTALL=0 PROTS= ROOT=; @@ -7664,6 +7732,12 @@ if [ "$setup_cmd" = "zaptel" ] || [ "$setup_cmd" = "dahdi" ] ; then #EXTRA_ARGS=" --protocol=TDM " fi +if [ "$setup_cmd" = "xmtp2_api" ]; then + setup_cmd="install" + NO_SMG_INSTALL=1 + PROTS="AFT_TE1-XMTP2" +fi + if [ "$setup_cmd" = "bri" ]; then setup_cmd="install" zaptel_auto_install="YES" @@ -7962,6 +8036,18 @@ if [ "$PKG_NAME" != "wanpipe-lite" ]; then fi fi ;; + + --with-oslec) + echo "WARNING:" + echo "You are going to use OSLEC as software echo canceler" + echo "Note: If you want to use OSLEC, do not forget to turn off the hardware echo canceler in wanpipe configuration" + getyn "Do you want to use OSLEC for Dahdi/Zaptel" + if [ $? -eq 0 ]; then + OSLEC="YES" + else + OSLEC="NO" + fi + ;; *) echo "Invalid option $arg" exit 1; diff --git a/api/legacy/Makefile b/api/legacy/Makefile index 6060830..1eb2838 100644 --- a/api/legacy/Makefile +++ b/api/legacy/Makefile @@ -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 diff --git a/api/legacy/aft/aft_api b/api/legacy/aft/aft_api deleted file mode 100755 index 22b4313..0000000 Binary files a/api/legacy/aft/aft_api and /dev/null differ diff --git a/api/legacy/aft/aft_api_repeater b/api/legacy/aft/aft_api_repeater deleted file mode 100755 index bbd4288..0000000 Binary files a/api/legacy/aft/aft_api_repeater and /dev/null differ diff --git a/api/legacy/chdlc/chdlc_echo b/api/legacy/chdlc/chdlc_echo deleted file mode 100755 index 3966cf9..0000000 Binary files a/api/legacy/chdlc/chdlc_echo and /dev/null differ diff --git a/api/legacy/chdlc/chdlc_modem_cmd b/api/legacy/chdlc/chdlc_modem_cmd deleted file mode 100755 index 1920f16..0000000 Binary files a/api/legacy/chdlc/chdlc_modem_cmd and /dev/null differ diff --git a/api/legacy/file b/api/legacy/file new file mode 100644 index 0000000..11f4ef1 --- /dev/null +++ b/api/legacy/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 diff --git a/api/libsangoma/.svn/all-wcprops b/api/libsangoma/.svn/all-wcprops index 53fbcb1..6db93af 100644 --- a/api/libsangoma/.svn/all-wcprops +++ b/api/libsangoma/.svn/all-wcprops @@ -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 diff --git a/api/libsangoma/.svn/entries b/api/libsangoma/.svn/entries index 9040225..462ed6c 100644 --- a/api/libsangoma/.svn/entries +++ b/api/libsangoma/.svn/entries @@ -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 diff --git a/api/libsangoma/.svn/text-base/libsangoma-pvt.h.svn-base b/api/libsangoma/.svn/text-base/libsangoma-pvt.h.svn-base index 532ef1f..3a76083 100644 --- a/api/libsangoma/.svn/text-base/libsangoma-pvt.h.svn-base +++ b/api/libsangoma/.svn/text-base/libsangoma-pvt.h.svn-base @@ -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; diff --git a/api/libsangoma/.svn/text-base/libsangoma.c.svn-base b/api/libsangoma/.svn/text-base/libsangoma.c.svn-base index b4cd35f..aebe5c7 100644 --- a/api/libsangoma/.svn/text-base/libsangoma.c.svn-base +++ b/api/libsangoma/.svn/text-base/libsangoma.c.svn-base @@ -307,12 +307,11 @@ sangoma_status_t _LIBSNG_CALL sangoma_cdev_ctrl_cmd(sng_fd_t fd, wanpipe_tdm_api return handle_device_ioctl_result(bIoResult, __FUNCTION__); } -static sangoma_status_t init_sangoma_event_object(sangoma_wait_obj_t *sng_wait_obj, int flags_in, sng_fd_t fd) +static sangoma_status_t init_sangoma_event_object(sangoma_wait_obj_t *sng_wait_obj, sng_fd_t fd) { - int event_index = -1; wanpipe_tdm_api_cmd_t tdm_api_cmd; sangoma_status_t sng_status; - char event_name[200], tmp_event_name[200]; + char event_name[200]; memset(&tdm_api_cmd, 0x00, sizeof(tdm_api_cmd)); @@ -325,40 +324,18 @@ static sangoma_status_t init_sangoma_event_object(sangoma_wait_obj_t *sng_wait_o DBG_EVNT("%s(): interface name: %s\n", __FUNCTION__, tdm_api_cmd.data); - if(flags_in & POLLIN){ - event_index = LIBSNG_EVENT_INDEX_POLLIN; - /* Form the Event Name from Interface Name and Event Type (i.e. wanpipe1_if1_pollin). */ - _snprintf(tmp_event_name, sizeof(tmp_event_name), "%s_pollin", tdm_api_cmd.data); - } - - if(flags_in & POLLOUT){ - event_index = LIBSNG_EVENT_INDEX_POLLOUT; - /* Form the Event Name from Interface Name and Event Type (i.e. wanpipe1_if1_pollout). */ - _snprintf(tmp_event_name, sizeof(tmp_event_name), "%s_pollout", tdm_api_cmd.data); - } - - if(flags_in & POLLPRI){ - event_index = LIBSNG_EVENT_INDEX_POLLPRI; - /* Form the Event Name from Interface Name and Event Type (i.e. wanpipe1_if1_pollpri). */ - _snprintf(tmp_event_name, sizeof(tmp_event_name), "%s_pollpri", tdm_api_cmd.data); - } - - if(event_index == -1){ - /* invalid 'flags_in', this should be an assert */ - return SANG_STATUS_GENERAL_ERROR; - } - /* 1. The Sangoma Device Driver creates Notification Events in "\\BaseNamedObjects\\Global\\" * when first CreateFile() was called by a process. That means the Events will inherit * the security attributes of the calling process, so the calling process will have * the permissions to open the Events by calling OpenEvent(). Since Events are created * "Global" subdirectory, the calling process does NOT need Administrator priveleges. + * The example name of the signaling object is: \\BaseNamedObjects\\Global\\wanpipe1_if1_signal. * 2. The Events are deleted when the last HANDLE for a device is closed by CloseHandle() * or automatically by the system when calling process exits. */ - _snprintf(event_name, sizeof(event_name), "Global\\%s", tmp_event_name); + _snprintf(event_name, sizeof(event_name), "Global\\%s_signal", tdm_api_cmd.data); - sng_wait_obj->sng_event_objects[event_index] = OpenEvent(EVENT_ALL_ACCESS, TRUE, event_name); - if(NULL == sng_wait_obj->sng_event_objects[event_index]){ + sng_wait_obj->signal_object = OpenEvent(EVENT_ALL_ACCESS, TRUE, event_name); + if(NULL == sng_wait_obj->signal_object){ /* error */ LibSangomaDecodeLastError(__FUNCTION__); return SANG_STATUS_GENERAL_ERROR; @@ -376,7 +353,7 @@ static sangoma_status_t sangoma_wait_obj_poll(sangoma_wait_obj_t *sangoma_wait_o *flags_out = 0; - memset(&api_poll, 0x00, sizeof(API_POLL_STRUCT)); + memset(&api_poll, 0x00, sizeof(api_poll)); api_poll.user_flags_bitmap = flags_in; /* This call is non-blocking - it will return immediatly. */ @@ -399,13 +376,20 @@ static sangoma_status_t sangoma_wait_obj_poll(sangoma_wait_obj_t *sangoma_wait_o return err; } -static int check_number_of_wait_objects(uint32_t number_of_objects, const char *caller_function, int lineno) +static int sangoma_check_number_of_wait_objects(uint32_t number_of_objects) { - if(number_of_objects >= MAXIMUM_WAIT_OBJECTS){ - DBG_ERR("Caller: %s(): Line: %d: 'number_of_objects': %d is greater than the Maximum of: %d\n", - caller_function, lineno, number_of_objects, MAXIMUM_WAIT_OBJECTS); + if(number_of_objects > MAXIMUM_WAIT_OBJECTS){ + DBG_ERR("'number_of_objects': %d is greater than the Maximum of: %d\n", + number_of_objects, MAXIMUM_WAIT_OBJECTS); return 1; } + + if(number_of_objects < 1){ + DBG_ERR("'number_of_objects': %d is less than the Minimum of: 1\n", + number_of_objects); + return 1; + } + return 0; } @@ -425,42 +409,36 @@ static sangoma_status_t get_out_flags(IN sangoma_wait_obj_t *sng_wait_objects[], sangoma_wait_obj_t *sangoma_wait_object = sng_wait_objects[i]; + if (!sangoma_wait_object->signal_object) { + return SANG_STATUS_DEV_INIT_INCOMPLETE; + } + if (!SANGOMA_OBJ_HAS_DEVICE(sangoma_wait_object)) { /* This object does not has a device, but, may have been signaled via sangoma_wait_obj_signal() * test if the object is signaled, if it is, set SANG_WAIT_OBJ_IS_SIGNALED */ - if((i == first_signaled_obj_index) || (WaitForSingleObject(sangoma_wait_object->generic_event_object, 0) == WAIT_OBJECT_0)) { - /* !+! jpboily : Since WaitForMultipleObjects cleared the status - * of the first signaled object, we make sure that the out_flag - * for this object is set */ + if((i == first_signaled_obj_index) || /* !+! jpboily : Since WaitForMultipleObjects cleared the status + * of the FIRST signaled object, we make sure that the out_flag + * for this object is set. + * !+! davidr: Status of all OTHER objects will be checked + * by WaitForSingleObject(). */ + (WaitForSingleObject(sangoma_wait_object->signal_object, 0) == WAIT_OBJECT_0)) { out_flags[i] |= SANG_WAIT_OBJ_IS_SIGNALED; } continue; } - for(j = 0; j < LIBSNG_NUMBER_OF_EVENT_OBJECTS; j++){ + if(sangoma_wait_obj_poll(sangoma_wait_object, in_flags[i], &out_flags[i])){ + return SANG_STATUS_GENERAL_ERROR; + } - if(!sangoma_wait_object->sng_event_objects[j]) { - continue; + if (out_flags[i] & in_flags[i]) { + if (at_least_one_poll_set_flags_out) { + *at_least_one_poll_set_flags_out = TRUE; } + } - if(sangoma_wait_obj_poll(sangoma_wait_object, in_flags[i], &out_flags[i])){ - return SANG_STATUS_GENERAL_ERROR; - } - - if( out_flags[i] & in_flags[i] ){ - if(at_least_one_poll_set_flags_out){ - *at_least_one_poll_set_flags_out = TRUE; - } - } -#if 0 - /* Check if a device-related object was signalled, if it is, set SANG_WAIT_OBJ_IS_SIGNALED. */ - if (WaitForSingleObject(sangoma_wait_object->sng_event_objects[j], 0) == WAIT_OBJECT_0) { - out_flags[i] |= SANG_WAIT_OBJ_IS_SIGNALED; - } -#endif - }/* for(j = 0; j < LIBSNG_NUMBER_OF_EVENT_OBJECTS; j++) */ }/* for(i = 0; i < number_of_sangoma_wait_objects; i++) */ return SANG_STATUS_SUCCESS; @@ -1255,7 +1233,7 @@ sangoma_status_t _LIBSNG_CALL sangoma_wait_obj_create(sangoma_wait_obj_t **sango sangoma_wait_obj_t *sng_wait_obj = NULL; if (!sangoma_wait_object) { - return SANG_STATUS_INVALID_DEVICE; + return SANG_STATUS_INVALID_PARAMETER; } *sangoma_wait_object = NULL; sng_wait_obj = malloc(sizeof(**sangoma_wait_object)); @@ -1271,40 +1249,19 @@ sangoma_status_t _LIBSNG_CALL sangoma_wait_obj_create(sangoma_wait_obj_t **sango sng_wait_obj->object_type = object_type; #if defined(__WINDOWS__) - DBG_INIT("%s(): sng_wait_obj ptr: 0x%p\n", __FUNCTION__, sng_wait_obj); - DBG_INIT("%s(): fd: 0x%X, object_type: %s\n", __FUNCTION__, fd, DECODE_SANGOMA_WAIT_OBJECT_TYPE(object_type)); - DBG_INIT("%s(): sizeof(**sangoma_wait_object): %d\n", __FUNCTION__, sizeof(**sangoma_wait_object)); - - if (SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) { - sng_wait_obj->generic_event_object = CreateEvent( NULL, FALSE, FALSE, NULL); - if(!sng_wait_obj->generic_event_object){ + if (!SANGOMA_OBJ_HAS_DEVICE(sng_wait_obj)) { + sng_wait_obj->signal_object = CreateEvent(NULL, FALSE, FALSE, NULL); + if(!sng_wait_obj->signal_object){ err = SANG_STATUS_GENERAL_ERROR; goto failed; } + err = SANG_STATUS_SUCCESS; + } else { + err = init_sangoma_event_object(sng_wait_obj, fd); + if(SANG_STATUS_SUCCESS != err){ + goto failed; + } } - - if(SANGOMA_GENERIC_WAIT_OBJ == object_type){ - /* everything is done for the generic wait object */ - *sangoma_wait_object = sng_wait_obj; - return SANG_STATUS_SUCCESS; - } - - err = init_sangoma_event_object(sng_wait_obj, POLLIN, fd); - if(SANG_STATUS_SUCCESS != err){ - goto failed; - } - - err = init_sangoma_event_object(sng_wait_obj, POLLOUT, fd); - if(SANG_STATUS_SUCCESS != err){ - goto failed; - } - - err = init_sangoma_event_object(sng_wait_obj, POLLPRI, fd); - if(SANG_STATUS_SUCCESS != err) { - goto failed; - } - - DBG_INIT("%s(): returning: %d", __FUNCTION__, err); #else int filedes[2]; if (SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) { @@ -1338,9 +1295,6 @@ failed: sangoma_status_t _LIBSNG_CALL sangoma_wait_obj_delete(sangoma_wait_obj_t **sangoma_wait_object) { sangoma_wait_obj_t *sng_wait_obj = *sangoma_wait_object; -#if defined(__WINDOWS__) - int index = 0; -#endif if(sng_wait_obj->init_flag != LIBSNG_MAGIC_NO){ /* error. object was not initialized by sangoma_wait_obj_init() */ @@ -1348,13 +1302,9 @@ sangoma_status_t _LIBSNG_CALL sangoma_wait_obj_delete(sangoma_wait_obj_t **sango } #if defined(__WINDOWS__) - if (SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) { - sangoma_close(&sng_wait_obj->generic_event_object); - } - if (SANGOMA_OBJ_HAS_DEVICE(sng_wait_obj)) { - for(index = 0; index < LIBSNG_NUMBER_OF_EVENT_OBJECTS; index++){ - sangoma_close(&sng_wait_obj->sng_event_objects[index]); - } + if (sng_wait_obj->signal_object && + sng_wait_obj->signal_object != INVALID_HANDLE_VALUE) { + sangoma_close(&sng_wait_obj->signal_object); } #else if (SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) { @@ -1380,13 +1330,12 @@ int _LIBSNG_CALL sangoma_wait_obj_signal(sangoma_wait_obj_t *sng_wait_obj) if (!SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) { /* even when Windows objects are always signalable for the sake of providing * a consistent interface to the user we downgrade the capabilities of Windows - * objects unless the sangoma wait object is explicitly initialized as signalable - * */ + * objects unless the sangoma wait object is explicitly initialized as signalable */ return SANG_STATUS_INVALID_DEVICE; } #if defined(__WINDOWS__) - if(sng_wait_obj->generic_event_object){ - if (!SetEvent(sng_wait_obj->generic_event_object)) { + if(sng_wait_obj->signal_object){ + if (!SetEvent(sng_wait_obj->signal_object)) { return SANG_STATUS_GENERAL_ERROR; } } @@ -1449,58 +1398,44 @@ sangoma_status_t _LIBSNG_CALL sangoma_waitfor_many(sangoma_wait_obj_t *sng_wait_ { #if defined(__WINDOWS__) HANDLE hEvents[MAXIMUM_WAIT_OBJECTS]; - uint32_t uiMapEventIndexToWaitObjectIndex[MAXIMUM_WAIT_OBJECTS]; DWORD dwResult; - int at_least_one_poll_set_flags_out, number_of_internal_signaling_objects, err; + int at_least_one_poll_set_flags_out, err; + sangoma_wait_obj_t *sangoma_wait_object; #endif uint32_t i = 0, j = 0; memset(out_flags, 0x00, number_of_sangoma_wait_objects * sizeof(out_flags[0])); #if defined(__WINDOWS__) - /* This loop will calculate 'number_of_internal_signaling_objects' and will initialize 'hEvents' - * based on 'number_of_sangoma_wait_objects' and 'in_flags'. */ - number_of_internal_signaling_objects = 0; - for(i = 0; i < number_of_sangoma_wait_objects; i++){ - sangoma_wait_obj_t *sangoma_wait_object = sng_wait_objects[i]; - /* if SANGOMA_OBJ_IS_SIGNALABLE add the generic_event_object.hEvent to the hEvents */ - if(sangoma_wait_object->generic_event_object){ - if(check_number_of_wait_objects(number_of_internal_signaling_objects, __FUNCTION__, __LINE__)){ - return SANG_STATUS_NO_FREE_BUFFERS; - } - hEvents[number_of_internal_signaling_objects] = sangoma_wait_object->generic_event_object; - uiMapEventIndexToWaitObjectIndex[number_of_internal_signaling_objects] = i; - number_of_internal_signaling_objects++; - } - - for(j = 0; j < LIBSNG_NUMBER_OF_EVENT_OBJECTS; j++){ - if(sangoma_wait_object->sng_event_objects[j]){ - if( ((j == LIBSNG_EVENT_INDEX_POLLIN) && (in_flags[i] & POLLIN)) || - ((j == LIBSNG_EVENT_INDEX_POLLOUT) && (in_flags[i] & POLLOUT)) || - ((j == LIBSNG_EVENT_INDEX_POLLPRI) && (in_flags[i] & POLLPRI)) ){ - - if(check_number_of_wait_objects(number_of_internal_signaling_objects, __FUNCTION__, __LINE__)){ - return SANG_STATUS_NO_FREE_BUFFERS; - } - hEvents[number_of_internal_signaling_objects] = sangoma_wait_object->sng_event_objects[j]; - uiMapEventIndexToWaitObjectIndex[number_of_internal_signaling_objects] = i; - number_of_internal_signaling_objects++; - } - }/* if () */ - }/* for() */ - }/* for() */ - - if(number_of_internal_signaling_objects < 1){ - DBG_ERR("'number_of_internal_signaling_objects': %d is less than the Minimum of: 1!\n", - number_of_internal_signaling_objects); + if(sangoma_check_number_of_wait_objects(number_of_sangoma_wait_objects)){ /* error - most likely the user did not initialize sng_wait_objects[] */ return SANG_STATUS_INVALID_PARAMETER; } + for(i = 0; i < MAXIMUM_WAIT_OBJECTS; i++){ + hEvents[i] = INVALID_HANDLE_VALUE; + } + + /* This loop will initialize 'hEvents[]' based on + * 'number_of_sangoma_wait_objects' and sng_wait_objects[]. */ + for(i = 0; i < number_of_sangoma_wait_objects; i++){ + + sangoma_wait_object = sng_wait_objects[i]; + + if(LIBSNG_MAGIC_NO != sangoma_wait_object->init_flag){ + return SANG_STATUS_DEV_INIT_INCOMPLETE; + } + + if(sangoma_wait_object->signal_object){ + hEvents[i] = sangoma_wait_object->signal_object; + } + + }/* for() */ + at_least_one_poll_set_flags_out = FALSE; /* It is important to get 'out flags' BEFORE the WaitForMultipleObjects() - * because it allows to keep API driver's transmit queue full. */ + * because it allows to keep API driver's TRANSMIT queue full. */ err = get_out_flags(sng_wait_objects, INVALID_INDEX, in_flags, out_flags, number_of_sangoma_wait_objects, &at_least_one_poll_set_flags_out); if(SANG_ERROR(err)){ return err; @@ -1511,19 +1446,19 @@ sangoma_status_t _LIBSNG_CALL sangoma_waitfor_many(sangoma_wait_obj_t *sng_wait_ } /* wait untill at least one of the events is signaled OR a 'system_wait_timeout' occured */ - dwResult = WaitForMultipleObjects(number_of_internal_signaling_objects, &hEvents[0], FALSE, system_wait_timeout); + dwResult = WaitForMultipleObjects(number_of_sangoma_wait_objects, &hEvents[0], FALSE, system_wait_timeout); if (WAIT_TIMEOUT == dwResult){ return SANG_STATUS_APIPOLL_TIMEOUT; } - if( dwResult >= (DWORD)number_of_internal_signaling_objects ) { + if( dwResult >= (DWORD)number_of_sangoma_wait_objects ) { return SANG_STATUS_GENERAL_ERROR; } /* WaitForMultipleObjects() was waken by a Sangoma or by a non-Sangoma wait object. */ err = get_out_flags(sng_wait_objects, - uiMapEventIndexToWaitObjectIndex[dwResult],/* This is the index of first signaled object in - * the original sng_wait_objects[] array, not in hEvents[] array. */ + dwResult, /* Array index of the signalled object with the smallest index + * value of all the signalled objects, from array. */ in_flags, out_flags, number_of_sangoma_wait_objects, NULL); if(SANG_ERROR(err)){ return err; @@ -1681,14 +1616,25 @@ int _LIBSNG_CALL sangoma_span_chan_fromif(char *interface_name, int *span, int * int ret = 0; char data[FNAME_LEN]; + /* Windows: Accept WANPIPEx_IFy or wanpipex_ify + * where x is the span and y is the chan. */ + strncpy(data, interface_name, FNAME_LEN); if ((data[0])) { for (p = data; *p; p++) { +#if defined(__WINDOWS__) + if (sp && (*p == 'F'||*p == 'f')) { +#else if (sp && *p == 'c') { +#endif *p = '\0'; ch = (p + 1); break; +#if defined(__WINDOWS__) + } else if (*p == 'E'||*p == 'e') { +#else } else if (*p == 's') { +#endif sp = (p + 1); } } @@ -1791,6 +1737,7 @@ int _LIBSNG_CALL sangoma_get_open_cnt(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_OPEN_CNT; err=sangoma_cmd_exec(fd,tdm_api); @@ -1897,8 +1844,11 @@ int _LIBSNG_CALL sangoma_readmsg(sng_fd_t fd, void *hdrbuf, int hdrlen, void *da rx_hdr->operation_status = SANG_STATUS_BUFFER_TOO_SMALL; } break; + case SANG_STATUS_NO_DATA_AVAILABLE: + /* Note that SANG_STATUS_NO_DATA_AVAILABLE is NOT an error becase + * read() is non-blocking and can be called at any time (by some polling code)*/ + return 1; /* return positive value to indicate success, user must check 'rx_hdr->operation_status' */ default: - /* note that SANG_STATUS_NO_DATA_AVAILABLE is NOT an error! */ if(libsng_dbg_level)DBG_ERR("Operation Status: %s(%d)\n", SDLA_DECODE_SANG_STATUS(rx_hdr->operation_status), rx_hdr->operation_status); return -5; @@ -2039,6 +1989,7 @@ int _LIBSNG_CALL sangoma_get_full_cfg(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_FULL_CFG; err=sangoma_cmd_exec(fd,tdm_api); @@ -2092,6 +2043,7 @@ int _LIBSNG_CALL sangoma_get_full_cfg(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_tdm_set_codec(sng_fd_t fd, wanpipe_api_t *tdm_api, int codec) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_CODEC; tdm_api->wp_cmd.tdm_codec = codec; return sangoma_cmd_exec(fd,tdm_api); @@ -2114,6 +2066,7 @@ int _LIBSNG_CALL sangoma_tdm_get_codec(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_CODEC; err=sangoma_cmd_exec(fd,tdm_api); @@ -2134,6 +2087,7 @@ int _LIBSNG_CALL sangoma_tdm_get_codec(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_tdm_set_usr_period(sng_fd_t fd, wanpipe_api_t *tdm_api, int period) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_USR_PERIOD; tdm_api->wp_cmd.usr_period = period; return sangoma_cmd_exec(fd,tdm_api); @@ -2151,6 +2105,7 @@ int _LIBSNG_CALL sangoma_tdm_get_usr_period(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_USR_PERIOD; err=sangoma_cmd_exec(fd,tdm_api); @@ -2172,6 +2127,7 @@ int _LIBSNG_CALL sangoma_get_hw_coding(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_CODING; err=sangoma_cmd_exec(fd,tdm_api); if (err){ @@ -2192,6 +2148,7 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_dtmf(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_DTMF; err=sangoma_cmd_exec(fd,tdm_api); if (err){ @@ -2201,9 +2158,9 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_dtmf(sng_fd_t fd, wanpipe_api_t *tdm_api) } /*======================================================== - * GET Current User Hardware EC Enabled/Disabled + * GET status of echo canceler chip. * - * Will return true if HW EC is enabled + * Will return true if HW EC is available */ int _LIBSNG_CALL sangoma_tdm_get_hw_ec(sng_fd_t fd, wanpipe_api_t *tdm_api) @@ -2211,6 +2168,7 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_ec(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_EC; err=sangoma_cmd_exec(fd,tdm_api); if (err){ @@ -2220,6 +2178,31 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_ec(sng_fd_t fd, wanpipe_api_t *tdm_api) } #endif + +#ifdef WP_API_FEATURE_EC_CHAN_STAT +/*======================================================== + * GET status of the echo canceler for current channel. + * + * Will return true if HW EC is enabled + */ + +int _LIBSNG_CALL sangoma_tdm_get_hwec_chan_status(sng_fd_t fd, wanpipe_api_t *tdm_api) +{ + int err; + + WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); + tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_EC_CHAN; + err=sangoma_cmd_exec(fd,tdm_api); + if (err){ + return err; + } + return tdm_api->wp_cmd.hw_ec; +} + +#endif + + /*======================================================== * GET Current User MTU/MRU values in bytes. * @@ -2231,6 +2214,7 @@ int _LIBSNG_CALL sangoma_tdm_get_usr_mtu_mru(sng_fd_t fd, wanpipe_api_t *tdm_api int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_USR_MTU_MRU; err=sangoma_cmd_exec(fd,tdm_api); @@ -2250,6 +2234,7 @@ int _LIBSNG_CALL sangoma_tdm_get_usr_mtu_mru(sng_fd_t fd, wanpipe_api_t *tdm_api int _LIBSNG_CALL sangoma_tdm_set_power_level(sng_fd_t fd, wanpipe_api_t *tdm_api, int power) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_POWER_LEVEL; tdm_api->wp_cmd.power_level = power; return sangoma_cmd_exec(fd,tdm_api); @@ -2266,6 +2251,7 @@ int _LIBSNG_CALL sangoma_tdm_get_power_level(sng_fd_t fd, wanpipe_api_t *tdm_api int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_POWER_LEVEL; err=sangoma_cmd_exec(fd,tdm_api); @@ -2279,6 +2265,7 @@ int _LIBSNG_CALL sangoma_tdm_get_power_level(sng_fd_t fd, wanpipe_api_t *tdm_api int _LIBSNG_CALL sangoma_flush_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_FLUSH_BUFFERS; return sangoma_cmd_exec(fd,tdm_api); } @@ -2286,6 +2273,7 @@ int _LIBSNG_CALL sangoma_flush_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_flush_rx_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_FLUSH_RX_BUFFERS; return sangoma_cmd_exec(fd,tdm_api); } @@ -2293,6 +2281,7 @@ int _LIBSNG_CALL sangoma_flush_rx_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_flush_tx_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_FLUSH_TX_BUFFERS; return sangoma_cmd_exec(fd,tdm_api); } @@ -2300,6 +2289,7 @@ int _LIBSNG_CALL sangoma_flush_tx_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_flush_event_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_FLUSH_EVENT_BUFFERS; return sangoma_cmd_exec(fd,tdm_api); } @@ -2307,6 +2297,7 @@ int _LIBSNG_CALL sangoma_flush_event_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_tdm_enable_rbs_events(sng_fd_t fd, wanpipe_api_t *tdm_api, int poll_in_sec) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_ENABLE_RBS_EVENTS; tdm_api->wp_cmd.rbs_poll = poll_in_sec; return sangoma_cmd_exec(fd,tdm_api); @@ -2315,6 +2306,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_rbs_events(sng_fd_t fd, wanpipe_api_t *tdm_a int _LIBSNG_CALL sangoma_tdm_disable_rbs_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_DISABLE_RBS_EVENTS; return sangoma_cmd_exec(fd,tdm_api); } @@ -2322,6 +2314,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_rbs_events(sng_fd_t fd, wanpipe_api_t *tdm_ int _LIBSNG_CALL sangoma_tdm_write_rbs(sng_fd_t fd, wanpipe_api_t *tdm_api, int channel, unsigned char rbs) { WANPIPE_API_INIT_CHAN(tdm_api, channel); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_WRITE_RBS_BITS; tdm_api->wp_cmd.rbs_tx_bits=rbs; return sangoma_cmd_exec(fd,tdm_api); @@ -2331,6 +2324,7 @@ int _LIBSNG_CALL sangoma_tdm_read_rbs(sng_fd_t fd, wanpipe_api_t *tdm_api, int c { int err; WANPIPE_API_INIT_CHAN(tdm_api, channel); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_READ_RBS_BITS; tdm_api->wp_cmd.rbs_tx_bits=0; @@ -2341,7 +2335,29 @@ int _LIBSNG_CALL sangoma_tdm_read_rbs(sng_fd_t fd, wanpipe_api_t *tdm_api, int c *rbs=(unsigned char)tdm_api->wp_cmd.rbs_rx_bits; return 0; -} +} + +#ifdef WP_API_FEATURE_BUFFER_MULT + +int _LIBSNG_CALL sangoma_tdm_set_buffer_multiplier(sng_fd_t fd, wanpipe_api_t *tdm_api, unsigned int multiplier) +{ + + int err; + WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); + tdm_api->wp_cmd.cmd = WP_API_CMD_BUFFER_MULTIPLIER; + *((unsigned int*)&tdm_api->wp_cmd.data[0]) = multiplier; + + err=sangoma_cmd_exec(fd,tdm_api); + if (err){ + return err; + } + + return 0; +} + +#endif + int _LIBSNG_CALL sangoma_read_event(sng_fd_t fd, wanpipe_api_t *tdm_api) { @@ -2351,6 +2367,7 @@ int _LIBSNG_CALL sangoma_read_event(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_READ_EVENT; err=sangoma_cmd_exec(fd,tdm_api); @@ -2360,6 +2377,7 @@ int _LIBSNG_CALL sangoma_read_event(sng_fd_t fd, wanpipe_api_t *tdm_api) rx_event = &tdm_api->wp_cmd.event; +#ifdef WP_API_DEPRECATED_FEATURE_READ_CALLBACK_FUNCTIONS /* The use of callbacks here is purely optional and is left here for backward compatibility purposes. By default user @@ -2439,6 +2457,9 @@ int _LIBSNG_CALL sangoma_read_event(sng_fd_t fd, wanpipe_api_t *tdm_api) #endif break; } + +#endif + return 0; #else @@ -2516,6 +2537,7 @@ sangoma_status_t _LIBSNG_CALL sangoma_logger_set_logger_level(sng_fd_t fd, wp_lo int _LIBSNG_CALL sangoma_tdm_enable_fax_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_FAX_DETECT; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2525,6 +2547,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_fax_events(sng_fd_t fd, wanpipe_api_t *tdm_a int _LIBSNG_CALL sangoma_tdm_disable_fax_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_FAX_DETECT; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE; @@ -2535,6 +2558,7 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_fax(sng_fd_t fd, wanpipe_api_t *tdm_api) { int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_FAX_DETECT; err=sangoma_cmd_exec(fd,tdm_api); if (err){ @@ -2548,6 +2572,7 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_fax(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_tdm_enable_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_DTMF; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2557,6 +2582,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_ int _LIBSNG_CALL sangoma_tdm_disable_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_DTMF; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE; @@ -2566,6 +2592,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm int _LIBSNG_CALL sangoma_tdm_enable_rm_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RM_DTMF; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2575,6 +2602,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_rm_dtmf_events(sng_fd_t fd, wanpipe_api_t *t int _LIBSNG_CALL sangoma_tdm_disable_rm_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RM_DTMF; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE; @@ -2584,6 +2612,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_rm_dtmf_events(sng_fd_t fd, wanpipe_api_t * int _LIBSNG_CALL sangoma_tdm_enable_rxhook_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RXHOOK; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2593,6 +2622,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_rxhook_events(sng_fd_t fd, wanpipe_api_t *td int _LIBSNG_CALL sangoma_tdm_disable_rxhook_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RXHOOK; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE; @@ -2602,6 +2632,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_rxhook_events(sng_fd_t fd, wanpipe_api_t *t int _LIBSNG_CALL sangoma_tdm_enable_ring_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2611,6 +2642,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_ring_events(sng_fd_t fd, wanpipe_api_t *tdm_ int _LIBSNG_CALL sangoma_tdm_disable_ring_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE; @@ -2620,6 +2652,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_ring_events(sng_fd_t fd, wanpipe_api_t *tdm int _LIBSNG_CALL sangoma_tdm_enable_ring_detect_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING_DETECT; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2629,6 +2662,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_ring_detect_events(sng_fd_t fd, wanpipe_api_ int _LIBSNG_CALL sangoma_tdm_disable_ring_detect_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING_DETECT; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE; @@ -2638,6 +2672,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_ring_detect_events(sng_fd_t fd, wanpipe_api int _LIBSNG_CALL sangoma_tdm_enable_ring_trip_detect_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING_TRIP_DETECT; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2647,6 +2682,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_ring_trip_detect_events(sng_fd_t fd, wanpipe int _LIBSNG_CALL sangoma_tdm_disable_ring_trip_detect_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING_TRIP_DETECT; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE; @@ -2656,6 +2692,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_ring_trip_detect_events(sng_fd_t fd, wanpip int _LIBSNG_CALL sangoma_tdm_txsig_kewl(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TXSIG_KEWL; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2665,6 +2702,7 @@ int _LIBSNG_CALL sangoma_tdm_txsig_kewl(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_tdm_txsig_start(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TXSIG_START; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2674,6 +2712,7 @@ int _LIBSNG_CALL sangoma_tdm_txsig_start(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_tdm_txsig_onhook(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TXSIG_ONHOOK; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2683,6 +2722,7 @@ int _LIBSNG_CALL sangoma_tdm_txsig_onhook(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_tdm_txsig_offhook(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TXSIG_OFFHOOK; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2692,6 +2732,7 @@ int _LIBSNG_CALL sangoma_tdm_txsig_offhook(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_tdm_enable_tone_events(sng_fd_t fd, wanpipe_api_t *tdm_api, uint16_t tone_id) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TONE; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2702,6 +2743,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_tone_events(sng_fd_t fd, wanpipe_api_t *tdm_ int _LIBSNG_CALL sangoma_tdm_disable_tone_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TONE; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE; @@ -2713,6 +2755,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_tone_events(sng_fd_t fd, wanpipe_api_t *tdm int _LIBSNG_CALL sangoma_tdm_enable_hwec(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_ENABLE_HWEC; return sangoma_cmd_exec(fd,tdm_api); } @@ -2720,6 +2763,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_hwec(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_tdm_disable_hwec(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_DISABLE_HWEC; return sangoma_cmd_exec(fd,tdm_api); } @@ -2735,6 +2779,7 @@ int _LIBSNG_CALL sangoma_tdm_get_fe_alarms(sng_fd_t fd, wanpipe_api_t *tdm_api, int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_FE_ALARMS; err=sangoma_cmd_exec(fd,tdm_api); @@ -2753,6 +2798,7 @@ int _LIBSNG_CALL sangoma_get_fe_status(sng_fd_t fd, wanpipe_api_t *tdm_api, unsi int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_FE_STATUS; err = sangoma_cmd_exec(fd, tdm_api); *current_status = tdm_api->wp_cmd.fe_status; @@ -2768,6 +2814,7 @@ int _LIBSNG_CALL sangoma_get_link_status(sng_fd_t fd, wanpipe_api_t *tdm_api, un int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_FE_STATUS; err = sangoma_cmd_exec(fd, tdm_api); *current_status = tdm_api->wp_cmd.fe_status; @@ -2779,6 +2826,7 @@ int _LIBSNG_CALL sangoma_get_link_status(sng_fd_t fd, wanpipe_api_t *tdm_api, un int _LIBSNG_CALL sangoma_set_fe_status(sng_fd_t fd, wanpipe_api_t *tdm_api, unsigned char new_status) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_FE_STATUS; tdm_api->wp_cmd.fe_status = new_status; return sangoma_cmd_exec(fd, tdm_api); @@ -2788,6 +2836,7 @@ int _LIBSNG_CALL sangoma_set_fe_status(sng_fd_t fd, wanpipe_api_t *tdm_api, unsi int _LIBSNG_CALL sangoma_disable_bri_bchan_loopback(sng_fd_t fd, wanpipe_api_t *tdm_api, int channel) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.channel = (unsigned char)channel; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_BRI_CHAN_LOOPBACK; @@ -2798,6 +2847,7 @@ int _LIBSNG_CALL sangoma_disable_bri_bchan_loopback(sng_fd_t fd, wanpipe_api_t * int _LIBSNG_CALL sangoma_enable_bri_bchan_loopback(sng_fd_t fd, wanpipe_api_t *tdm_api, int channel) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.channel = (unsigned char)channel; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_BRI_CHAN_LOOPBACK; @@ -2810,6 +2860,7 @@ int _LIBSNG_CALL sangoma_get_tx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_TX_Q_SIZE; tdm_api->wp_cmd.tx_queue_sz = 0; @@ -2827,6 +2878,7 @@ int _LIBSNG_CALL sangoma_set_tx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api, in return -1; } WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_TX_Q_SIZE; tdm_api->wp_cmd.tx_queue_sz = size; return sangoma_cmd_exec(fd, tdm_api); @@ -2837,6 +2889,7 @@ int _LIBSNG_CALL sangoma_get_rx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_RX_Q_SIZE; tdm_api->wp_cmd.rx_queue_sz = 0; @@ -2856,6 +2909,7 @@ int _LIBSNG_CALL sangoma_set_rx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api, in } WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_RX_Q_SIZE; tdm_api->wp_cmd.rx_queue_sz = size; return sangoma_cmd_exec(fd, tdm_api); @@ -2866,6 +2920,7 @@ int _LIBSNG_CALL sangoma_get_driver_version(sng_fd_t fd, wanpipe_api_t *tdm_api, int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_DRIVER_VERSION; err = sangoma_cmd_exec(fd, tdm_api); @@ -2887,6 +2942,7 @@ int _LIBSNG_CALL sangoma_get_firmware_version(sng_fd_t fd, wanpipe_api_t *tdm_ap int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_FIRMWARE_VERSION; err = sangoma_cmd_exec(fd, tdm_api); @@ -2906,6 +2962,7 @@ int _LIBSNG_CALL sangoma_get_cpld_version(sng_fd_t fd, wanpipe_api_t *tdm_api, u int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_CPLD_VERSION; err = sangoma_cmd_exec(fd, tdm_api); @@ -2925,6 +2982,7 @@ int _LIBSNG_CALL sangoma_get_stats(sng_fd_t fd, wanpipe_api_t *tdm_api, wanpipe_ int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_STATS; err = sangoma_cmd_exec(fd, tdm_api); @@ -2940,6 +2998,7 @@ int _LIBSNG_CALL sangoma_get_stats(sng_fd_t fd, wanpipe_api_t *tdm_api, wanpipe_ int _LIBSNG_CALL sangoma_flush_stats(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_RESET_STATS; return sangoma_cmd_exec(fd, tdm_api); } @@ -2947,6 +3006,7 @@ int _LIBSNG_CALL sangoma_flush_stats(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_set_rm_rxflashtime(sng_fd_t fd, wanpipe_api_t *tdm_api, int rxflashtime) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_RM_RXFLASHTIME; tdm_api->wp_cmd.rxflashtime=rxflashtime; return sangoma_cmd_exec(fd, tdm_api); @@ -2956,6 +3016,7 @@ int _LIBSNG_CALL sangoma_set_rm_rxflashtime(sng_fd_t fd, wanpipe_api_t *tdm_api, int _LIBSNG_CALL sangoma_set_rm_tx_gain(sng_fd_t fd, wanpipe_api_t *tdm_api, int value) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_SET_RM_TX_GAIN; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2966,6 +3027,7 @@ int _LIBSNG_CALL sangoma_set_rm_tx_gain(sng_fd_t fd, wanpipe_api_t *tdm_api, int int _LIBSNG_CALL sangoma_set_rm_rx_gain(sng_fd_t fd, wanpipe_api_t *tdm_api, int value) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_SET_RM_RX_GAIN; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2979,6 +3041,7 @@ int _LIBSNG_CALL sangoma_tdm_set_polarity(sng_fd_t fd, wanpipe_api_t *tdm_api, i int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_SETPOLARITY; tdm_api->wp_cmd.event.wp_api_event_polarity = polarity; @@ -2991,6 +3054,7 @@ int _LIBSNG_CALL sangoma_tdm_set_polarity(sng_fd_t fd, wanpipe_api_t *tdm_api, i int _LIBSNG_CALL sangoma_tdm_txsig_onhooktransfer(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_ONHOOKTRANSFER; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -3004,6 +3068,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_loop(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_ENABLE_LOOP; err = sangoma_cmd_exec(fd, tdm_api); return err; @@ -3014,6 +3079,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_loop(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_DISABLE_LOOP; err = sangoma_cmd_exec(fd, tdm_api); return err; @@ -3139,6 +3205,7 @@ int _LIBSNG_CALL sangoma_mgmt_cmd(sng_fd_t fd, wan_udp_hdr_t* wan_udp) int _LIBSNG_CALL sangoma_driver_port_start(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no) { int err; + port_mgmnt->operation_status = SANG_STATUS_GENERAL_ERROR; port_mgmnt->command_code = START_PORT_VOLATILE_CONFIG; port_mgmnt->port_no = port_no; @@ -3154,6 +3221,7 @@ int _LIBSNG_CALL sangoma_driver_port_start(sng_fd_t fd, port_management_struct_t int _LIBSNG_CALL sangoma_driver_port_stop(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no) { int err; + port_mgmnt->operation_status = SANG_STATUS_GENERAL_ERROR; port_mgmnt->command_code = STOP_PORT; port_mgmnt->port_no = port_no; @@ -3182,6 +3250,7 @@ int _LIBSNG_CALL sangoma_driver_port_stop(sng_fd_t fd, port_management_struct_t int _LIBSNG_CALL sangoma_driver_get_hw_info(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no) { int err; + port_mgmnt->operation_status = SANG_STATUS_GENERAL_ERROR; port_mgmnt->command_code = GET_HARDWARE_INFO; port_mgmnt->port_no = port_no; @@ -3193,8 +3262,23 @@ int _LIBSNG_CALL sangoma_driver_get_hw_info(sng_fd_t fd, port_management_struct_ return port_mgmnt->operation_status; } +int _LIBSNG_CALL sangoma_driver_get_version(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no) +{ + int err; + port_mgmnt->command_code = GET_DRIVER_VERSION; + port_mgmnt->port_no = port_no; + + err = sangoma_port_mgmnt_ioctl(fd, port_mgmnt); + if (err) { + return err; + } + + return port_mgmnt->operation_status; +} + int _LIBSNG_CALL sangoma_driver_port_set_config(sng_fd_t fd, port_cfg_t *port_cfg, unsigned short port_no) { + port_cfg->operation_status = SANG_STATUS_GENERAL_ERROR; port_cfg->command_code = SET_PORT_VOLATILE_CONFIG; port_cfg->port_no = port_no; @@ -3203,6 +3287,7 @@ int _LIBSNG_CALL sangoma_driver_port_set_config(sng_fd_t fd, port_cfg_t *port_cf int _LIBSNG_CALL sangoma_driver_port_get_config(sng_fd_t fd, port_cfg_t *port_cfg, unsigned short port_no) { + port_cfg->operation_status = SANG_STATUS_GENERAL_ERROR; port_cfg->command_code = GET_PORT_VOLATILE_CONFIG; port_cfg->port_no = port_no; return sangoma_port_cfg_ioctl(fd, port_cfg); diff --git a/api/libsangoma/.svn/text-base/libsangoma.h.svn-base b/api/libsangoma/.svn/text-base/libsangoma.h.svn-base index 58fecf9..e051ccd 100644 --- a/api/libsangoma/.svn/text-base/libsangoma.h.svn-base +++ b/api/libsangoma/.svn/text-base/libsangoma.h.svn-base @@ -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 #include #include +#include /*! \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 */ diff --git a/api/libsangoma/.svn/text-base/libsangoma.vcproj.svn-base b/api/libsangoma/.svn/text-base/libsangoma.vcproj.svn-base index c1e2001..d2408b0 100644 --- a/api/libsangoma/.svn/text-base/libsangoma.vcproj.svn-base +++ b/api/libsangoma/.svn/text-base/libsangoma.vcproj.svn-base @@ -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" diff --git a/api/libsangoma/.svn/text-base/libsangoma_hwec.c.svn-base b/api/libsangoma/.svn/text-base/libsangoma_hwec.c.svn-base index a1909e7..448df07 100644 --- a/api/libsangoma/.svn/text-base/libsangoma_hwec.c.svn-base +++ b/api/libsangoma/.svn/text-base/libsangoma_hwec.c.svn-base @@ -44,12 +44,7 @@ # pragma comment( lib, "waneclib" ) /* import functions from waneclib.dll */ #endif/* __WINDOWS__) */ -/* Fast sequence of commands to HWEC may cause the chip - * enter fatal error state, the workaround is to have - * a guaranteed delay after eache command. */ -#define HWEC_CMD_DELAY() wp_usleep(20000) /* 20ms */ - -static int libsng_hwec_verbosity_level = 0; +static int libsng_hwec_verbosity_level = 0x00; /************************************************************//** * Private Functions. (Not exported) @@ -67,54 +62,145 @@ static sangoma_status_t sangoma_hwec_bypass(char *device_name, int enable, unsig /* WAN_EC_API_CMD_HWEC_ENABLE/WAN_EC_API_CMD_HWEC_DISABLE - Controls the "bypass" mode.)*/ rc = wanec_api_hwec(device_name, libsng_hwec_verbosity_level, &hwec); - if( rc ) { - return rc; - } - HWEC_CMD_DELAY(); - return SANG_STATUS_SUCCESS; + + return rc; } +static int sangoma_hwec_is_numeric_parameter(char *parameter) +{ + int i; + static char *WANEC_numeric_params[] = { + "WANEC_TailDisplacement", + "WANEC_MaxPlayoutBuffers", + "WANEC_MaxConfBridges", + "WANEC_EchoOperationMode", + "WANEC_ComfortNoiseMode", + "WANEC_NonLinearityBehaviorA", + "WANEC_NonLinearityBehaviorB", + "WANEC_DoubleTalkBehavior", + "WANEC_RinLevelControlGainDb", + "WANEC_SoutLevelControlGainDb", + "WANEC_RinAutomaticLevelControlTargetDb", + "WANEC_SoutAutomaticLevelControlTargetDb", + "WANEC_RinHighLevelCompensationThresholdDb", + "WANEC_AnrSnrEnhancementDb", + NULL + }; -/************************************************************//** + i = 0; + while(WANEC_numeric_params[i]){ + if (!wp_strncasecmp(parameter, WANEC_numeric_params[i], strlen(parameter))) { + return 1;/* this IS a numeric parameter */ + } + i++; + }; + + return 0;/* NOT a numeric parameter */ +} + +/*************************************************************** * Public Functions. (Exported) ***************************************************************/ /*! - \fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name) + \fn void _LIBSNG_CALL sangoma_hwec_initialize_custom_parameter_structure(wan_custom_param_t *custom_param, char *parameter_name, char *parameter_value) - \brief Load Firmware image onto EC chip. + \brief Initialize Custom Paramter structure. + + \param parameter_name Parameter Name + + \param parameter_value Parameter Value + + \return None +*/ +void _LIBSNG_CALL sangoma_hwec_initialize_custom_parameter_structure(wan_custom_param_t *custom_param, char *parameter_name, char *parameter_value) +{ + memset(custom_param, 0x00, sizeof(*custom_param)); + + strncpy( custom_param->name, parameter_name, sizeof(custom_param->name) ); + + if (sangoma_hwec_is_numeric_parameter(parameter_name)) { + custom_param->dValue = atoi(parameter_value); + } else { + strncpy(custom_param->sValue, parameter_value, sizeof(custom_param->sValue)); + } +} + +/*! + \fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name, wan_custom_param_t custom_params[], unsigned int number_of_custom_params) + + \brief Load Firmware image onto EC chip. All chip-wide configuration paramters, if any, + must be specified at the time of chip initialization. \param device_name Sangoma API device name. Windows: wanpipe1_if1, wanpipe2_if1... Linux: wanpipe1, wanpipe2... + \param custom_params[] - (optional) array of custom paramter structures. + + This is list of Echo Cancellation chip parameters: + + Chip parameter Chip parameter value + ================= ======================= + WANEC_TailDisplacement 0-896 + WANEC_MaxPlayoutBuffers 0-4678 + WANEC_EnableExtToneDetection TRUE | FALSE + WANEC_EnableAcousticEcho TRUE | FALSE + + \param number_of_custom_params - (optional) number of structures in custom_params[]. Minimum value is 1, maximum is 4, + if any other value the custom_params[] will be ignored. + \return SANG_STATUS_SUCCESS: success, or error status */ -sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name) +sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name, wan_custom_param_t custom_params[], unsigned int number_of_custom_params) { - sangoma_status_t rc; - wan_custom_param_t custom_parms; + sangoma_status_t rc = SANG_STATUS_SUCCESS; wanec_api_config_t config; memset(&config, 0x00, sizeof(config)); - memset(&custom_parms, 0x0, sizeof(custom_parms)); -#if 1 - /* enable acoustic echo cancellation by default */ - strcpy( custom_parms.name, "WANEC_EnableAcousticEcho" ); - strcpy( custom_parms.sValue, "TRUE" ); - - config.conf.param_no = 1; - config.conf.params = &custom_parms; -#endif + if (number_of_custom_params >= 1 && number_of_custom_params <= 4) { - /* Load firmware on EC chip */ + wan_custom_param_t *custom_parms_ptr; + unsigned int i, custom_params_memory_size; + + custom_params_memory_size = sizeof(wan_custom_param_t) * number_of_custom_params; + + /* Do NOT change memory at custom_params[] (it belongs to the caller). + * Instead allocate temporary buffer, and use information in custom_params[] + * for proper initialization the temproary buffer and + * and send if down to API driver. */ + custom_parms_ptr = malloc(custom_params_memory_size); + if (!custom_parms_ptr) { + return SANG_STATUS_FAILED_ALLOCATE_MEMORY; + } + + memset(custom_parms_ptr, 0x00, custom_params_memory_size); + + for (i = 0; i < number_of_custom_params; i++) { + + strcpy( custom_parms_ptr[i].name, custom_params[i].name ); + + if (sangoma_hwec_is_numeric_parameter(custom_params[i].name)) { + custom_parms_ptr[i].dValue = atoi(custom_params[i].sValue); + } else { + strcpy(custom_parms_ptr[i].sValue, custom_params[i].sValue); + } + } /* for() */ + + config.conf.param_no = number_of_custom_params; + config.conf.params = custom_parms_ptr; + + }/* if() */ + + /* Load firmware on EC chip AND apply configuration, if any. */ rc = wanec_api_config( device_name, libsng_hwec_verbosity_level, &config ); - if( rc ) { - return rc; + + if (config.conf.params) { + free(config.conf.params); } - HWEC_CMD_DELAY(); - return SANG_STATUS_SUCCESS; + + return rc; } @@ -137,14 +223,10 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_release(char *device_name) memset(&release, 0, sizeof(wanec_api_release_t)); rc = wanec_api_release( device_name, libsng_hwec_verbosity_level, &release ); - if( rc ) { - return rc; - } - HWEC_CMD_DELAY(); - return SANG_STATUS_SUCCESS; + + return rc; } - /*! Modify channel operation mode. */ @@ -167,11 +249,8 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_operation_mode(char *device_na WANEC_API_OPMODE_SPEECH_RECOGNITION. */ rc = wanec_api_opmode(device_name, libsng_hwec_verbosity_level, &opmode); - if( rc ) { - return rc; - } - HWEC_CMD_DELAY(); - return SANG_STATUS_SUCCESS; + + return rc; } /*! @@ -229,7 +308,7 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_power_off(char *device_name, This command is recommened for fast enabling of Echo Cancellation. Note 1: Chip must be configured and in POWER ON state for echo Chancellation to take place. - Note 2: sangoma_tdm_enable_hwec() function can be use to achive + Note 2: sangoma_tdm_enable_hwec() function can be used to achive the same funcitnality based on file descriptor versus channel map. @@ -275,10 +354,17 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_disable(char *device_name, unsigned i } /*! - \fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameters(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map) + \fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameter(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map) \brief Modify channel configuration parameters. - This is list of Echo Cancellation channel parameters: + + \param device_name Sangoma API device name. + Windows: wanpipe1_if1, wanpipe2_if1... + Linux: wanpipe1, wanpipe2... + + \param parameter Echo Cancellation channel parameter + + This channel parameters are listed under "Channel parameter": Channel parameter Channel parameter value ================= ======================= @@ -301,33 +387,30 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_disable(char *device_name, unsigned i WANEC_DoubleTalkBehavior DT_BEH_NORMAL DT_BEH_LESS_AGGRESSIVE + \param parameter_value channel parameter value, listed under "Channel parameter value" + \param fe_chan_map Bitmap of channels (timeslots for Digital, lines for Analog) where the call will take effect. \return SANG_STATUS_SUCCESS: success, or error status */ -sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameters(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map) +sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameter(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map) { sangoma_status_t rc; wanec_api_modify_t channelModify; - wan_custom_param_t aParms; + wan_custom_param_t custom_param; memset(&channelModify, 0x00, sizeof(channelModify)); - memset(&aParms, 0x00, sizeof(aParms)); + + sangoma_hwec_initialize_custom_parameter_structure(&custom_param, parameter, parameter_value); channelModify.fe_chan_map = channel_map; channelModify.conf.param_no = 1; - channelModify.conf.params = &aParms; - - strcpy( aParms.name, parameter); - strcpy( aParms.sValue, parameter_value); + channelModify.conf.params = &custom_param; rc = wanec_api_modify( device_name, libsng_hwec_verbosity_level, &channelModify ); - if( rc ){ - return rc; - } - HWEC_CMD_DELAY(); - return SANG_STATUS_SUCCESS; + + return rc; } /*! @@ -366,11 +449,8 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_tone_detection(char *device_na tone.type_map = WAN_EC_TONE_PRESENT | WAN_EC_TONE_STOP; rc = wanec_api_tone( device_name, libsng_hwec_verbosity_level, &tone ); - if( rc ) { - return rc; - } - HWEC_CMD_DELAY(); - return SANG_STATUS_SUCCESS; + + return rc; } /*! @@ -401,11 +481,8 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_print_statistics(char *device_name, i stats.reset = 0; /* do not reset */ rc = wanec_api_stats( device_name, libsng_hwec_verbosity_level, &stats ); - if( rc ) { - return rc; - } - HWEC_CMD_DELAY(); - return SANG_STATUS_SUCCESS; + + return rc; } /*! @@ -443,7 +520,6 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_audio_buffer_load(char *device_name, *out_buffer_id = bufferload.buffer_id; - HWEC_CMD_DELAY(); return SANG_STATUS_SUCCESS; } @@ -468,11 +544,8 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_audio_buffer_unload(char *device_name bufferunload.buffer_id = (unsigned int)in_buffer_id; rc = wanec_api_buffer_unload( device_name, libsng_hwec_verbosity_level, &bufferunload); - if( rc ) { - return rc; - } - HWEC_CMD_DELAY(); - return SANG_STATUS_SUCCESS; + + return rc; } /*! @@ -518,18 +591,17 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_audio_buffer_playout(char *device_nam playout.duration = (duration) ? duration : 5000; /* default is 5s */ rc = wanec_api_playout( device_name, libsng_hwec_verbosity_level, &playout); - if( rc ) { - return rc; - } - HWEC_CMD_DELAY(); - return SANG_STATUS_SUCCESS; + + return rc; } /*! \fn void _LIBSNG_CALL sangoma_hwec_config_verbosity(int verbosity_level) - \brief Set Verbosity level of EC API. The level controls amount of data - printed to stdout and wanpipelog.txt for diagnostic purposes. + \brief Set Verbosity level of EC API Driver and Library. + The level controls amount of data + printed to stdout and to wanpipelog.txt (Windows) or + /var/log/messages (Linux) for diagnostic purposes. \param verbosity_level Valid values are from 0 to 3. @@ -539,6 +611,7 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_verbosity(int verbosity_level) { if (verbosity_level >= 0 || verbosity_level <= 3) { libsng_hwec_verbosity_level = verbosity_level; + wanec_api_set_lib_verbosity(verbosity_level); return SANG_STATUS_SUCCESS; } return SANG_STATUS_INVALID_PARAMETER; diff --git a/api/libsangoma/.svn/text-base/sources.svn-base b/api/libsangoma/.svn/text-base/sources.svn-base index d89d9b4..64cfad1 100644 --- a/api/libsangoma/.svn/text-base/sources.svn-base +++ b/api/libsangoma/.svn/text-base/sources.svn-base @@ -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);\ diff --git a/api/libsangoma/docs/.svn/entries b/api/libsangoma/docs/.svn/entries index 1ce9b6f..c9dc190 100644 --- a/api/libsangoma/docs/.svn/entries +++ b/api/libsangoma/docs/.svn/entries @@ -1,7 +1,7 @@ 8 dir -273 +293 https://www.sangomapbx.com/svn/libsangoma/trunk/docs https://www.sangomapbx.com/svn/libsangoma diff --git a/api/libsangoma/docs/doxygen/.svn/entries b/api/libsangoma/docs/doxygen/.svn/entries index 588b0c6..146226d 100644 --- a/api/libsangoma/docs/doxygen/.svn/entries +++ b/api/libsangoma/docs/doxygen/.svn/entries @@ -1,7 +1,7 @@ 8 dir -273 +293 https://www.sangomapbx.com/svn/libsangoma/trunk/docs/doxygen https://www.sangomapbx.com/svn/libsangoma diff --git a/api/libsangoma/examples/.svn/entries b/api/libsangoma/examples/.svn/entries index 972034b..6721903 100644 --- a/api/libsangoma/examples/.svn/entries +++ b/api/libsangoma/examples/.svn/entries @@ -1,7 +1,7 @@ 8 dir -273 +293 https://www.sangomapbx.com/svn/libsangoma/trunk/examples https://www.sangomapbx.com/svn/libsangoma diff --git a/api/libsangoma/examples/hptdm_api/.svn/entries b/api/libsangoma/examples/hptdm_api/.svn/entries index 68f5677..20ee355 100644 --- a/api/libsangoma/examples/hptdm_api/.svn/entries +++ b/api/libsangoma/examples/hptdm_api/.svn/entries @@ -1,7 +1,7 @@ 8 dir -273 +293 https://www.sangomapbx.com/svn/libsangoma/trunk/examples/hptdm_api https://www.sangomapbx.com/svn/libsangoma diff --git a/api/libsangoma/examples/hptdm_api/docs/.svn/entries b/api/libsangoma/examples/hptdm_api/docs/.svn/entries index 4e6c49a..9b3ce02 100644 --- a/api/libsangoma/examples/hptdm_api/docs/.svn/entries +++ b/api/libsangoma/examples/hptdm_api/docs/.svn/entries @@ -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 diff --git a/api/libsangoma/examples/hptdm_api/docs/doxygen/.svn/entries b/api/libsangoma/examples/hptdm_api/docs/doxygen/.svn/entries index 220257f..7137c3f 100644 --- a/api/libsangoma/examples/hptdm_api/docs/doxygen/.svn/entries +++ b/api/libsangoma/examples/hptdm_api/docs/doxygen/.svn/entries @@ -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 diff --git a/api/libsangoma/examples/priserver/.svn/entries b/api/libsangoma/examples/priserver/.svn/entries index d13c9dc..eab12d2 100644 --- a/api/libsangoma/examples/priserver/.svn/entries +++ b/api/libsangoma/examples/priserver/.svn/entries @@ -1,7 +1,7 @@ 8 dir -273 +293 https://www.sangomapbx.com/svn/libsangoma/trunk/examples/priserver https://www.sangomapbx.com/svn/libsangoma diff --git a/api/libsangoma/libsangoma-pvt.h b/api/libsangoma/libsangoma-pvt.h index 532ef1f..3a76083 100644 --- a/api/libsangoma/libsangoma-pvt.h +++ b/api/libsangoma/libsangoma-pvt.h @@ -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; diff --git a/api/libsangoma/libsangoma.c b/api/libsangoma/libsangoma.c index b4cd35f..aebe5c7 100644 --- a/api/libsangoma/libsangoma.c +++ b/api/libsangoma/libsangoma.c @@ -307,12 +307,11 @@ sangoma_status_t _LIBSNG_CALL sangoma_cdev_ctrl_cmd(sng_fd_t fd, wanpipe_tdm_api return handle_device_ioctl_result(bIoResult, __FUNCTION__); } -static sangoma_status_t init_sangoma_event_object(sangoma_wait_obj_t *sng_wait_obj, int flags_in, sng_fd_t fd) +static sangoma_status_t init_sangoma_event_object(sangoma_wait_obj_t *sng_wait_obj, sng_fd_t fd) { - int event_index = -1; wanpipe_tdm_api_cmd_t tdm_api_cmd; sangoma_status_t sng_status; - char event_name[200], tmp_event_name[200]; + char event_name[200]; memset(&tdm_api_cmd, 0x00, sizeof(tdm_api_cmd)); @@ -325,40 +324,18 @@ static sangoma_status_t init_sangoma_event_object(sangoma_wait_obj_t *sng_wait_o DBG_EVNT("%s(): interface name: %s\n", __FUNCTION__, tdm_api_cmd.data); - if(flags_in & POLLIN){ - event_index = LIBSNG_EVENT_INDEX_POLLIN; - /* Form the Event Name from Interface Name and Event Type (i.e. wanpipe1_if1_pollin). */ - _snprintf(tmp_event_name, sizeof(tmp_event_name), "%s_pollin", tdm_api_cmd.data); - } - - if(flags_in & POLLOUT){ - event_index = LIBSNG_EVENT_INDEX_POLLOUT; - /* Form the Event Name from Interface Name and Event Type (i.e. wanpipe1_if1_pollout). */ - _snprintf(tmp_event_name, sizeof(tmp_event_name), "%s_pollout", tdm_api_cmd.data); - } - - if(flags_in & POLLPRI){ - event_index = LIBSNG_EVENT_INDEX_POLLPRI; - /* Form the Event Name from Interface Name and Event Type (i.e. wanpipe1_if1_pollpri). */ - _snprintf(tmp_event_name, sizeof(tmp_event_name), "%s_pollpri", tdm_api_cmd.data); - } - - if(event_index == -1){ - /* invalid 'flags_in', this should be an assert */ - return SANG_STATUS_GENERAL_ERROR; - } - /* 1. The Sangoma Device Driver creates Notification Events in "\\BaseNamedObjects\\Global\\" * when first CreateFile() was called by a process. That means the Events will inherit * the security attributes of the calling process, so the calling process will have * the permissions to open the Events by calling OpenEvent(). Since Events are created * "Global" subdirectory, the calling process does NOT need Administrator priveleges. + * The example name of the signaling object is: \\BaseNamedObjects\\Global\\wanpipe1_if1_signal. * 2. The Events are deleted when the last HANDLE for a device is closed by CloseHandle() * or automatically by the system when calling process exits. */ - _snprintf(event_name, sizeof(event_name), "Global\\%s", tmp_event_name); + _snprintf(event_name, sizeof(event_name), "Global\\%s_signal", tdm_api_cmd.data); - sng_wait_obj->sng_event_objects[event_index] = OpenEvent(EVENT_ALL_ACCESS, TRUE, event_name); - if(NULL == sng_wait_obj->sng_event_objects[event_index]){ + sng_wait_obj->signal_object = OpenEvent(EVENT_ALL_ACCESS, TRUE, event_name); + if(NULL == sng_wait_obj->signal_object){ /* error */ LibSangomaDecodeLastError(__FUNCTION__); return SANG_STATUS_GENERAL_ERROR; @@ -376,7 +353,7 @@ static sangoma_status_t sangoma_wait_obj_poll(sangoma_wait_obj_t *sangoma_wait_o *flags_out = 0; - memset(&api_poll, 0x00, sizeof(API_POLL_STRUCT)); + memset(&api_poll, 0x00, sizeof(api_poll)); api_poll.user_flags_bitmap = flags_in; /* This call is non-blocking - it will return immediatly. */ @@ -399,13 +376,20 @@ static sangoma_status_t sangoma_wait_obj_poll(sangoma_wait_obj_t *sangoma_wait_o return err; } -static int check_number_of_wait_objects(uint32_t number_of_objects, const char *caller_function, int lineno) +static int sangoma_check_number_of_wait_objects(uint32_t number_of_objects) { - if(number_of_objects >= MAXIMUM_WAIT_OBJECTS){ - DBG_ERR("Caller: %s(): Line: %d: 'number_of_objects': %d is greater than the Maximum of: %d\n", - caller_function, lineno, number_of_objects, MAXIMUM_WAIT_OBJECTS); + if(number_of_objects > MAXIMUM_WAIT_OBJECTS){ + DBG_ERR("'number_of_objects': %d is greater than the Maximum of: %d\n", + number_of_objects, MAXIMUM_WAIT_OBJECTS); return 1; } + + if(number_of_objects < 1){ + DBG_ERR("'number_of_objects': %d is less than the Minimum of: 1\n", + number_of_objects); + return 1; + } + return 0; } @@ -425,42 +409,36 @@ static sangoma_status_t get_out_flags(IN sangoma_wait_obj_t *sng_wait_objects[], sangoma_wait_obj_t *sangoma_wait_object = sng_wait_objects[i]; + if (!sangoma_wait_object->signal_object) { + return SANG_STATUS_DEV_INIT_INCOMPLETE; + } + if (!SANGOMA_OBJ_HAS_DEVICE(sangoma_wait_object)) { /* This object does not has a device, but, may have been signaled via sangoma_wait_obj_signal() * test if the object is signaled, if it is, set SANG_WAIT_OBJ_IS_SIGNALED */ - if((i == first_signaled_obj_index) || (WaitForSingleObject(sangoma_wait_object->generic_event_object, 0) == WAIT_OBJECT_0)) { - /* !+! jpboily : Since WaitForMultipleObjects cleared the status - * of the first signaled object, we make sure that the out_flag - * for this object is set */ + if((i == first_signaled_obj_index) || /* !+! jpboily : Since WaitForMultipleObjects cleared the status + * of the FIRST signaled object, we make sure that the out_flag + * for this object is set. + * !+! davidr: Status of all OTHER objects will be checked + * by WaitForSingleObject(). */ + (WaitForSingleObject(sangoma_wait_object->signal_object, 0) == WAIT_OBJECT_0)) { out_flags[i] |= SANG_WAIT_OBJ_IS_SIGNALED; } continue; } - for(j = 0; j < LIBSNG_NUMBER_OF_EVENT_OBJECTS; j++){ + if(sangoma_wait_obj_poll(sangoma_wait_object, in_flags[i], &out_flags[i])){ + return SANG_STATUS_GENERAL_ERROR; + } - if(!sangoma_wait_object->sng_event_objects[j]) { - continue; + if (out_flags[i] & in_flags[i]) { + if (at_least_one_poll_set_flags_out) { + *at_least_one_poll_set_flags_out = TRUE; } + } - if(sangoma_wait_obj_poll(sangoma_wait_object, in_flags[i], &out_flags[i])){ - return SANG_STATUS_GENERAL_ERROR; - } - - if( out_flags[i] & in_flags[i] ){ - if(at_least_one_poll_set_flags_out){ - *at_least_one_poll_set_flags_out = TRUE; - } - } -#if 0 - /* Check if a device-related object was signalled, if it is, set SANG_WAIT_OBJ_IS_SIGNALED. */ - if (WaitForSingleObject(sangoma_wait_object->sng_event_objects[j], 0) == WAIT_OBJECT_0) { - out_flags[i] |= SANG_WAIT_OBJ_IS_SIGNALED; - } -#endif - }/* for(j = 0; j < LIBSNG_NUMBER_OF_EVENT_OBJECTS; j++) */ }/* for(i = 0; i < number_of_sangoma_wait_objects; i++) */ return SANG_STATUS_SUCCESS; @@ -1255,7 +1233,7 @@ sangoma_status_t _LIBSNG_CALL sangoma_wait_obj_create(sangoma_wait_obj_t **sango sangoma_wait_obj_t *sng_wait_obj = NULL; if (!sangoma_wait_object) { - return SANG_STATUS_INVALID_DEVICE; + return SANG_STATUS_INVALID_PARAMETER; } *sangoma_wait_object = NULL; sng_wait_obj = malloc(sizeof(**sangoma_wait_object)); @@ -1271,40 +1249,19 @@ sangoma_status_t _LIBSNG_CALL sangoma_wait_obj_create(sangoma_wait_obj_t **sango sng_wait_obj->object_type = object_type; #if defined(__WINDOWS__) - DBG_INIT("%s(): sng_wait_obj ptr: 0x%p\n", __FUNCTION__, sng_wait_obj); - DBG_INIT("%s(): fd: 0x%X, object_type: %s\n", __FUNCTION__, fd, DECODE_SANGOMA_WAIT_OBJECT_TYPE(object_type)); - DBG_INIT("%s(): sizeof(**sangoma_wait_object): %d\n", __FUNCTION__, sizeof(**sangoma_wait_object)); - - if (SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) { - sng_wait_obj->generic_event_object = CreateEvent( NULL, FALSE, FALSE, NULL); - if(!sng_wait_obj->generic_event_object){ + if (!SANGOMA_OBJ_HAS_DEVICE(sng_wait_obj)) { + sng_wait_obj->signal_object = CreateEvent(NULL, FALSE, FALSE, NULL); + if(!sng_wait_obj->signal_object){ err = SANG_STATUS_GENERAL_ERROR; goto failed; } + err = SANG_STATUS_SUCCESS; + } else { + err = init_sangoma_event_object(sng_wait_obj, fd); + if(SANG_STATUS_SUCCESS != err){ + goto failed; + } } - - if(SANGOMA_GENERIC_WAIT_OBJ == object_type){ - /* everything is done for the generic wait object */ - *sangoma_wait_object = sng_wait_obj; - return SANG_STATUS_SUCCESS; - } - - err = init_sangoma_event_object(sng_wait_obj, POLLIN, fd); - if(SANG_STATUS_SUCCESS != err){ - goto failed; - } - - err = init_sangoma_event_object(sng_wait_obj, POLLOUT, fd); - if(SANG_STATUS_SUCCESS != err){ - goto failed; - } - - err = init_sangoma_event_object(sng_wait_obj, POLLPRI, fd); - if(SANG_STATUS_SUCCESS != err) { - goto failed; - } - - DBG_INIT("%s(): returning: %d", __FUNCTION__, err); #else int filedes[2]; if (SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) { @@ -1338,9 +1295,6 @@ failed: sangoma_status_t _LIBSNG_CALL sangoma_wait_obj_delete(sangoma_wait_obj_t **sangoma_wait_object) { sangoma_wait_obj_t *sng_wait_obj = *sangoma_wait_object; -#if defined(__WINDOWS__) - int index = 0; -#endif if(sng_wait_obj->init_flag != LIBSNG_MAGIC_NO){ /* error. object was not initialized by sangoma_wait_obj_init() */ @@ -1348,13 +1302,9 @@ sangoma_status_t _LIBSNG_CALL sangoma_wait_obj_delete(sangoma_wait_obj_t **sango } #if defined(__WINDOWS__) - if (SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) { - sangoma_close(&sng_wait_obj->generic_event_object); - } - if (SANGOMA_OBJ_HAS_DEVICE(sng_wait_obj)) { - for(index = 0; index < LIBSNG_NUMBER_OF_EVENT_OBJECTS; index++){ - sangoma_close(&sng_wait_obj->sng_event_objects[index]); - } + if (sng_wait_obj->signal_object && + sng_wait_obj->signal_object != INVALID_HANDLE_VALUE) { + sangoma_close(&sng_wait_obj->signal_object); } #else if (SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) { @@ -1380,13 +1330,12 @@ int _LIBSNG_CALL sangoma_wait_obj_signal(sangoma_wait_obj_t *sng_wait_obj) if (!SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) { /* even when Windows objects are always signalable for the sake of providing * a consistent interface to the user we downgrade the capabilities of Windows - * objects unless the sangoma wait object is explicitly initialized as signalable - * */ + * objects unless the sangoma wait object is explicitly initialized as signalable */ return SANG_STATUS_INVALID_DEVICE; } #if defined(__WINDOWS__) - if(sng_wait_obj->generic_event_object){ - if (!SetEvent(sng_wait_obj->generic_event_object)) { + if(sng_wait_obj->signal_object){ + if (!SetEvent(sng_wait_obj->signal_object)) { return SANG_STATUS_GENERAL_ERROR; } } @@ -1449,58 +1398,44 @@ sangoma_status_t _LIBSNG_CALL sangoma_waitfor_many(sangoma_wait_obj_t *sng_wait_ { #if defined(__WINDOWS__) HANDLE hEvents[MAXIMUM_WAIT_OBJECTS]; - uint32_t uiMapEventIndexToWaitObjectIndex[MAXIMUM_WAIT_OBJECTS]; DWORD dwResult; - int at_least_one_poll_set_flags_out, number_of_internal_signaling_objects, err; + int at_least_one_poll_set_flags_out, err; + sangoma_wait_obj_t *sangoma_wait_object; #endif uint32_t i = 0, j = 0; memset(out_flags, 0x00, number_of_sangoma_wait_objects * sizeof(out_flags[0])); #if defined(__WINDOWS__) - /* This loop will calculate 'number_of_internal_signaling_objects' and will initialize 'hEvents' - * based on 'number_of_sangoma_wait_objects' and 'in_flags'. */ - number_of_internal_signaling_objects = 0; - for(i = 0; i < number_of_sangoma_wait_objects; i++){ - sangoma_wait_obj_t *sangoma_wait_object = sng_wait_objects[i]; - /* if SANGOMA_OBJ_IS_SIGNALABLE add the generic_event_object.hEvent to the hEvents */ - if(sangoma_wait_object->generic_event_object){ - if(check_number_of_wait_objects(number_of_internal_signaling_objects, __FUNCTION__, __LINE__)){ - return SANG_STATUS_NO_FREE_BUFFERS; - } - hEvents[number_of_internal_signaling_objects] = sangoma_wait_object->generic_event_object; - uiMapEventIndexToWaitObjectIndex[number_of_internal_signaling_objects] = i; - number_of_internal_signaling_objects++; - } - - for(j = 0; j < LIBSNG_NUMBER_OF_EVENT_OBJECTS; j++){ - if(sangoma_wait_object->sng_event_objects[j]){ - if( ((j == LIBSNG_EVENT_INDEX_POLLIN) && (in_flags[i] & POLLIN)) || - ((j == LIBSNG_EVENT_INDEX_POLLOUT) && (in_flags[i] & POLLOUT)) || - ((j == LIBSNG_EVENT_INDEX_POLLPRI) && (in_flags[i] & POLLPRI)) ){ - - if(check_number_of_wait_objects(number_of_internal_signaling_objects, __FUNCTION__, __LINE__)){ - return SANG_STATUS_NO_FREE_BUFFERS; - } - hEvents[number_of_internal_signaling_objects] = sangoma_wait_object->sng_event_objects[j]; - uiMapEventIndexToWaitObjectIndex[number_of_internal_signaling_objects] = i; - number_of_internal_signaling_objects++; - } - }/* if () */ - }/* for() */ - }/* for() */ - - if(number_of_internal_signaling_objects < 1){ - DBG_ERR("'number_of_internal_signaling_objects': %d is less than the Minimum of: 1!\n", - number_of_internal_signaling_objects); + if(sangoma_check_number_of_wait_objects(number_of_sangoma_wait_objects)){ /* error - most likely the user did not initialize sng_wait_objects[] */ return SANG_STATUS_INVALID_PARAMETER; } + for(i = 0; i < MAXIMUM_WAIT_OBJECTS; i++){ + hEvents[i] = INVALID_HANDLE_VALUE; + } + + /* This loop will initialize 'hEvents[]' based on + * 'number_of_sangoma_wait_objects' and sng_wait_objects[]. */ + for(i = 0; i < number_of_sangoma_wait_objects; i++){ + + sangoma_wait_object = sng_wait_objects[i]; + + if(LIBSNG_MAGIC_NO != sangoma_wait_object->init_flag){ + return SANG_STATUS_DEV_INIT_INCOMPLETE; + } + + if(sangoma_wait_object->signal_object){ + hEvents[i] = sangoma_wait_object->signal_object; + } + + }/* for() */ + at_least_one_poll_set_flags_out = FALSE; /* It is important to get 'out flags' BEFORE the WaitForMultipleObjects() - * because it allows to keep API driver's transmit queue full. */ + * because it allows to keep API driver's TRANSMIT queue full. */ err = get_out_flags(sng_wait_objects, INVALID_INDEX, in_flags, out_flags, number_of_sangoma_wait_objects, &at_least_one_poll_set_flags_out); if(SANG_ERROR(err)){ return err; @@ -1511,19 +1446,19 @@ sangoma_status_t _LIBSNG_CALL sangoma_waitfor_many(sangoma_wait_obj_t *sng_wait_ } /* wait untill at least one of the events is signaled OR a 'system_wait_timeout' occured */ - dwResult = WaitForMultipleObjects(number_of_internal_signaling_objects, &hEvents[0], FALSE, system_wait_timeout); + dwResult = WaitForMultipleObjects(number_of_sangoma_wait_objects, &hEvents[0], FALSE, system_wait_timeout); if (WAIT_TIMEOUT == dwResult){ return SANG_STATUS_APIPOLL_TIMEOUT; } - if( dwResult >= (DWORD)number_of_internal_signaling_objects ) { + if( dwResult >= (DWORD)number_of_sangoma_wait_objects ) { return SANG_STATUS_GENERAL_ERROR; } /* WaitForMultipleObjects() was waken by a Sangoma or by a non-Sangoma wait object. */ err = get_out_flags(sng_wait_objects, - uiMapEventIndexToWaitObjectIndex[dwResult],/* This is the index of first signaled object in - * the original sng_wait_objects[] array, not in hEvents[] array. */ + dwResult, /* Array index of the signalled object with the smallest index + * value of all the signalled objects, from array. */ in_flags, out_flags, number_of_sangoma_wait_objects, NULL); if(SANG_ERROR(err)){ return err; @@ -1681,14 +1616,25 @@ int _LIBSNG_CALL sangoma_span_chan_fromif(char *interface_name, int *span, int * int ret = 0; char data[FNAME_LEN]; + /* Windows: Accept WANPIPEx_IFy or wanpipex_ify + * where x is the span and y is the chan. */ + strncpy(data, interface_name, FNAME_LEN); if ((data[0])) { for (p = data; *p; p++) { +#if defined(__WINDOWS__) + if (sp && (*p == 'F'||*p == 'f')) { +#else if (sp && *p == 'c') { +#endif *p = '\0'; ch = (p + 1); break; +#if defined(__WINDOWS__) + } else if (*p == 'E'||*p == 'e') { +#else } else if (*p == 's') { +#endif sp = (p + 1); } } @@ -1791,6 +1737,7 @@ int _LIBSNG_CALL sangoma_get_open_cnt(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_OPEN_CNT; err=sangoma_cmd_exec(fd,tdm_api); @@ -1897,8 +1844,11 @@ int _LIBSNG_CALL sangoma_readmsg(sng_fd_t fd, void *hdrbuf, int hdrlen, void *da rx_hdr->operation_status = SANG_STATUS_BUFFER_TOO_SMALL; } break; + case SANG_STATUS_NO_DATA_AVAILABLE: + /* Note that SANG_STATUS_NO_DATA_AVAILABLE is NOT an error becase + * read() is non-blocking and can be called at any time (by some polling code)*/ + return 1; /* return positive value to indicate success, user must check 'rx_hdr->operation_status' */ default: - /* note that SANG_STATUS_NO_DATA_AVAILABLE is NOT an error! */ if(libsng_dbg_level)DBG_ERR("Operation Status: %s(%d)\n", SDLA_DECODE_SANG_STATUS(rx_hdr->operation_status), rx_hdr->operation_status); return -5; @@ -2039,6 +1989,7 @@ int _LIBSNG_CALL sangoma_get_full_cfg(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_FULL_CFG; err=sangoma_cmd_exec(fd,tdm_api); @@ -2092,6 +2043,7 @@ int _LIBSNG_CALL sangoma_get_full_cfg(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_tdm_set_codec(sng_fd_t fd, wanpipe_api_t *tdm_api, int codec) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_CODEC; tdm_api->wp_cmd.tdm_codec = codec; return sangoma_cmd_exec(fd,tdm_api); @@ -2114,6 +2066,7 @@ int _LIBSNG_CALL sangoma_tdm_get_codec(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_CODEC; err=sangoma_cmd_exec(fd,tdm_api); @@ -2134,6 +2087,7 @@ int _LIBSNG_CALL sangoma_tdm_get_codec(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_tdm_set_usr_period(sng_fd_t fd, wanpipe_api_t *tdm_api, int period) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_USR_PERIOD; tdm_api->wp_cmd.usr_period = period; return sangoma_cmd_exec(fd,tdm_api); @@ -2151,6 +2105,7 @@ int _LIBSNG_CALL sangoma_tdm_get_usr_period(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_USR_PERIOD; err=sangoma_cmd_exec(fd,tdm_api); @@ -2172,6 +2127,7 @@ int _LIBSNG_CALL sangoma_get_hw_coding(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_CODING; err=sangoma_cmd_exec(fd,tdm_api); if (err){ @@ -2192,6 +2148,7 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_dtmf(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_DTMF; err=sangoma_cmd_exec(fd,tdm_api); if (err){ @@ -2201,9 +2158,9 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_dtmf(sng_fd_t fd, wanpipe_api_t *tdm_api) } /*======================================================== - * GET Current User Hardware EC Enabled/Disabled + * GET status of echo canceler chip. * - * Will return true if HW EC is enabled + * Will return true if HW EC is available */ int _LIBSNG_CALL sangoma_tdm_get_hw_ec(sng_fd_t fd, wanpipe_api_t *tdm_api) @@ -2211,6 +2168,7 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_ec(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_EC; err=sangoma_cmd_exec(fd,tdm_api); if (err){ @@ -2220,6 +2178,31 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_ec(sng_fd_t fd, wanpipe_api_t *tdm_api) } #endif + +#ifdef WP_API_FEATURE_EC_CHAN_STAT +/*======================================================== + * GET status of the echo canceler for current channel. + * + * Will return true if HW EC is enabled + */ + +int _LIBSNG_CALL sangoma_tdm_get_hwec_chan_status(sng_fd_t fd, wanpipe_api_t *tdm_api) +{ + int err; + + WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); + tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_EC_CHAN; + err=sangoma_cmd_exec(fd,tdm_api); + if (err){ + return err; + } + return tdm_api->wp_cmd.hw_ec; +} + +#endif + + /*======================================================== * GET Current User MTU/MRU values in bytes. * @@ -2231,6 +2214,7 @@ int _LIBSNG_CALL sangoma_tdm_get_usr_mtu_mru(sng_fd_t fd, wanpipe_api_t *tdm_api int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_USR_MTU_MRU; err=sangoma_cmd_exec(fd,tdm_api); @@ -2250,6 +2234,7 @@ int _LIBSNG_CALL sangoma_tdm_get_usr_mtu_mru(sng_fd_t fd, wanpipe_api_t *tdm_api int _LIBSNG_CALL sangoma_tdm_set_power_level(sng_fd_t fd, wanpipe_api_t *tdm_api, int power) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_POWER_LEVEL; tdm_api->wp_cmd.power_level = power; return sangoma_cmd_exec(fd,tdm_api); @@ -2266,6 +2251,7 @@ int _LIBSNG_CALL sangoma_tdm_get_power_level(sng_fd_t fd, wanpipe_api_t *tdm_api int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_POWER_LEVEL; err=sangoma_cmd_exec(fd,tdm_api); @@ -2279,6 +2265,7 @@ int _LIBSNG_CALL sangoma_tdm_get_power_level(sng_fd_t fd, wanpipe_api_t *tdm_api int _LIBSNG_CALL sangoma_flush_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_FLUSH_BUFFERS; return sangoma_cmd_exec(fd,tdm_api); } @@ -2286,6 +2273,7 @@ int _LIBSNG_CALL sangoma_flush_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_flush_rx_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_FLUSH_RX_BUFFERS; return sangoma_cmd_exec(fd,tdm_api); } @@ -2293,6 +2281,7 @@ int _LIBSNG_CALL sangoma_flush_rx_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_flush_tx_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_FLUSH_TX_BUFFERS; return sangoma_cmd_exec(fd,tdm_api); } @@ -2300,6 +2289,7 @@ int _LIBSNG_CALL sangoma_flush_tx_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_flush_event_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_FLUSH_EVENT_BUFFERS; return sangoma_cmd_exec(fd,tdm_api); } @@ -2307,6 +2297,7 @@ int _LIBSNG_CALL sangoma_flush_event_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_tdm_enable_rbs_events(sng_fd_t fd, wanpipe_api_t *tdm_api, int poll_in_sec) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_ENABLE_RBS_EVENTS; tdm_api->wp_cmd.rbs_poll = poll_in_sec; return sangoma_cmd_exec(fd,tdm_api); @@ -2315,6 +2306,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_rbs_events(sng_fd_t fd, wanpipe_api_t *tdm_a int _LIBSNG_CALL sangoma_tdm_disable_rbs_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_DISABLE_RBS_EVENTS; return sangoma_cmd_exec(fd,tdm_api); } @@ -2322,6 +2314,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_rbs_events(sng_fd_t fd, wanpipe_api_t *tdm_ int _LIBSNG_CALL sangoma_tdm_write_rbs(sng_fd_t fd, wanpipe_api_t *tdm_api, int channel, unsigned char rbs) { WANPIPE_API_INIT_CHAN(tdm_api, channel); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_WRITE_RBS_BITS; tdm_api->wp_cmd.rbs_tx_bits=rbs; return sangoma_cmd_exec(fd,tdm_api); @@ -2331,6 +2324,7 @@ int _LIBSNG_CALL sangoma_tdm_read_rbs(sng_fd_t fd, wanpipe_api_t *tdm_api, int c { int err; WANPIPE_API_INIT_CHAN(tdm_api, channel); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_READ_RBS_BITS; tdm_api->wp_cmd.rbs_tx_bits=0; @@ -2341,7 +2335,29 @@ int _LIBSNG_CALL sangoma_tdm_read_rbs(sng_fd_t fd, wanpipe_api_t *tdm_api, int c *rbs=(unsigned char)tdm_api->wp_cmd.rbs_rx_bits; return 0; -} +} + +#ifdef WP_API_FEATURE_BUFFER_MULT + +int _LIBSNG_CALL sangoma_tdm_set_buffer_multiplier(sng_fd_t fd, wanpipe_api_t *tdm_api, unsigned int multiplier) +{ + + int err; + WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); + tdm_api->wp_cmd.cmd = WP_API_CMD_BUFFER_MULTIPLIER; + *((unsigned int*)&tdm_api->wp_cmd.data[0]) = multiplier; + + err=sangoma_cmd_exec(fd,tdm_api); + if (err){ + return err; + } + + return 0; +} + +#endif + int _LIBSNG_CALL sangoma_read_event(sng_fd_t fd, wanpipe_api_t *tdm_api) { @@ -2351,6 +2367,7 @@ int _LIBSNG_CALL sangoma_read_event(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_READ_EVENT; err=sangoma_cmd_exec(fd,tdm_api); @@ -2360,6 +2377,7 @@ int _LIBSNG_CALL sangoma_read_event(sng_fd_t fd, wanpipe_api_t *tdm_api) rx_event = &tdm_api->wp_cmd.event; +#ifdef WP_API_DEPRECATED_FEATURE_READ_CALLBACK_FUNCTIONS /* The use of callbacks here is purely optional and is left here for backward compatibility purposes. By default user @@ -2439,6 +2457,9 @@ int _LIBSNG_CALL sangoma_read_event(sng_fd_t fd, wanpipe_api_t *tdm_api) #endif break; } + +#endif + return 0; #else @@ -2516,6 +2537,7 @@ sangoma_status_t _LIBSNG_CALL sangoma_logger_set_logger_level(sng_fd_t fd, wp_lo int _LIBSNG_CALL sangoma_tdm_enable_fax_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_FAX_DETECT; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2525,6 +2547,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_fax_events(sng_fd_t fd, wanpipe_api_t *tdm_a int _LIBSNG_CALL sangoma_tdm_disable_fax_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_FAX_DETECT; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE; @@ -2535,6 +2558,7 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_fax(sng_fd_t fd, wanpipe_api_t *tdm_api) { int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_FAX_DETECT; err=sangoma_cmd_exec(fd,tdm_api); if (err){ @@ -2548,6 +2572,7 @@ int _LIBSNG_CALL sangoma_tdm_get_hw_fax(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_tdm_enable_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_DTMF; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2557,6 +2582,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_ int _LIBSNG_CALL sangoma_tdm_disable_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_DTMF; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE; @@ -2566,6 +2592,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm int _LIBSNG_CALL sangoma_tdm_enable_rm_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RM_DTMF; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2575,6 +2602,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_rm_dtmf_events(sng_fd_t fd, wanpipe_api_t *t int _LIBSNG_CALL sangoma_tdm_disable_rm_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RM_DTMF; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE; @@ -2584,6 +2612,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_rm_dtmf_events(sng_fd_t fd, wanpipe_api_t * int _LIBSNG_CALL sangoma_tdm_enable_rxhook_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RXHOOK; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2593,6 +2622,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_rxhook_events(sng_fd_t fd, wanpipe_api_t *td int _LIBSNG_CALL sangoma_tdm_disable_rxhook_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RXHOOK; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE; @@ -2602,6 +2632,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_rxhook_events(sng_fd_t fd, wanpipe_api_t *t int _LIBSNG_CALL sangoma_tdm_enable_ring_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2611,6 +2642,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_ring_events(sng_fd_t fd, wanpipe_api_t *tdm_ int _LIBSNG_CALL sangoma_tdm_disable_ring_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE; @@ -2620,6 +2652,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_ring_events(sng_fd_t fd, wanpipe_api_t *tdm int _LIBSNG_CALL sangoma_tdm_enable_ring_detect_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING_DETECT; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2629,6 +2662,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_ring_detect_events(sng_fd_t fd, wanpipe_api_ int _LIBSNG_CALL sangoma_tdm_disable_ring_detect_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING_DETECT; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE; @@ -2638,6 +2672,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_ring_detect_events(sng_fd_t fd, wanpipe_api int _LIBSNG_CALL sangoma_tdm_enable_ring_trip_detect_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING_TRIP_DETECT; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2647,6 +2682,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_ring_trip_detect_events(sng_fd_t fd, wanpipe int _LIBSNG_CALL sangoma_tdm_disable_ring_trip_detect_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING_TRIP_DETECT; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE; @@ -2656,6 +2692,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_ring_trip_detect_events(sng_fd_t fd, wanpip int _LIBSNG_CALL sangoma_tdm_txsig_kewl(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TXSIG_KEWL; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2665,6 +2702,7 @@ int _LIBSNG_CALL sangoma_tdm_txsig_kewl(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_tdm_txsig_start(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TXSIG_START; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2674,6 +2712,7 @@ int _LIBSNG_CALL sangoma_tdm_txsig_start(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_tdm_txsig_onhook(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TXSIG_ONHOOK; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2683,6 +2722,7 @@ int _LIBSNG_CALL sangoma_tdm_txsig_onhook(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_tdm_txsig_offhook(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TXSIG_OFFHOOK; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2692,6 +2732,7 @@ int _LIBSNG_CALL sangoma_tdm_txsig_offhook(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_tdm_enable_tone_events(sng_fd_t fd, wanpipe_api_t *tdm_api, uint16_t tone_id) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TONE; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2702,6 +2743,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_tone_events(sng_fd_t fd, wanpipe_api_t *tdm_ int _LIBSNG_CALL sangoma_tdm_disable_tone_events(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TONE; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE; @@ -2713,6 +2755,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_tone_events(sng_fd_t fd, wanpipe_api_t *tdm int _LIBSNG_CALL sangoma_tdm_enable_hwec(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_ENABLE_HWEC; return sangoma_cmd_exec(fd,tdm_api); } @@ -2720,6 +2763,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_hwec(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_tdm_disable_hwec(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_DISABLE_HWEC; return sangoma_cmd_exec(fd,tdm_api); } @@ -2735,6 +2779,7 @@ int _LIBSNG_CALL sangoma_tdm_get_fe_alarms(sng_fd_t fd, wanpipe_api_t *tdm_api, int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_FE_ALARMS; err=sangoma_cmd_exec(fd,tdm_api); @@ -2753,6 +2798,7 @@ int _LIBSNG_CALL sangoma_get_fe_status(sng_fd_t fd, wanpipe_api_t *tdm_api, unsi int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_FE_STATUS; err = sangoma_cmd_exec(fd, tdm_api); *current_status = tdm_api->wp_cmd.fe_status; @@ -2768,6 +2814,7 @@ int _LIBSNG_CALL sangoma_get_link_status(sng_fd_t fd, wanpipe_api_t *tdm_api, un int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_FE_STATUS; err = sangoma_cmd_exec(fd, tdm_api); *current_status = tdm_api->wp_cmd.fe_status; @@ -2779,6 +2826,7 @@ int _LIBSNG_CALL sangoma_get_link_status(sng_fd_t fd, wanpipe_api_t *tdm_api, un int _LIBSNG_CALL sangoma_set_fe_status(sng_fd_t fd, wanpipe_api_t *tdm_api, unsigned char new_status) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_FE_STATUS; tdm_api->wp_cmd.fe_status = new_status; return sangoma_cmd_exec(fd, tdm_api); @@ -2788,6 +2836,7 @@ int _LIBSNG_CALL sangoma_set_fe_status(sng_fd_t fd, wanpipe_api_t *tdm_api, unsi int _LIBSNG_CALL sangoma_disable_bri_bchan_loopback(sng_fd_t fd, wanpipe_api_t *tdm_api, int channel) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.channel = (unsigned char)channel; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_BRI_CHAN_LOOPBACK; @@ -2798,6 +2847,7 @@ int _LIBSNG_CALL sangoma_disable_bri_bchan_loopback(sng_fd_t fd, wanpipe_api_t * int _LIBSNG_CALL sangoma_enable_bri_bchan_loopback(sng_fd_t fd, wanpipe_api_t *tdm_api, int channel) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.channel = (unsigned char)channel; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_BRI_CHAN_LOOPBACK; @@ -2810,6 +2860,7 @@ int _LIBSNG_CALL sangoma_get_tx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_TX_Q_SIZE; tdm_api->wp_cmd.tx_queue_sz = 0; @@ -2827,6 +2878,7 @@ int _LIBSNG_CALL sangoma_set_tx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api, in return -1; } WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_TX_Q_SIZE; tdm_api->wp_cmd.tx_queue_sz = size; return sangoma_cmd_exec(fd, tdm_api); @@ -2837,6 +2889,7 @@ int _LIBSNG_CALL sangoma_get_rx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_RX_Q_SIZE; tdm_api->wp_cmd.rx_queue_sz = 0; @@ -2856,6 +2909,7 @@ int _LIBSNG_CALL sangoma_set_rx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api, in } WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_RX_Q_SIZE; tdm_api->wp_cmd.rx_queue_sz = size; return sangoma_cmd_exec(fd, tdm_api); @@ -2866,6 +2920,7 @@ int _LIBSNG_CALL sangoma_get_driver_version(sng_fd_t fd, wanpipe_api_t *tdm_api, int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_DRIVER_VERSION; err = sangoma_cmd_exec(fd, tdm_api); @@ -2887,6 +2942,7 @@ int _LIBSNG_CALL sangoma_get_firmware_version(sng_fd_t fd, wanpipe_api_t *tdm_ap int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_FIRMWARE_VERSION; err = sangoma_cmd_exec(fd, tdm_api); @@ -2906,6 +2962,7 @@ int _LIBSNG_CALL sangoma_get_cpld_version(sng_fd_t fd, wanpipe_api_t *tdm_api, u int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_CPLD_VERSION; err = sangoma_cmd_exec(fd, tdm_api); @@ -2925,6 +2982,7 @@ int _LIBSNG_CALL sangoma_get_stats(sng_fd_t fd, wanpipe_api_t *tdm_api, wanpipe_ int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_GET_STATS; err = sangoma_cmd_exec(fd, tdm_api); @@ -2940,6 +2998,7 @@ int _LIBSNG_CALL sangoma_get_stats(sng_fd_t fd, wanpipe_api_t *tdm_api, wanpipe_ int _LIBSNG_CALL sangoma_flush_stats(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_RESET_STATS; return sangoma_cmd_exec(fd, tdm_api); } @@ -2947,6 +3006,7 @@ int _LIBSNG_CALL sangoma_flush_stats(sng_fd_t fd, wanpipe_api_t *tdm_api) int _LIBSNG_CALL sangoma_set_rm_rxflashtime(sng_fd_t fd, wanpipe_api_t *tdm_api, int rxflashtime) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_RM_RXFLASHTIME; tdm_api->wp_cmd.rxflashtime=rxflashtime; return sangoma_cmd_exec(fd, tdm_api); @@ -2956,6 +3016,7 @@ int _LIBSNG_CALL sangoma_set_rm_rxflashtime(sng_fd_t fd, wanpipe_api_t *tdm_api, int _LIBSNG_CALL sangoma_set_rm_tx_gain(sng_fd_t fd, wanpipe_api_t *tdm_api, int value) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_SET_RM_TX_GAIN; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2966,6 +3027,7 @@ int _LIBSNG_CALL sangoma_set_rm_tx_gain(sng_fd_t fd, wanpipe_api_t *tdm_api, int int _LIBSNG_CALL sangoma_set_rm_rx_gain(sng_fd_t fd, wanpipe_api_t *tdm_api, int value) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_SET_RM_RX_GAIN; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -2979,6 +3041,7 @@ int _LIBSNG_CALL sangoma_tdm_set_polarity(sng_fd_t fd, wanpipe_api_t *tdm_api, i int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_SETPOLARITY; tdm_api->wp_cmd.event.wp_api_event_polarity = polarity; @@ -2991,6 +3054,7 @@ int _LIBSNG_CALL sangoma_tdm_set_polarity(sng_fd_t fd, wanpipe_api_t *tdm_api, i int _LIBSNG_CALL sangoma_tdm_txsig_onhooktransfer(sng_fd_t fd, wanpipe_api_t *tdm_api) { WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT; tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_ONHOOKTRANSFER; tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE; @@ -3004,6 +3068,7 @@ int _LIBSNG_CALL sangoma_tdm_enable_loop(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_ENABLE_LOOP; err = sangoma_cmd_exec(fd, tdm_api); return err; @@ -3014,6 +3079,7 @@ int _LIBSNG_CALL sangoma_tdm_disable_loop(sng_fd_t fd, wanpipe_api_t *tdm_api) int err; WANPIPE_API_INIT_CHAN(tdm_api, 0); + SANGOMA_INIT_TDM_API_CMD_RESULT(*tdm_api); tdm_api->wp_cmd.cmd = WP_API_CMD_DISABLE_LOOP; err = sangoma_cmd_exec(fd, tdm_api); return err; @@ -3139,6 +3205,7 @@ int _LIBSNG_CALL sangoma_mgmt_cmd(sng_fd_t fd, wan_udp_hdr_t* wan_udp) int _LIBSNG_CALL sangoma_driver_port_start(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no) { int err; + port_mgmnt->operation_status = SANG_STATUS_GENERAL_ERROR; port_mgmnt->command_code = START_PORT_VOLATILE_CONFIG; port_mgmnt->port_no = port_no; @@ -3154,6 +3221,7 @@ int _LIBSNG_CALL sangoma_driver_port_start(sng_fd_t fd, port_management_struct_t int _LIBSNG_CALL sangoma_driver_port_stop(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no) { int err; + port_mgmnt->operation_status = SANG_STATUS_GENERAL_ERROR; port_mgmnt->command_code = STOP_PORT; port_mgmnt->port_no = port_no; @@ -3182,6 +3250,7 @@ int _LIBSNG_CALL sangoma_driver_port_stop(sng_fd_t fd, port_management_struct_t int _LIBSNG_CALL sangoma_driver_get_hw_info(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no) { int err; + port_mgmnt->operation_status = SANG_STATUS_GENERAL_ERROR; port_mgmnt->command_code = GET_HARDWARE_INFO; port_mgmnt->port_no = port_no; @@ -3193,8 +3262,23 @@ int _LIBSNG_CALL sangoma_driver_get_hw_info(sng_fd_t fd, port_management_struct_ return port_mgmnt->operation_status; } +int _LIBSNG_CALL sangoma_driver_get_version(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no) +{ + int err; + port_mgmnt->command_code = GET_DRIVER_VERSION; + port_mgmnt->port_no = port_no; + + err = sangoma_port_mgmnt_ioctl(fd, port_mgmnt); + if (err) { + return err; + } + + return port_mgmnt->operation_status; +} + int _LIBSNG_CALL sangoma_driver_port_set_config(sng_fd_t fd, port_cfg_t *port_cfg, unsigned short port_no) { + port_cfg->operation_status = SANG_STATUS_GENERAL_ERROR; port_cfg->command_code = SET_PORT_VOLATILE_CONFIG; port_cfg->port_no = port_no; @@ -3203,6 +3287,7 @@ int _LIBSNG_CALL sangoma_driver_port_set_config(sng_fd_t fd, port_cfg_t *port_cf int _LIBSNG_CALL sangoma_driver_port_get_config(sng_fd_t fd, port_cfg_t *port_cfg, unsigned short port_no) { + port_cfg->operation_status = SANG_STATUS_GENERAL_ERROR; port_cfg->command_code = GET_PORT_VOLATILE_CONFIG; port_cfg->port_no = port_no; return sangoma_port_cfg_ioctl(fd, port_cfg); diff --git a/api/libsangoma/libsangoma.h b/api/libsangoma/libsangoma.h index 58fecf9..e051ccd 100644 --- a/api/libsangoma/libsangoma.h +++ b/api/libsangoma/libsangoma.h @@ -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 #include #include +#include /*! \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 */ diff --git a/api/libsangoma/libsangoma.vcproj b/api/libsangoma/libsangoma.vcproj index c1e2001..d2408b0 100644 --- a/api/libsangoma/libsangoma.vcproj +++ b/api/libsangoma/libsangoma.vcproj @@ -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" diff --git a/api/libsangoma/libsangoma_hwec.c b/api/libsangoma/libsangoma_hwec.c index a1909e7..448df07 100644 --- a/api/libsangoma/libsangoma_hwec.c +++ b/api/libsangoma/libsangoma_hwec.c @@ -44,12 +44,7 @@ # pragma comment( lib, "waneclib" ) /* import functions from waneclib.dll */ #endif/* __WINDOWS__) */ -/* Fast sequence of commands to HWEC may cause the chip - * enter fatal error state, the workaround is to have - * a guaranteed delay after eache command. */ -#define HWEC_CMD_DELAY() wp_usleep(20000) /* 20ms */ - -static int libsng_hwec_verbosity_level = 0; +static int libsng_hwec_verbosity_level = 0x00; /************************************************************//** * Private Functions. (Not exported) @@ -67,54 +62,145 @@ static sangoma_status_t sangoma_hwec_bypass(char *device_name, int enable, unsig /* WAN_EC_API_CMD_HWEC_ENABLE/WAN_EC_API_CMD_HWEC_DISABLE - Controls the "bypass" mode.)*/ rc = wanec_api_hwec(device_name, libsng_hwec_verbosity_level, &hwec); - if( rc ) { - return rc; - } - HWEC_CMD_DELAY(); - return SANG_STATUS_SUCCESS; + + return rc; } +static int sangoma_hwec_is_numeric_parameter(char *parameter) +{ + int i; + static char *WANEC_numeric_params[] = { + "WANEC_TailDisplacement", + "WANEC_MaxPlayoutBuffers", + "WANEC_MaxConfBridges", + "WANEC_EchoOperationMode", + "WANEC_ComfortNoiseMode", + "WANEC_NonLinearityBehaviorA", + "WANEC_NonLinearityBehaviorB", + "WANEC_DoubleTalkBehavior", + "WANEC_RinLevelControlGainDb", + "WANEC_SoutLevelControlGainDb", + "WANEC_RinAutomaticLevelControlTargetDb", + "WANEC_SoutAutomaticLevelControlTargetDb", + "WANEC_RinHighLevelCompensationThresholdDb", + "WANEC_AnrSnrEnhancementDb", + NULL + }; -/************************************************************//** + i = 0; + while(WANEC_numeric_params[i]){ + if (!wp_strncasecmp(parameter, WANEC_numeric_params[i], strlen(parameter))) { + return 1;/* this IS a numeric parameter */ + } + i++; + }; + + return 0;/* NOT a numeric parameter */ +} + +/*************************************************************** * Public Functions. (Exported) ***************************************************************/ /*! - \fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name) + \fn void _LIBSNG_CALL sangoma_hwec_initialize_custom_parameter_structure(wan_custom_param_t *custom_param, char *parameter_name, char *parameter_value) - \brief Load Firmware image onto EC chip. + \brief Initialize Custom Paramter structure. + + \param parameter_name Parameter Name + + \param parameter_value Parameter Value + + \return None +*/ +void _LIBSNG_CALL sangoma_hwec_initialize_custom_parameter_structure(wan_custom_param_t *custom_param, char *parameter_name, char *parameter_value) +{ + memset(custom_param, 0x00, sizeof(*custom_param)); + + strncpy( custom_param->name, parameter_name, sizeof(custom_param->name) ); + + if (sangoma_hwec_is_numeric_parameter(parameter_name)) { + custom_param->dValue = atoi(parameter_value); + } else { + strncpy(custom_param->sValue, parameter_value, sizeof(custom_param->sValue)); + } +} + +/*! + \fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name, wan_custom_param_t custom_params[], unsigned int number_of_custom_params) + + \brief Load Firmware image onto EC chip. All chip-wide configuration paramters, if any, + must be specified at the time of chip initialization. \param device_name Sangoma API device name. Windows: wanpipe1_if1, wanpipe2_if1... Linux: wanpipe1, wanpipe2... + \param custom_params[] - (optional) array of custom paramter structures. + + This is list of Echo Cancellation chip parameters: + + Chip parameter Chip parameter value + ================= ======================= + WANEC_TailDisplacement 0-896 + WANEC_MaxPlayoutBuffers 0-4678 + WANEC_EnableExtToneDetection TRUE | FALSE + WANEC_EnableAcousticEcho TRUE | FALSE + + \param number_of_custom_params - (optional) number of structures in custom_params[]. Minimum value is 1, maximum is 4, + if any other value the custom_params[] will be ignored. + \return SANG_STATUS_SUCCESS: success, or error status */ -sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name) +sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_init(char *device_name, wan_custom_param_t custom_params[], unsigned int number_of_custom_params) { - sangoma_status_t rc; - wan_custom_param_t custom_parms; + sangoma_status_t rc = SANG_STATUS_SUCCESS; wanec_api_config_t config; memset(&config, 0x00, sizeof(config)); - memset(&custom_parms, 0x0, sizeof(custom_parms)); -#if 1 - /* enable acoustic echo cancellation by default */ - strcpy( custom_parms.name, "WANEC_EnableAcousticEcho" ); - strcpy( custom_parms.sValue, "TRUE" ); - - config.conf.param_no = 1; - config.conf.params = &custom_parms; -#endif + if (number_of_custom_params >= 1 && number_of_custom_params <= 4) { - /* Load firmware on EC chip */ + wan_custom_param_t *custom_parms_ptr; + unsigned int i, custom_params_memory_size; + + custom_params_memory_size = sizeof(wan_custom_param_t) * number_of_custom_params; + + /* Do NOT change memory at custom_params[] (it belongs to the caller). + * Instead allocate temporary buffer, and use information in custom_params[] + * for proper initialization the temproary buffer and + * and send if down to API driver. */ + custom_parms_ptr = malloc(custom_params_memory_size); + if (!custom_parms_ptr) { + return SANG_STATUS_FAILED_ALLOCATE_MEMORY; + } + + memset(custom_parms_ptr, 0x00, custom_params_memory_size); + + for (i = 0; i < number_of_custom_params; i++) { + + strcpy( custom_parms_ptr[i].name, custom_params[i].name ); + + if (sangoma_hwec_is_numeric_parameter(custom_params[i].name)) { + custom_parms_ptr[i].dValue = atoi(custom_params[i].sValue); + } else { + strcpy(custom_parms_ptr[i].sValue, custom_params[i].sValue); + } + } /* for() */ + + config.conf.param_no = number_of_custom_params; + config.conf.params = custom_parms_ptr; + + }/* if() */ + + /* Load firmware on EC chip AND apply configuration, if any. */ rc = wanec_api_config( device_name, libsng_hwec_verbosity_level, &config ); - if( rc ) { - return rc; + + if (config.conf.params) { + free(config.conf.params); } - HWEC_CMD_DELAY(); - return SANG_STATUS_SUCCESS; + + return rc; } @@ -137,14 +223,10 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_release(char *device_name) memset(&release, 0, sizeof(wanec_api_release_t)); rc = wanec_api_release( device_name, libsng_hwec_verbosity_level, &release ); - if( rc ) { - return rc; - } - HWEC_CMD_DELAY(); - return SANG_STATUS_SUCCESS; + + return rc; } - /*! Modify channel operation mode. */ @@ -167,11 +249,8 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_operation_mode(char *device_na WANEC_API_OPMODE_SPEECH_RECOGNITION. */ rc = wanec_api_opmode(device_name, libsng_hwec_verbosity_level, &opmode); - if( rc ) { - return rc; - } - HWEC_CMD_DELAY(); - return SANG_STATUS_SUCCESS; + + return rc; } /*! @@ -229,7 +308,7 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_power_off(char *device_name, This command is recommened for fast enabling of Echo Cancellation. Note 1: Chip must be configured and in POWER ON state for echo Chancellation to take place. - Note 2: sangoma_tdm_enable_hwec() function can be use to achive + Note 2: sangoma_tdm_enable_hwec() function can be used to achive the same funcitnality based on file descriptor versus channel map. @@ -275,10 +354,17 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_disable(char *device_name, unsigned i } /*! - \fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameters(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map) + \fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameter(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map) \brief Modify channel configuration parameters. - This is list of Echo Cancellation channel parameters: + + \param device_name Sangoma API device name. + Windows: wanpipe1_if1, wanpipe2_if1... + Linux: wanpipe1, wanpipe2... + + \param parameter Echo Cancellation channel parameter + + This channel parameters are listed under "Channel parameter": Channel parameter Channel parameter value ================= ======================= @@ -301,33 +387,30 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_disable(char *device_name, unsigned i WANEC_DoubleTalkBehavior DT_BEH_NORMAL DT_BEH_LESS_AGGRESSIVE + \param parameter_value channel parameter value, listed under "Channel parameter value" + \param fe_chan_map Bitmap of channels (timeslots for Digital, lines for Analog) where the call will take effect. \return SANG_STATUS_SUCCESS: success, or error status */ -sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameters(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map) +sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_channel_parameter(char *device_name, char *parameter, char *parameter_value, unsigned int channel_map) { sangoma_status_t rc; wanec_api_modify_t channelModify; - wan_custom_param_t aParms; + wan_custom_param_t custom_param; memset(&channelModify, 0x00, sizeof(channelModify)); - memset(&aParms, 0x00, sizeof(aParms)); + + sangoma_hwec_initialize_custom_parameter_structure(&custom_param, parameter, parameter_value); channelModify.fe_chan_map = channel_map; channelModify.conf.param_no = 1; - channelModify.conf.params = &aParms; - - strcpy( aParms.name, parameter); - strcpy( aParms.sValue, parameter_value); + channelModify.conf.params = &custom_param; rc = wanec_api_modify( device_name, libsng_hwec_verbosity_level, &channelModify ); - if( rc ){ - return rc; - } - HWEC_CMD_DELAY(); - return SANG_STATUS_SUCCESS; + + return rc; } /*! @@ -366,11 +449,8 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_tone_detection(char *device_na tone.type_map = WAN_EC_TONE_PRESENT | WAN_EC_TONE_STOP; rc = wanec_api_tone( device_name, libsng_hwec_verbosity_level, &tone ); - if( rc ) { - return rc; - } - HWEC_CMD_DELAY(); - return SANG_STATUS_SUCCESS; + + return rc; } /*! @@ -401,11 +481,8 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_print_statistics(char *device_name, i stats.reset = 0; /* do not reset */ rc = wanec_api_stats( device_name, libsng_hwec_verbosity_level, &stats ); - if( rc ) { - return rc; - } - HWEC_CMD_DELAY(); - return SANG_STATUS_SUCCESS; + + return rc; } /*! @@ -443,7 +520,6 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_audio_buffer_load(char *device_name, *out_buffer_id = bufferload.buffer_id; - HWEC_CMD_DELAY(); return SANG_STATUS_SUCCESS; } @@ -468,11 +544,8 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_audio_buffer_unload(char *device_name bufferunload.buffer_id = (unsigned int)in_buffer_id; rc = wanec_api_buffer_unload( device_name, libsng_hwec_verbosity_level, &bufferunload); - if( rc ) { - return rc; - } - HWEC_CMD_DELAY(); - return SANG_STATUS_SUCCESS; + + return rc; } /*! @@ -518,18 +591,17 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_audio_buffer_playout(char *device_nam playout.duration = (duration) ? duration : 5000; /* default is 5s */ rc = wanec_api_playout( device_name, libsng_hwec_verbosity_level, &playout); - if( rc ) { - return rc; - } - HWEC_CMD_DELAY(); - return SANG_STATUS_SUCCESS; + + return rc; } /*! \fn void _LIBSNG_CALL sangoma_hwec_config_verbosity(int verbosity_level) - \brief Set Verbosity level of EC API. The level controls amount of data - printed to stdout and wanpipelog.txt for diagnostic purposes. + \brief Set Verbosity level of EC API Driver and Library. + The level controls amount of data + printed to stdout and to wanpipelog.txt (Windows) or + /var/log/messages (Linux) for diagnostic purposes. \param verbosity_level Valid values are from 0 to 3. @@ -539,6 +611,7 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_config_verbosity(int verbosity_level) { if (verbosity_level >= 0 || verbosity_level <= 3) { libsng_hwec_verbosity_level = verbosity_level; + wanec_api_set_lib_verbosity(verbosity_level); return SANG_STATUS_SUCCESS; } return SANG_STATUS_INVALID_PARAMETER; diff --git a/api/libsangoma/sample_c/.svn/all-wcprops b/api/libsangoma/sample_c/.svn/all-wcprops index 47dd1cf..49485cc 100644 --- a/api/libsangoma/sample_c/.svn/all-wcprops +++ b/api/libsangoma/sample_c/.svn/all-wcprops @@ -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 diff --git a/api/libsangoma/sample_c/.svn/entries b/api/libsangoma/sample_c/.svn/entries index 24fff89..54522fd 100644 --- a/api/libsangoma/sample_c/.svn/entries +++ b/api/libsangoma/sample_c/.svn/entries @@ -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 diff --git a/api/libsangoma/sample_c/.svn/text-base/lib_api.c.svn-base b/api/libsangoma/sample_c/.svn/text-base/lib_api.c.svn-base index d9cad77..723f0fc 100644 --- a/api/libsangoma/sample_c/.svn/text-base/lib_api.c.svn-base +++ b/api/libsangoma/sample_c/.svn/text-base/lib_api.c.svn-base @@ -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" ":\n" -" -p #port/span number\n" -" -i #if/chan number\n" -" -r #read enable\n" -" -w #write eable\n" +" -span #port/span number\n" +" -chan #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" "\n" " -txcnt #number of tx packets (Dflt: 1)\n" diff --git a/api/libsangoma/sample_c/.svn/text-base/lib_api.h.svn-base b/api/libsangoma/sample_c/.svn/text-base/lib_api.h.svn-base index d368bf8..5b94661 100644 --- a/api/libsangoma/sample_c/.svn/text-base/lib_api.h.svn-base +++ b/api/libsangoma/sample_c/.svn/text-base/lib_api.h.svn-base @@ -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]; diff --git a/api/libsangoma/sample_c/.svn/text-base/sample.c.svn-base b/api/libsangoma/sample_c/.svn/text-base/sample.c.svn-base index 6e9d17d..8f4b007 100644 --- a/api/libsangoma/sample_c/.svn/text-base/sample.c.svn-base +++ b/api/libsangoma/sample_c/.svn/text-base/sample.c.svn-base @@ -1,769 +1,919 @@ -/******************************************************************************//** - * \file sample.c - * \brief WANPIPE(tm) API C Sample Code - * - * Authors: David Rokhvarg - * Nenad Corbic - * - * 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 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); -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); /* dont remove prototype, gcc complains */ -void print_rxdata(unsigned char *data, int datalen) -{ - int i; - - printf("Data: (Len=%i)\n",datalen); - 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"); -} - -/*! - \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 (verbose){ - print_rxdata(rx_buffer, Rx_lgth); - } - - /* 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) - \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 - \return 0 - Ok otherwise Error -*/ -int write_data(uint32_t dev_index, wp_api_hdr_t *tx_hdr, void *tx_buffer) -{ - 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; - - /* 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 */ - 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\n", Tx_count, err); - }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){ - 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); - } -#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; - - 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); - } - } - } - - 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); - - if(write_data(dev_index, &txhdr, txdata) == 0){ - tx_test_byte++; - } - } - return 0; -} - -/*! - \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 */, - 2000 /* wait timeout, in milliseconds */); - switch(iResult) - { - case SANG_STATUS_APIPOLL_TIMEOUT: - /* timeout (not an error) */ - 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"); - } - } - - 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"); - } - } - }/* 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; - } - } - - 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)); - - 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; -} +/******************************************************************************//** + * \file sample.c + * \brief WANPIPE(tm) API C Sample Code + * + * Authors: David Rokhvarg + * Nenad Corbic + * + * 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; + +#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){ + 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; + } + + +#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<spanno,chan->channo,rx_hdr->wp_api_rx_hdr_error_map); + } + if (rx_hdr->wp_api_rx_hdr_error_map & 1<spanno,chan->channo,rx_hdr->wp_api_rx_hdr_error_map); + } + if (rx_hdr->wp_api_rx_hdr_error_map & 1<spanno,chan->channo,rx_hdr->wp_api_rx_hdr_error_map); + } + if (rx_hdr->wp_api_rx_hdr_error_map & 1<spanno,chan->channo,rx_hdr->wp_api_rx_hdr_error_map); + } + if (rx_hdr->wp_api_rx_hdr_error_map & 1<spanno,chan->channo,rx_hdr->wp_api_rx_hdr_error_map); + } + //return 1; + } +#endif + + 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; +} diff --git a/api/libsangoma/sample_c/.svn/tmp/tempfile.2.tmp b/api/libsangoma/sample_c/.svn/tmp/tempfile.2.tmp new file mode 100644 index 0000000..f8af125 --- /dev/null +++ b/api/libsangoma/sample_c/.svn/tmp/tempfile.2.tmp @@ -0,0 +1,913 @@ +/******************************************************************************//** + * \file sample.c + * \brief WANPIPE(tm) API C Sample Code + * + * Authors: David Rokhvarg + * Nenad Corbic + * + * 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_api_rx_hdr_error_map & 1<wp_api_rx_hdr_error_map & 1<wp_api_rx_hdr_error_map & 1<wp_api_rx_hdr_error_map & 1<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; +} diff --git a/api/libsangoma/sample_c/.svn/tmp/tempfile.3.tmp b/api/libsangoma/sample_c/.svn/tmp/tempfile.3.tmp new file mode 100644 index 0000000..0dbfb7f --- /dev/null +++ b/api/libsangoma/sample_c/.svn/tmp/tempfile.3.tmp @@ -0,0 +1,945 @@ +/******************************************************************************//** + * \file sample.c + * \brief WANPIPE(tm) API C Sample Code + * + * Authors: David Rokhvarg + * Nenad Corbic + * + * 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_api_rx_hdr_error_map & 1<wp_api_rx_hdr_error_map & 1<wp_api_rx_hdr_error_map & 1<wp_api_rx_hdr_error_map & 1<wp_api_rx_hdr_error_map) { + if (rx_hdr->wp_api_rx_hdr_error_map & 1<spanno,chan->channo,rx_hdr->wp_api_rx_hdr_error_map); + } + if (rx_hdr->wp_api_rx_hdr_error_map & 1<spanno,chan->channo,rx_hdr->wp_api_rx_hdr_error_map); + } + if (rx_hdr->wp_api_rx_hdr_error_map & 1<spanno,chan->channo,rx_hdr->wp_api_rx_hdr_error_map); + } + if (rx_hdr->wp_api_rx_hdr_error_map & 1<spanno,chan->channo,rx_hdr->wp_api_rx_hdr_error_map); + } + if (rx_hdr->wp_api_rx_hdr_error_map & 1<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; +} diff --git a/api/libsangoma/sample_c/lib_api.c b/api/libsangoma/sample_c/lib_api.c index d9cad77..723f0fc 100644 --- a/api/libsangoma/sample_c/lib_api.c +++ b/api/libsangoma/sample_c/lib_api.c @@ -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" ":\n" -" -p #port/span number\n" -" -i #if/chan number\n" -" -r #read enable\n" -" -w #write eable\n" +" -span #port/span number\n" +" -chan #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" "\n" " -txcnt #number of tx packets (Dflt: 1)\n" diff --git a/api/libsangoma/sample_c/lib_api.h b/api/libsangoma/sample_c/lib_api.h index d368bf8..5b94661 100644 --- a/api/libsangoma/sample_c/lib_api.h +++ b/api/libsangoma/sample_c/lib_api.h @@ -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]; diff --git a/api/libsangoma/sample_c/sample.c b/api/libsangoma/sample_c/sample.c index 6e9d17d..8f4b007 100644 --- a/api/libsangoma/sample_c/sample.c +++ b/api/libsangoma/sample_c/sample.c @@ -1,769 +1,919 @@ -/******************************************************************************//** - * \file sample.c - * \brief WANPIPE(tm) API C Sample Code - * - * Authors: David Rokhvarg - * Nenad Corbic - * - * 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 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); -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); /* dont remove prototype, gcc complains */ -void print_rxdata(unsigned char *data, int datalen) -{ - int i; - - printf("Data: (Len=%i)\n",datalen); - 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"); -} - -/*! - \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 (verbose){ - print_rxdata(rx_buffer, Rx_lgth); - } - - /* 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) - \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 - \return 0 - Ok otherwise Error -*/ -int write_data(uint32_t dev_index, wp_api_hdr_t *tx_hdr, void *tx_buffer) -{ - 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; - - /* 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 */ - 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\n", Tx_count, err); - }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){ - 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); - } -#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; - - 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); - } - } - } - - 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); - - if(write_data(dev_index, &txhdr, txdata) == 0){ - tx_test_byte++; - } - } - return 0; -} - -/*! - \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 */, - 2000 /* wait timeout, in milliseconds */); - switch(iResult) - { - case SANG_STATUS_APIPOLL_TIMEOUT: - /* timeout (not an error) */ - 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"); - } - } - - 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"); - } - } - }/* 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; - } - } - - 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)); - - 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; -} +/******************************************************************************//** + * \file sample.c + * \brief WANPIPE(tm) API C Sample Code + * + * Authors: David Rokhvarg + * Nenad Corbic + * + * 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; + +#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){ + 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; + } + + +#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<spanno,chan->channo,rx_hdr->wp_api_rx_hdr_error_map); + } + if (rx_hdr->wp_api_rx_hdr_error_map & 1<spanno,chan->channo,rx_hdr->wp_api_rx_hdr_error_map); + } + if (rx_hdr->wp_api_rx_hdr_error_map & 1<spanno,chan->channo,rx_hdr->wp_api_rx_hdr_error_map); + } + if (rx_hdr->wp_api_rx_hdr_error_map & 1<spanno,chan->channo,rx_hdr->wp_api_rx_hdr_error_map); + } + if (rx_hdr->wp_api_rx_hdr_error_map & 1<spanno,chan->channo,rx_hdr->wp_api_rx_hdr_error_map); + } + //return 1; + } +#endif + + 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; +} diff --git a/api/libsangoma/sample_cpp/.svn/all-wcprops b/api/libsangoma/sample_cpp/.svn/all-wcprops index 3606ccf..f0cf5ec 100644 --- a/api/libsangoma/sample_cpp/.svn/all-wcprops +++ b/api/libsangoma/sample_cpp/.svn/all-wcprops @@ -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 diff --git a/api/libsangoma/sample_cpp/.svn/entries b/api/libsangoma/sample_cpp/.svn/entries index 47c3c07..006faa1 100644 --- a/api/libsangoma/sample_cpp/.svn/entries +++ b/api/libsangoma/sample_cpp/.svn/entries @@ -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 diff --git a/api/libsangoma/sample_cpp/.svn/text-base/sample.cpp.svn-base b/api/libsangoma/sample_cpp/.svn/text-base/sample.cpp.svn-base index 06a149a..7570130 100644 --- a/api/libsangoma/sample_cpp/.svn/text-base/sample.cpp.svn-base +++ b/api/libsangoma/sample_cpp/.svn/text-base/sample.cpp.svn-base @@ -59,17 +59,12 @@ callback_functions_t callback_functions; * Prototypes & Defines *****************************************************************/ -static int got_rx_data(void *sang_if_ptr, void *rx_data); +static int got_rx_data(void *sang_if_ptr, void *rxhdr, void *rx_data); static void got_tdm_api_event(void *sang_if_ptr, void *event_data); #if USE_WP_LOGGER static void got_logger_event(void *sang_if_ptr, wp_logger_event_t *logger_event); #endif -typedef struct{ - void *sang_if_ptr; - wp_api_event_t event; -}TDM_API_EVENT_THREAD_PARAM; - #if USE_STELEPHONY_API //Sangoma Telephony API (Stelephony.dll) provides the following telephony services: @@ -88,13 +83,6 @@ CRITICAL_SECTION PrintCriticalSection; //critical section for TDM events CRITICAL_SECTION TdmEventCriticalSection; -#if defined (__WINDOWS__) -DWORD TdmApiEventThreadFunc(LPDWORD lpdwParam); -#else -void *TdmApiEventThreadFunc(void *lpdwParam); -#endif - - /***************************************************************** * Debugging Macros *****************************************************************/ @@ -195,9 +183,9 @@ void PrintRxData(wp_api_hdr_t *hdr, void *pdata) if(program_settings.silent){ if((rx_counter % 1000) == 0){ INFO_MAIN("Rx counter: %d, Rx datlen: %d\n", rx_counter, datlen); -#if 0 +#if 1 INFO_MAIN("Timestamp: Seconds: %d, Microseconds: %d\n", - hdr->wp_api_hdr_time_stamp_sec, hdr->wp_api_hdr_time_stamp_use); + hdr->time_stamp_sec, hdr->time_stamp_usec); #endif } return; @@ -222,10 +210,13 @@ void PrintRxData(wp_api_hdr_t *hdr, void *pdata) /*! \fn static int got_rx_data(void *sang_if_ptr, void *rx_data) - \brief Callback function indicating data rx is pending + \brief Callback function indicating data rx is pending. \param sang_if_ptr sangoma interface pointer \param rx_data API data element strcutre containt header + data \return 0 - ok non-zero - Error + + This function must return as fast as possible + because it is called from real time receiver thread. */ static int got_rx_data(void *sang_if_ptr, void *rxhdr, void *rx_data) { @@ -267,71 +258,33 @@ static int got_rx_data(void *sang_if_ptr, void *rxhdr, void *rx_data) \param event_data API event element strcutre containt header + data \return 0 - ok non-zero - Error - Currently Windows launches a thread to handle the event, where - Linux handles the event directly. Implementation is left to the user. + + Handling of Events must be done OUTSIDE of the REAL-TIME Rx thread + because it may make take a lot of time. + Create a special thread for Event hadling Or push Event into + a queue - implentation is left to the user. + In this example event is handled directly. */ static void got_tdm_api_event(void *sang_if_ptr, void *event_data) { - TDM_API_EVENT_THREAD_PARAM *param = - (TDM_API_EVENT_THREAD_PARAM*)malloc(sizeof(TDM_API_EVENT_THREAD_PARAM)); - - if(param == NULL){ - ERR_MAIN("Failed to allocate memory for 'Event Thread parameter'!!\n"); - return; - } - - memcpy(¶m->event, event_data, sizeof(wp_api_event_t)); - param->sang_if_ptr = sang_if_ptr; - - ////////////////////////////////////////////////////////////////////// - //Handling of Events must be done OUTSIDE of the REAL-TIME Rx thread// - //because it may make take a lot of time. // - //Create a special thread for Event hadling. // - ////////////////////////////////////////////////////////////////////// -#if defined(__WINDOWS__) - DWORD dwThreadId; - - if(CreateThread( - NULL, /* no security attributes */ - 0, /* use default stack size */ - (LPTHREAD_START_ROUTINE)TdmApiEventThreadFunc, /* thread function */ - param, /* argument to thread function */ - 0, /* use default creation flags */ - &dwThreadId /* returns the thread identifier */ - ) == NULL){ - ERR_MAIN("Failed to create 'TdmApiEvent' thread!!\n"); - } -#else - //FIXME: implement the thread. Consider using sangoma_cthread class. - TdmApiEventThreadFunc(param); -#endif -} - -/*! - \fn void *TdmApiEventThreadFunc(void *lpdwParam) - \brief Event handling Function - \param lpdwParam pointer to the span/chan device - \return void -*/ -#if defined(__WINDOWS__) -DWORD TdmApiEventThreadFunc(LPDWORD lpdwParam) -#else -void *TdmApiEventThreadFunc(void *lpdwParam) -#endif -{ - TDM_API_EVENT_THREAD_PARAM *param; - sangoma_interface *sang_if; - wp_api_event_t *wp_tdm_api_event; + sangoma_interface *sang_if = (sangoma_interface *)sang_if_ptr; + wp_api_event_t *wp_tdm_api_event = (wp_api_event_t *)event_data; + wan_time_t wan_time; + char *timestamp_str; EnterCriticalSection(&TdmEventCriticalSection); - param = (TDM_API_EVENT_THREAD_PARAM*)lpdwParam; + /* Windows: wan_time is 64bit, time_stamp_sec is 32bit + * Linux: wan_time and time_stamp_sec is 32bit */ + wan_time = wp_tdm_api_event->time_stamp_sec; + timestamp_str = sangoma_ctime( &wan_time ); - wp_tdm_api_event = ¶m->event; - sang_if = (sangoma_interface*)param->sang_if_ptr; + /* Display Logger Event Timestamp as UNIX-style Date string. */ + /*DBG_MAIN("Time and Date:\t\t%s\n", (timestamp_str == NULL ? "Invalid Timestamp" : timestamp_str));*/ - DBG_MAIN("%s(): ifname: %s: Span: %d, Channel: %d\n", __FUNCTION__, sang_if->device_name, - wp_tdm_api_event->wp_api_event_span, wp_tdm_api_event->wp_api_event_channel); + DBG_MAIN("%s(): Span: %d, Channel: %d (Seconds:%u, Microseconds:%u)\n", __FUNCTION__, + wp_tdm_api_event->wp_api_event_span, wp_tdm_api_event->wp_api_event_channel, + wp_tdm_api_event->time_stamp_sec, wp_tdm_api_event->time_stamp_usec); switch(wp_tdm_api_event->wp_api_event_type) { @@ -340,7 +293,6 @@ void *TdmApiEventThreadFunc(void *lpdwParam) wp_tdm_api_event->wp_api_event_dtmf_digit, (wp_tdm_api_event->wp_api_event_dtmf_port == WAN_EC_CHANNEL_PORT_ROUT)?"ROUT":"SOUT", (wp_tdm_api_event->wp_api_event_dtmf_type == WAN_EC_TONE_PRESENT)?"PRESENT":"STOP"); - break; case WP_API_EVENT_RXHOOK: @@ -395,10 +347,8 @@ void *TdmApiEventThreadFunc(void *lpdwParam) break; } - free(lpdwParam); LeaveCriticalSection(&TdmEventCriticalSection); - //Done with the Event, exit the thread. - return 0; + return; } #if USE_WP_LOGGER @@ -567,6 +517,8 @@ static int parse_command_line_args(int argc, char* argv[]) #ifdef WP_API_FEATURE_LIBSNG_HWEC "\t-use_hwec \tInitialize/Configure/Use the Hardware Echo Canceller\n" #endif +"\t-real_time \tRun the Program at real-time priority. This maybe\n" +"\t \t\timportant when Audio stream is used for timing.\n" "\n" "Example: sample -c 1 -i 1\n"; @@ -686,9 +638,11 @@ static int parse_command_line_args(int argc, char* argv[]) i++; INFO_MAIN("Setting rxgain to %d.\n", program_settings.txgain); }else if(_stricmp(argv[i], "-use_hwec") == 0){ - INFO_MAIN("Using hardware echo canceller...\n"); program_settings.use_hardware_echo_canceller = 1; + }else if(_stricmp(argv[i], "-real_time") == 0){ + INFO_MAIN("Will be running at real-time priority...\n"); + program_settings.real_time = 1; }else{ INFO_MAIN("Error: Invalid Argument %s\n",argv[i]); return 1; @@ -751,6 +705,10 @@ int __cdecl main(int argc, char* argv[]) InitializeCriticalSection(&PrintCriticalSection); InitializeCriticalSection(&TdmEventCriticalSection); + if (program_settings.real_time) { + sng_set_process_priority_to_real_time(); + } + //////////////////////////////////////////////////////////////////////////// //User may provide Wanpipe Number and Interface Number as a command line arguments: INFO_MAIN("Using wanpipe_number: %d, interface_number: %d\n", program_settings.wanpipe_number, program_settings.interface_number); @@ -842,7 +800,7 @@ int __cdecl main(int argc, char* argv[]) INFO_MAIN("Press 'd' to disable bri bchan loopback\n"); break; } - INFO_MAIN("Press 'o' to enable DTMF events (on Octasic chip)\n"); + INFO_MAIN("Press 'o' to control DTMF events on DSP (Octasic)\n"); if (program_settings.encode_sw_dtmf) { INFO_MAIN("Press 'x' to send software DTMF\n"); } diff --git a/api/libsangoma/sample_cpp/.svn/text-base/sample.h.svn-base b/api/libsangoma/sample_cpp/.svn/text-base/sample.h.svn-base index d563360..80bd6c2 100644 --- a/api/libsangoma/sample_cpp/.svn/text-base/sample.h.svn-base +++ b/api/libsangoma/sample_cpp/.svn/text-base/sample.h.svn-base @@ -32,6 +32,7 @@ typedef struct{ int txgain; int rxgain; unsigned char use_hardware_echo_canceller; + unsigned char real_time; }wp_program_settings_t; #define DEV_NAME_LEN 100 @@ -63,9 +64,9 @@ typedef struct{ }callback_functions_t; +#if defined (__WINDOWS__) static void DecodeLastError(LPSTR lpszFunction) { -#if defined (__WINDOWS__) LPVOID lpMsgBuf; DWORD dwLastErr = GetLastError(); FormatMessage( @@ -83,8 +84,32 @@ static void DecodeLastError(LPSTR lpszFunction) printf("Last Error: %s (GetLastError() returned: %d)\n", (char*)lpMsgBuf, dwLastErr); // Free the buffer. LocalFree( lpMsgBuf ); -#endif } +#endif + +//This Program interfaces directly to hardware, it should be real time. +static void sng_set_process_priority_to_real_time() +{ +#if defined (__WINDOWS__) + if (!SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)) { + printf("Failed to set program priority!\n"); + } +#else + //TODO: implement for Linux +#endif +} + +//This Execution Thread interfaces directly to hardware, it should be real time. +static void sng_set_thread_priority_to_real_time() +{ +#if defined (__WINDOWS__) + if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL)) { + printf("Failed to set thread priority!\n"); + } +#else + //TODO: implement for Linux +#endif +} /* This flag controls debugging of time difference between * data receive indications. Disabled by default. */ @@ -118,13 +143,14 @@ debug_print_dbg_struct( const char *caller_name ) { - printf("timediff_deviation_counter: %d\n\tTimeDiff (ms) between '%s()':\n\tHighest:%d Lowest:%d Expected: %d Latest: %d\n", + printf("timediff_deviation_counter: %d\n\tTimeDiff (ms) between '%s()':\n\tHighest:%d Lowest:%d Expected: %d Latest: %d allowed deviation:%d\n", wan_debug_ptr->timediff_deviation_counter, caller_name, wan_debug_ptr->highest_timediff, wan_debug_ptr->lowest_timediff, wan_debug_ptr->high_resolution_timediff_value, - wan_debug_ptr->latest_timediff); + wan_debug_ptr->latest_timediff, + wan_debug_ptr->allowed_deviation_of_timediff_value); } /* Call this function to mesure TimeDiff between some function call. */ diff --git a/api/libsangoma/sample_cpp/.svn/text-base/sangoma_interface.cpp.svn-base b/api/libsangoma/sample_cpp/.svn/text-base/sangoma_interface.cpp.svn-base index 50265f0..fb6bd58 100644 --- a/api/libsangoma/sample_cpp/.svn/text-base/sangoma_interface.cpp.svn-base +++ b/api/libsangoma/sample_cpp/.svn/text-base/sangoma_interface.cpp.svn-base @@ -15,8 +15,6 @@ #define DO_COMMAND(wan_udp) DoManagementCommand(sangoma_dev, &wan_udp); -#define NUMBER_OF_WAIT_OBJECTS 1 - #ifdef WP_API_FEATURE_LIBSNG_HWEC /* defined in wanpipe_api_iface.h */ # include "wanpipe_events.h" # include "wanec_api.h" @@ -32,7 +30,8 @@ sangoma_interface::sangoma_interface(int wanpipe_number, int interface_number) memset(device_name, 0x00, DEV_NAME_LEN); memset(&wan_udp, 0x00, sizeof(wan_udp)); memset(&tdm_api_cmd, 0x00, sizeof(tdm_api_cmd)); - memset(&wp_api, 0x00, sizeof(wp_api)); + + SANGOMA_INIT_TDM_API_CMD(wp_api); WanpipeNumber = wanpipe_number; InterfaceNumber = interface_number; @@ -47,7 +46,7 @@ sangoma_interface::sangoma_interface(int wanpipe_number, int interface_number) terminate_tx_rx_threads = 0; is_rbs_monitoring_enabled = 0; - sng_wait_obj = NULL; + memset(sng_wait_obj, 0x00, sizeof(sng_wait_obj)); ////////////////////////////////////////////////////////////////// //receive stuff @@ -79,7 +78,8 @@ sangoma_interface::sangoma_interface(int wanpipe_number, int interface_number) memset(&wan_debug_rx_timing, 0x00, sizeof(wan_debug_t)); debug_set_timing_info( &wan_debug_rx_timing, 20 /* expected timediff in milliseconds */, - 2 /* allowed deviation from expected timediff */); + 2 /* allowed deviation from expected timediff + * (allowed_deviation_of_timediff_value) */); #endif } @@ -95,16 +95,17 @@ int sangoma_interface::init(callback_functions_t *callback_functions_ptr) memcpy(&callback_functions, callback_functions_ptr, sizeof(callback_functions_t)); + DBG_IFACE("%s(): WanpipeNumber: %d, InterfaceNumber: %d\n", __FUNCTION__, WanpipeNumber, InterfaceNumber); //////////////////////////////////////////////////////////////////////////// //open handle for reading and writing data, for events reception and other commands - sangoma_dev = open_api_device(); + sangoma_dev = sangoma_open_api_span_chan(WanpipeNumber, InterfaceNumber); if (sangoma_dev == INVALID_HANDLE_VALUE){ ERR_IFACE( "Unable to open %s for Rx/Tx!\n", device_name); return 1; } - if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj, sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){ - ERR_IFACE("Failed to create 'sangoma_wait_object' for %s\n", device_name); + if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj[SANGOMA_TX_WAIT_OBJECT], sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){ + ERR_IFACE("Failed to create 'Tx/Rx/Event WAIT_OBJECT' for %s\n", device_name); return 1; } @@ -182,13 +183,6 @@ int sangoma_interface::init(callback_functions_t *callback_functions_ptr) return 0; } -sng_fd_t sangoma_interface::open_api_device() -{ - DBG_IFACE("%s(): WanpipeNumber: %d, InterfaceNumber: %d\n", __FUNCTION__, WanpipeNumber, InterfaceNumber); - - return sangoma_open_api_span_chan(WanpipeNumber, InterfaceNumber); -} - void sangoma_interface::generate_bit_rev_table(void) { unsigned char util_char; @@ -589,6 +583,8 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats) { int err; unsigned char firm_ver, cpld_ver; + + SANGOMA_INIT_TDM_API_CMD(wp_api); err=sangoma_get_stats(sangoma_dev, &wp_api, stats); if (err) { @@ -612,9 +608,11 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats) INFO_IFACE("\trx_length_errors: %u\n", stats->rx_length_errors); INFO_IFACE("\trx_over_errors\t: %u\n", stats->rx_over_errors); INFO_IFACE("\trx_crc_errors\t: %u\n", stats->rx_crc_errors); //HDLC CRC mismatch - INFO_IFACE("\trx_frame_errors\t: %u\n", stats->rx_frame_errors);//HDLC "abort" occured + INFO_IFACE("\trx_frame_errors\t: %u\n", stats->rx_frame_errors);//HDLC Frame Start or Stop Flag is missing INFO_IFACE("\trx_fifo_errors\t: %u\n", stats->rx_fifo_errors); INFO_IFACE("\trx_missed_errors: %u\n", stats->rx_missed_errors); + INFO_IFACE("\trx_hdlc_abort_counter: %u\n", stats->rx_hdlc_abort_counter);//Transmitter aborted frame transmission. + //Not an error. INFO_IFACE("\ttx_aborted_errors: %u\n", stats->tx_aborted_errors); INFO_IFACE("\tTx Idle Data\t: %u\n", stats->tx_carrier_errors); @@ -637,6 +635,7 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats) INFO_IFACE("\tHWEC tone (DTMF) events counter: %u\n", stats->rx_events_tone); INFO_IFACE( "*********************************\n"); + SANGOMA_INIT_TDM_API_CMD(wp_api); err=sangoma_get_driver_version(sangoma_dev,&wp_api, NULL); if (err) { return 1; @@ -647,6 +646,7 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats) wp_api.wp_cmd.version.minor1, wp_api.wp_cmd.version.minor2); + SANGOMA_INIT_TDM_API_CMD(wp_api); err=sangoma_get_firmware_version(sangoma_dev, &wp_api, &firm_ver); if (err) { return 1; @@ -654,6 +654,7 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats) INFO_IFACE("\tFirmware Version: %X\n", firm_ver); + SANGOMA_INIT_TDM_API_CMD(wp_api); err=sangoma_get_cpld_version(sangoma_dev, &wp_api, &cpld_ver); if (err) { return 1; @@ -669,11 +670,13 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats) int sangoma_interface::flush_operational_stats() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_flush_stats(sangoma_dev,&wp_api); } int sangoma_interface::flush_tx_buffers() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_flush_bufs(sangoma_dev,&wp_api); } @@ -702,6 +705,7 @@ int sangoma_interface::enable_rbs_monitoring() // set Idle Transmit flag (BitStream/Voice only). int sangoma_interface::set_tx_idle_flag(unsigned char new_idle_flag) { + SANGOMA_INIT_TDM_API_CMD(wp_api); tdm_api_cmd.cmd = WP_API_CMD_SET_IDLE_FLAG; tdm_api_cmd.idle_flag = new_idle_flag; return tdmv_api_ioctl(&tdm_api_cmd); @@ -712,6 +716,7 @@ char sangoma_interface::get_rbs(rbs_management_t *rbs_management_ptr) { int err; + SANGOMA_INIT_TDM_API_CMD(wp_api); err=sangoma_tdm_read_rbs(sangoma_dev, &wp_api, rbs_management_ptr->channel, &rbs_management_ptr->ABCD_bits); if (err) { ERR_IFACE( "Error: command WANPIPEMON_GET_RBS_BITS failed!\n"); @@ -736,6 +741,7 @@ char sangoma_interface::set_rbs(rbs_management_t *rbs_management_ptr) { int err; + SANGOMA_INIT_TDM_API_CMD(wp_api); err=sangoma_tdm_write_rbs(sangoma_dev, &wp_api, rbs_management_ptr->channel, rbs_management_ptr->ABCD_bits); if (err) { return 1; @@ -833,6 +839,17 @@ int sangoma_interface::get_interface_configuration(if_cfg_t *wanif_conf_ptr) } INFO_IFACE( "****************************\n"); +#if 0 + // Audio Codec can be read for Voice interface. + // For Data interface this setting is ignored by the API. + SANGOMA_INIT_TDM_API_CMD(wp_api); + sangoma_get_hw_coding(sangoma_dev, &wp_api); + if (wp_api.wp_cmd.result == SANG_STATUS_SUCCESS) { + INFO_IFACE("Audio Codec: %s\n", + WP_CODEC_FORMAT_DECODE(wp_api.wp_cmd.hw_tdm_coding)); + } +#endif + return 0; } @@ -841,6 +858,7 @@ void sangoma_interface::get_api_driver_version (PDRIVER_VERSION version) int err; + SANGOMA_INIT_TDM_API_CMD(wp_api); err=sangoma_get_driver_version(sangoma_dev, &wp_api, version); if(err){ ERR_IFACE("Error: command READ_CODE_VERSION failed!\n"); @@ -874,6 +892,7 @@ void sangoma_interface::get_card_customer_id(u_int8_t *customer_id) int sangoma_interface::get_open_handles_counter() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_get_open_cnt(sangoma_dev,&wp_api); } @@ -883,12 +902,15 @@ int sangoma_interface::get_open_handles_counter() //receive data until the LAST handel is closed. void sangoma_interface::cleanup() { + int i; + INFO_IFACE("sangoma_interface::cleanup()\n"); - if(sng_wait_obj){ - sangoma_wait_obj_delete(&sng_wait_obj); + for (i = 0; i < SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS; i++) { + if(sng_wait_obj[i]){ + sangoma_wait_obj_delete(&sng_wait_obj[i]); + } } - #ifdef WIN32 if(sangoma_dev != INVALID_HANDLE_VALUE){ if(is_rbs_monitoring_enabled == 1){ @@ -924,7 +946,7 @@ int sangoma_interface::tdmv_api_ioctl(wanpipe_api_cmd_t *api_cmd) { int err; - memset(&wp_api, 0x00, sizeof(wp_api)); + SANGOMA_INIT_TDM_API_CMD(wp_api); memcpy(&wp_api.wp_cmd, api_cmd, sizeof(wanpipe_api_cmd_t)); @@ -937,11 +959,13 @@ int sangoma_interface::tdmv_api_ioctl(wanpipe_api_cmd_t *api_cmd) int sangoma_interface::tdm_enable_ring_detect_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_ring_detect_events(sangoma_dev,&wp_api); } int sangoma_interface::tdm_disable_ring_detect_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_disable_ring_detect_events(sangoma_dev,&wp_api); } @@ -950,13 +974,15 @@ int sangoma_interface::tdm_disable_ring_detect_events() * 1250 is most used value. To disable flash event set rxflashtime to 0 */ int sangoma_interface::tdm_control_flash_events(int rxflashtime) { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_set_rm_rxflashtime(sangoma_dev, &wp_api, rxflashtime); } int sangoma_interface::tdm_control_rm_txgain(int txgain) { #if WP_API_FEATURE_RM_GAIN - return sangoma_set_rm_tx_gain(sangoma_dev,&wp_api, txgain); + SANGOMA_INIT_TDM_API_CMD(wp_api); + return sangoma_set_rm_tx_gain(sangoma_dev, &wp_api, txgain); #else return SANG_STATUS_UNSUPPORTED_FUNCTION; #endif @@ -965,6 +991,7 @@ int sangoma_interface::tdm_control_rm_txgain(int txgain) int sangoma_interface::tdm_control_rm_rxgain(int rxgain) { #if WP_API_FEATURE_RM_GAIN + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_set_rm_rx_gain(sangoma_dev, &wp_api, rxgain); #else return SANG_STATUS_UNSUPPORTED_FUNCTION; @@ -973,96 +1000,117 @@ int sangoma_interface::tdm_control_rm_rxgain(int rxgain) int sangoma_interface::tdm_enable_ring_trip_detect_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_ring_trip_detect_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_disable_ring_trip_detect_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_disable_ring_trip_detect_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_enable_rm_dtmf_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_rm_dtmf_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_disable_rm_dtmf_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_disable_rm_dtmf_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_enable_dtmf_events(uint8_t channel) { + SANGOMA_INIT_TDM_API_CMD(wp_api); + wp_api.wp_cmd.chan = channel; return sangoma_tdm_enable_dtmf_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_disable_dtmf_events(uint8_t channel) { + SANGOMA_INIT_TDM_API_CMD(wp_api); + wp_api.wp_cmd.chan = channel; return sangoma_tdm_disable_dtmf_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_enable_rxhook_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_rxhook_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_disable_rxhook_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_disable_rxhook_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_enable_ring_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_ring_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_disable_ring_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_disable_ring_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_txsig_onhook() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_txsig_onhook(sangoma_dev, &wp_api); } int sangoma_interface::tdm_txsig_kewl() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_txsig_kewl(sangoma_dev, &wp_api); } int sangoma_interface::tdm_txsig_onhooktransfer() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_txsig_onhooktransfer(sangoma_dev, &wp_api); } int sangoma_interface::tdm_set_rm_polarity(int polarity) { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_set_polarity(sangoma_dev, &wp_api, polarity); } int sangoma_interface::tdm_txsig_offhook() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_txsig_offhook(sangoma_dev, &wp_api); } int sangoma_interface::tdm_enable_tone_events(uint16_t tone_id) { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_tone_events(sangoma_dev, &wp_api, tone_id); } int sangoma_interface::tdm_disable_tone_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_disable_tone_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_enable_bri_bchan_loopback(u_int8_t channel) { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_enable_bri_bchan_loopback(sangoma_dev, &wp_api, channel); } int sangoma_interface::tdm_disable_bri_bchan_loopback(u_int8_t channel) { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_disable_bri_bchan_loopback(sangoma_dev, &wp_api, channel); } @@ -1073,49 +1121,57 @@ int sangoma_interface::tdm_disable_bri_bchan_loopback(u_int8_t channel) Valid values are between 20 and 100 (including). */ int sangoma_interface::tdm_enable_rbs_events(int polls_per_second) { - return sangoma_tdm_enable_rbs_events(sangoma_dev, &wp_api,polls_per_second); + SANGOMA_INIT_TDM_API_CMD(wp_api); + return sangoma_tdm_enable_rbs_events(sangoma_dev, &wp_api, polls_per_second); } /* Stop monitoring change in state of RBS bits */ int sangoma_interface::tdm_disable_rbs_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_disable_rbs_events(sangoma_dev, &wp_api); } /* Activate ISDN BRI line. */ int sangoma_interface::tdm_front_end_activate() { - return sangoma_set_fe_status(sangoma_dev, &wp_api,WAN_FE_CONNECTED); + SANGOMA_INIT_TDM_API_CMD(wp_api); + return sangoma_set_fe_status(sangoma_dev, &wp_api, WAN_FE_CONNECTED); } /* De-activate ISDN BRI line. */ int sangoma_interface::tdm_front_end_deactivate() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_set_fe_status(sangoma_dev, &wp_api, WAN_FE_DISCONNECTED); } /* get current state of the line - is it Connected or Disconnected */ int sangoma_interface::tdm_get_front_end_status(unsigned char *status) { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_get_fe_status(sangoma_dev, &wp_api, status); } /* Milliseconds interval between receive of Voice Data */ int sangoma_interface::tdm_set_user_period(unsigned int usr_period) { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_set_usr_period(sangoma_dev, &wp_api, usr_period); } int sangoma_interface::stop() { - int wait_counter = 0; + int wait_counter = 0, i; DBG_IFACE("%s()\n", __FUNCTION__); INFO_IFACE("Stopping."); terminate_tx_rx_threads = 1; - if(sng_wait_obj){ - sangoma_wait_obj_signal(sng_wait_obj); + for (i = 0; i < SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS; i++) { + if(sng_wait_obj[i]){ + sangoma_wait_obj_signal(sng_wait_obj[i]); + } } while(terminate_tx_rx_threads == 1 && wait_counter++ < 5){ @@ -1362,20 +1418,25 @@ void sangoma_interface::TxThreadFunc() void sangoma_interface::RxThreadFunc() { int iResult; - u_int32_t input_flags[NUMBER_OF_WAIT_OBJECTS], output_flags[NUMBER_OF_WAIT_OBJECTS]; - - input_flags[0] = (POLLIN | POLLPRI); + u_int32_t output_flags[SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS]; + u_int32_t input_flags[SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS]; + input_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT] = (WP_POLLIN | WP_POLLPRI); + INFO_IFACE("\n%s: %s() - start\n", device_name, __FUNCTION__); #if defined(__WINDOWS__) INFO_IFACE("ThreadID: %d - Start\n", ::GetCurrentThreadId()); #endif + if (program_settings.real_time) { + sng_set_thread_priority_to_real_time(); + } + while(terminate_tx_rx_threads == 0){ - iResult = sangoma_waitfor_many(&sng_wait_obj, + iResult = sangoma_waitfor_many(sng_wait_obj, input_flags, output_flags, - NUMBER_OF_WAIT_OBJECTS, + SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS, 5000 /* Wait timeout, in milliseconds. Or SANGOMA_INFINITE_API_POLL_WAIT. */ ); if(terminate_tx_rx_threads){ @@ -1391,21 +1452,22 @@ void sangoma_interface::RxThreadFunc() case SANG_STATUS_SUCCESS: /* a wait object was signaled */ - if(output_flags[0] & POLLIN){ + if(output_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT] & WP_POLLIN){ /* data */ if(read_data()){ ERR_IFACE("Error in read_data()!\n"); } } - if(output_flags[0] & POLLPRI){ + if(output_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT] & WP_POLLPRI){ if(read_event()){ ERR_IFACE("Error in read_event()!\n"); } } - if(!output_flags[0] || (output_flags[0] & (~input_flags[0])) ){ - WARN_IFACE("\nUnexpected output_flags[0]: 0x%X\n\n", output_flags[0]); + if( output_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT] & (~input_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT]) ){ + ERR_IFACE("\nUnexpected output_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT]: 0x%X\n\n", output_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT]); + iResult = SANG_STATUS_IO_ERROR; } break; @@ -1430,7 +1492,7 @@ int sangoma_interface::read_event() { int err; - memset(&wp_api, 0, sizeof(wp_api)); + SANGOMA_INIT_TDM_API_CMD(wp_api); err = sangoma_read_event(sangoma_dev, &wp_api); if(err){ @@ -1481,6 +1543,13 @@ int sangoma_interface::read_data() #if DBG_TIMING debug_update_timediff(&wan_debug_rx_timing, __FUNCTION__); + if(1){ + static int dbg_counter = 0; + dbg_counter++; + if(!(dbg_counter % 100)){ + debug_print_dbg_struct(&wan_debug_rx_timing, "sangoma_interface::read_data"); + } + } #endif break; @@ -1541,48 +1610,73 @@ int sangoma_interface::write_data(wp_api_hdr_t *hdr, void *tx_buffer) int sangoma_interface::transmit(wp_api_hdr_t *hdr, void *data) { - int iResult; - u_int32_t input_flags[NUMBER_OF_WAIT_OBJECTS], output_flags[NUMBER_OF_WAIT_OBJECTS]; + int iResult, retry_wait; + u_int32_t output_flags[SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS]; + u_int32_t input_flags[SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS]; - input_flags[0] = (POLLOUT); + input_flags[SANGOMA_TX_WAIT_OBJECT] = (WP_POLLOUT); - iResult = sangoma_waitfor_many(&sng_wait_obj, - input_flags, - output_flags, - NUMBER_OF_WAIT_OBJECTS, - 2000 /* wait timeout, in milliseconds */); + do { - switch(iResult) - { - case SANG_STATUS_APIPOLL_TIMEOUT: - //Timeout. It is possible line is disconnected. - DBG_IFACE("%s: Tx Timeout!\n", device_name); - return SANG_STATUS_TX_TIMEOUT; + iResult = sangoma_waitfor_many(sng_wait_obj, + input_flags, + output_flags, + SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS, + 2000 /* wait timeout, in milliseconds */); - case SANG_STATUS_SUCCESS: - /* a wait object was signaled */ - if(output_flags[0] & POLLOUT){ - /* POLLOUT bit is set - there is at least one free Tx buffer. */ - iResult = write_data(hdr, data); - if(SANG_ERROR(iResult)){ - ERR_IFACE("Error in write_data()!\n"); + retry_wait = 0; + switch(iResult) + { + case SANG_STATUS_APIPOLL_TIMEOUT: + //Timeout. It is possible line is disconnected. + DBG_IFACE("%s: Tx Timeout!\n", device_name); + return SANG_STATUS_TX_TIMEOUT; + + case SANG_STATUS_SUCCESS: + /* a wait object was signaled */ + if(output_flags[SANGOMA_TX_WAIT_OBJECT] & WP_POLLOUT){ + /* WP_POLLOUT bit is set - there is at least one free Tx buffer. */ + iResult = write_data(hdr, data); + if(SANG_ERROR(iResult)){ + ERR_IFACE("Error in write_data()! iResult:%d\n", iResult); + } } - } - if(!output_flags[0] || (output_flags[0] & (~input_flags[0])) ){ - WARN_IFACE("\nUnexpected output_flags[0]: 0x%X\n\n", output_flags[0]); - } - break; + if(!output_flags[SANGOMA_TX_WAIT_OBJECT]){ + // + //For case (1) when there are multiple objects in sng_wait_obj[], + //the wait was woken up by another object in the array. + // + //For case (2) when there is a single object in sng_wait_obj[], + //the Tx wait was woken up by Rx Data or Event. + //This sitation is possible because for each Interface, + //at the kernel-mode driver level, there is a + //SINGLE signalling object which can be signalled for THREE reasons: + //Rx Data, API Event AND by availability of free Tx buffer. + // + //For both cases (1) and (2) the right action is to + //retry the wait for free Tx buffer. + // + retry_wait = 1; + } - default: - /* error */ - ERR_IFACE("iResult: %s (%d)\n", SDLA_DECODE_SANG_STATUS(iResult), iResult); - if(SANG_STATUS_FAILED_ALLOCATE_MEMORY == iResult){ - INFO_IFACE("Fatal Error. Press any key to exit the application.\n"); - _getch(); - exit(1); - } - }//switch(iResult) + if( output_flags[SANGOMA_TX_WAIT_OBJECT] & (~input_flags[SANGOMA_TX_WAIT_OBJECT]) ){ + ERR_IFACE("\nUnexpected output_flags[SANGOMA_TX_WAIT_OBJECT]: 0x%X\n\n", output_flags[SANGOMA_TX_WAIT_OBJECT]); + iResult = SANG_STATUS_IO_ERROR; + } + break; + + default: + /* error */ + ERR_IFACE("iResult: %s (%d)\n", SDLA_DECODE_SANG_STATUS(iResult), iResult); + if(SANG_STATUS_FAILED_ALLOCATE_MEMORY == iResult){ + INFO_IFACE("Fatal Error. Press any key to exit the application.\n"); + _getch(); + exit(1); + } + }//switch(iResult) + + } while(retry_wait); return iResult; } @@ -1590,50 +1684,50 @@ int sangoma_interface::transmit(wp_api_hdr_t *hdr, void *data) /////////////////////////////////////////////////////////////////////// int sangoma_interface::start_ring_tone() { - DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__); + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_tone_events(sangoma_dev, &wp_api, WP_API_EVENT_TONE_RING); } /////////////////////////////////////////////////////////////////////// int sangoma_interface::start_congestion_tone() { - DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__); + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_tone_events(sangoma_dev, &wp_api, WP_API_EVENT_TONE_CONGESTION); } /////////////////////////////////////////////////////////////////////// int sangoma_interface::start_busy_tone() { - DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__); + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_tone_events(sangoma_dev, &wp_api, WP_API_EVENT_TONE_BUSY); } /////////////////////////////////////////////////////////////////////// int sangoma_interface::start_dial_tone() { - DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__); + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_tone_events(sangoma_dev, &wp_api, WP_API_EVENT_TONE_DIAL); } /////////////////////////////////////////////////////////////////////// int sangoma_interface::stop_all_tones() { - DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__); + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_disable_tone_events(sangoma_dev, &wp_api); } /////////////////////////////////////////////////////////////////////// int sangoma_interface::start_ringing_phone() { - DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__); + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_ring_events(sangoma_dev, &wp_api); } int sangoma_interface::stop_ringing_phone() { - DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__); + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_disable_ring_events(sangoma_dev, &wp_api); } /////////////////////////////////////////////////////////////////////// int sangoma_interface::fxo_go_off_hook() { - DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__); + SANGOMA_INIT_TDM_API_CMD(wp_api); if(wanif_conf_struct.sub_media != MOD_TYPE_FXO){ ERR_IFACE( "%s: The 'Go Off Hook' command valid only for FXO!\n", device_name); @@ -1645,19 +1739,21 @@ int sangoma_interface::fxo_go_off_hook() /////////////////////////////////////////////////////////////////////// int sangoma_interface::fxs_txsig_offhook() { - DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__); + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_txsig_offhook(sangoma_dev,&wp_api); } int sangoma_interface::fxo_go_on_hook() { DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__); + + SANGOMA_INIT_TDM_API_CMD(wp_api); if(wanif_conf_struct.sub_media != MOD_TYPE_FXO){ ERR_IFACE( "%s: The 'Go On Hook' command valid only for FXO!\n", device_name); return 1; } - return sangoma_tdm_txsig_onhook(sangoma_dev,&wp_api); + return sangoma_tdm_txsig_onhook(sangoma_dev, &wp_api); } //set a Telephony interface to it's default state @@ -1793,7 +1889,7 @@ int sangoma_api_ctrl_dev::init(callback_functions_t *callback_functions_ptr) return 1; } - if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj, sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){ + if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj[0], sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){ ERR_IFACE("Failed to create 'sangoma_wait_object' for %s\n", device_name); return 1; } @@ -1833,7 +1929,7 @@ int sangoma_api_logger_dev::init(callback_functions_t *callback_functions_ptr) return 1; } - if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj, sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){ + if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj[0], sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){ ERR_IFACE("Failed to create 'sangoma_wait_object' for %s\n", device_name); return 1; } @@ -1930,26 +2026,40 @@ int sangoma_api_logger_dev::get_logger_dev_operational_stats(wp_logger_stats_t * memcpy(stats, &logger_cmd.stats, sizeof(*stats)); INFO_IFACE("*** Logger Device Statistics ***\n"); - INFO_IFACE("\trx_events\t: %u\n", stats->rx_events); - INFO_IFACE("\trx_events_dropped\t: %u\n", stats->rx_events_dropped); - INFO_IFACE("\tmax_event_queue_length\t: %u\n", stats->max_event_queue_length); - INFO_IFACE("\tcurrent_number_of_events_in_event_queue\t: %u\n", stats->current_number_of_events_in_event_queue); + INFO_IFACE("\trx_events\t: %lu\n", stats->rx_events); + INFO_IFACE("\trx_events_dropped\t: %lu\n", stats->rx_events_dropped); + INFO_IFACE("\tmax_event_queue_length\t: %lu\n", stats->max_event_queue_length); + INFO_IFACE("\tcurrent_number_of_events_in_event_queue\t: %lu\n", stats->current_number_of_events_in_event_queue); INFO_IFACE("\n"); #endif return err; } #ifdef WP_API_FEATURE_LIBSNG_HWEC + +#define WP_HWEC_USE_OPTIONAL_CHIP_CONFIG_PARAMS 1 + /* NOTE: HWEC must NOT be enabled on a d-channel. The 'in_ulChannelMap' should be - * the bitmap of voice channels only. */ + * the bitmap of voice channel(s) only. */ sangoma_status_t config_hwec(char *strDeviceName, unsigned long in_ulChannelMap) { sangoma_status_t rc; +#if WP_HWEC_USE_OPTIONAL_CHIP_CONFIG_PARAMS + wan_custom_param_t custom_params[1];//Optional paramter(s) for chip-wide initialization +#endif DBG_IFACE("%s(): strDeviceName: %s, in_ulChannelMap: 0x%X\n", __FUNCTION__, strDeviceName, in_ulChannelMap); - // Initialize the echo canceller (done once per-physical card) - rc = sangoma_hwec_config_init(strDeviceName); + // Optionally disable output from HWEC API Library and From API Driver. + //sangoma_hwec_config_verbosity(0); + + // Initialize the echo canceller (done once per-port) +#if WP_HWEC_USE_OPTIONAL_CHIP_CONFIG_PARAMS + sangoma_hwec_initialize_custom_parameter_structure(&custom_params[0], "WANEC_EnableAcousticEcho", "TRUE"); + rc = sangoma_hwec_config_init(strDeviceName, custom_params, sizeof(custom_params)/sizeof(custom_params[0])); +#else + rc = sangoma_hwec_config_init(strDeviceName, NULL, 0); +#endif if (SANG_STATUS_SUCCESS != rc) { ERR_IFACE( "Failed to initialize echo canceller. rc: %d\n", rc); return rc; @@ -1982,10 +2092,10 @@ sangoma_status_t config_hwec(char *strDeviceName, unsigned long in_ulChannelMap) } #if 0 -/* "WANEC_SoutAdaptiveNoiseReduction", "WANEC_TailDisplacement", "WANEC_DtmfToneRemoval", "WANEC_AcousticEcho"...*/ + /* "WANEC_SoutAdaptiveNoiseReduction", "WANEC_TailDisplacement", "WANEC_DtmfToneRemoval", "WANEC_AcousticEcho"...*/ // Optionally, Enable noise reduction from PSTN - rc = sangoma_hwec_config_channel_parameters(strDeviceName, + rc = sangoma_hwec_config_channel_parameter(strDeviceName, "WANEC_SoutAdaptiveNoiseReduction", "TRUE", in_ulChannelMap ); @@ -1993,6 +2103,15 @@ sangoma_status_t config_hwec(char *strDeviceName, unsigned long in_ulChannelMap) ERR_IFACE( "Failed to enable noise reduction.\n" ); return rc; } + + rc = sangoma_hwec_config_channel_parameter(strDeviceName, + "WANEC_TailDisplacement", + "32", + in_ulChannelMap ); + if (SANG_STATUS_SUCCESS != rc) { + ERR_IFACE( "Failed to change HWEC tail displacement.\n" ); + return rc; + } #endif return SANG_STATUS_SUCCESS; diff --git a/api/libsangoma/sample_cpp/.svn/text-base/sangoma_interface.h.svn-base b/api/libsangoma/sample_cpp/.svn/text-base/sangoma_interface.h.svn-base index 9d23857..3154e78 100644 --- a/api/libsangoma/sample_cpp/.svn/text-base/sangoma_interface.h.svn-base +++ b/api/libsangoma/sample_cpp/.svn/text-base/sangoma_interface.h.svn-base @@ -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); diff --git a/api/libsangoma/sample_cpp/.svn/text-base/sangoma_port.cpp.svn-base b/api/libsangoma/sample_cpp/.svn/text-base/sangoma_port.cpp.svn-base index 61ff638..3c6be03 100644 --- a/api/libsangoma/sample_cpp/.svn/text-base/sangoma_port.cpp.svn-base +++ b/api/libsangoma/sample_cpp/.svn/text-base/sangoma_port.cpp.svn-base @@ -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; diff --git a/api/libsangoma/sample_cpp/.svn/text-base/sangoma_port.h.svn-base b/api/libsangoma/sample_cpp/.svn/text-base/sangoma_port.h.svn-base index a4c4fc0..6156d42 100644 --- a/api/libsangoma/sample_cpp/.svn/text-base/sangoma_port.h.svn-base +++ b/api/libsangoma/sample_cpp/.svn/text-base/sangoma_port.h.svn-base @@ -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); diff --git a/api/libsangoma/sample_cpp/.svn/text-base/sangoma_port_configurator.cpp.svn-base b/api/libsangoma/sample_cpp/.svn/text-base/sangoma_port_configurator.cpp.svn-base index fc94b4f..90fee14 100644 --- a/api/libsangoma/sample_cpp/.svn/text-base/sangoma_port_configurator.cpp.svn-base +++ b/api/libsangoma/sample_cpp/.svn/text-base/sangoma_port_configurator.cpp.svn-base @@ -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; diff --git a/api/libsangoma/sample_cpp/.svn/text-base/sangoma_port_configurator.h.svn-base b/api/libsangoma/sample_cpp/.svn/text-base/sangoma_port_configurator.h.svn-base index f327ba6..3d00249 100644 --- a/api/libsangoma/sample_cpp/.svn/text-base/sangoma_port_configurator.h.svn-base +++ b/api/libsangoma/sample_cpp/.svn/text-base/sangoma_port_configurator.h.svn-base @@ -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); diff --git a/api/libsangoma/sample_cpp/.svn/text-base/sources.svn-base b/api/libsangoma/sample_cpp/.svn/text-base/sources.svn-base index 1e48e55..78e1955 100644 --- a/api/libsangoma/sample_cpp/.svn/text-base/sources.svn-base +++ b/api/libsangoma/sample_cpp/.svn/text-base/sources.svn-base @@ -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 \ diff --git a/api/libsangoma/sample_cpp/sample.cpp b/api/libsangoma/sample_cpp/sample.cpp index 06a149a..7570130 100644 --- a/api/libsangoma/sample_cpp/sample.cpp +++ b/api/libsangoma/sample_cpp/sample.cpp @@ -59,17 +59,12 @@ callback_functions_t callback_functions; * Prototypes & Defines *****************************************************************/ -static int got_rx_data(void *sang_if_ptr, void *rx_data); +static int got_rx_data(void *sang_if_ptr, void *rxhdr, void *rx_data); static void got_tdm_api_event(void *sang_if_ptr, void *event_data); #if USE_WP_LOGGER static void got_logger_event(void *sang_if_ptr, wp_logger_event_t *logger_event); #endif -typedef struct{ - void *sang_if_ptr; - wp_api_event_t event; -}TDM_API_EVENT_THREAD_PARAM; - #if USE_STELEPHONY_API //Sangoma Telephony API (Stelephony.dll) provides the following telephony services: @@ -88,13 +83,6 @@ CRITICAL_SECTION PrintCriticalSection; //critical section for TDM events CRITICAL_SECTION TdmEventCriticalSection; -#if defined (__WINDOWS__) -DWORD TdmApiEventThreadFunc(LPDWORD lpdwParam); -#else -void *TdmApiEventThreadFunc(void *lpdwParam); -#endif - - /***************************************************************** * Debugging Macros *****************************************************************/ @@ -195,9 +183,9 @@ void PrintRxData(wp_api_hdr_t *hdr, void *pdata) if(program_settings.silent){ if((rx_counter % 1000) == 0){ INFO_MAIN("Rx counter: %d, Rx datlen: %d\n", rx_counter, datlen); -#if 0 +#if 1 INFO_MAIN("Timestamp: Seconds: %d, Microseconds: %d\n", - hdr->wp_api_hdr_time_stamp_sec, hdr->wp_api_hdr_time_stamp_use); + hdr->time_stamp_sec, hdr->time_stamp_usec); #endif } return; @@ -222,10 +210,13 @@ void PrintRxData(wp_api_hdr_t *hdr, void *pdata) /*! \fn static int got_rx_data(void *sang_if_ptr, void *rx_data) - \brief Callback function indicating data rx is pending + \brief Callback function indicating data rx is pending. \param sang_if_ptr sangoma interface pointer \param rx_data API data element strcutre containt header + data \return 0 - ok non-zero - Error + + This function must return as fast as possible + because it is called from real time receiver thread. */ static int got_rx_data(void *sang_if_ptr, void *rxhdr, void *rx_data) { @@ -267,71 +258,33 @@ static int got_rx_data(void *sang_if_ptr, void *rxhdr, void *rx_data) \param event_data API event element strcutre containt header + data \return 0 - ok non-zero - Error - Currently Windows launches a thread to handle the event, where - Linux handles the event directly. Implementation is left to the user. + + Handling of Events must be done OUTSIDE of the REAL-TIME Rx thread + because it may make take a lot of time. + Create a special thread for Event hadling Or push Event into + a queue - implentation is left to the user. + In this example event is handled directly. */ static void got_tdm_api_event(void *sang_if_ptr, void *event_data) { - TDM_API_EVENT_THREAD_PARAM *param = - (TDM_API_EVENT_THREAD_PARAM*)malloc(sizeof(TDM_API_EVENT_THREAD_PARAM)); - - if(param == NULL){ - ERR_MAIN("Failed to allocate memory for 'Event Thread parameter'!!\n"); - return; - } - - memcpy(¶m->event, event_data, sizeof(wp_api_event_t)); - param->sang_if_ptr = sang_if_ptr; - - ////////////////////////////////////////////////////////////////////// - //Handling of Events must be done OUTSIDE of the REAL-TIME Rx thread// - //because it may make take a lot of time. // - //Create a special thread for Event hadling. // - ////////////////////////////////////////////////////////////////////// -#if defined(__WINDOWS__) - DWORD dwThreadId; - - if(CreateThread( - NULL, /* no security attributes */ - 0, /* use default stack size */ - (LPTHREAD_START_ROUTINE)TdmApiEventThreadFunc, /* thread function */ - param, /* argument to thread function */ - 0, /* use default creation flags */ - &dwThreadId /* returns the thread identifier */ - ) == NULL){ - ERR_MAIN("Failed to create 'TdmApiEvent' thread!!\n"); - } -#else - //FIXME: implement the thread. Consider using sangoma_cthread class. - TdmApiEventThreadFunc(param); -#endif -} - -/*! - \fn void *TdmApiEventThreadFunc(void *lpdwParam) - \brief Event handling Function - \param lpdwParam pointer to the span/chan device - \return void -*/ -#if defined(__WINDOWS__) -DWORD TdmApiEventThreadFunc(LPDWORD lpdwParam) -#else -void *TdmApiEventThreadFunc(void *lpdwParam) -#endif -{ - TDM_API_EVENT_THREAD_PARAM *param; - sangoma_interface *sang_if; - wp_api_event_t *wp_tdm_api_event; + sangoma_interface *sang_if = (sangoma_interface *)sang_if_ptr; + wp_api_event_t *wp_tdm_api_event = (wp_api_event_t *)event_data; + wan_time_t wan_time; + char *timestamp_str; EnterCriticalSection(&TdmEventCriticalSection); - param = (TDM_API_EVENT_THREAD_PARAM*)lpdwParam; + /* Windows: wan_time is 64bit, time_stamp_sec is 32bit + * Linux: wan_time and time_stamp_sec is 32bit */ + wan_time = wp_tdm_api_event->time_stamp_sec; + timestamp_str = sangoma_ctime( &wan_time ); - wp_tdm_api_event = ¶m->event; - sang_if = (sangoma_interface*)param->sang_if_ptr; + /* Display Logger Event Timestamp as UNIX-style Date string. */ + /*DBG_MAIN("Time and Date:\t\t%s\n", (timestamp_str == NULL ? "Invalid Timestamp" : timestamp_str));*/ - DBG_MAIN("%s(): ifname: %s: Span: %d, Channel: %d\n", __FUNCTION__, sang_if->device_name, - wp_tdm_api_event->wp_api_event_span, wp_tdm_api_event->wp_api_event_channel); + DBG_MAIN("%s(): Span: %d, Channel: %d (Seconds:%u, Microseconds:%u)\n", __FUNCTION__, + wp_tdm_api_event->wp_api_event_span, wp_tdm_api_event->wp_api_event_channel, + wp_tdm_api_event->time_stamp_sec, wp_tdm_api_event->time_stamp_usec); switch(wp_tdm_api_event->wp_api_event_type) { @@ -340,7 +293,6 @@ void *TdmApiEventThreadFunc(void *lpdwParam) wp_tdm_api_event->wp_api_event_dtmf_digit, (wp_tdm_api_event->wp_api_event_dtmf_port == WAN_EC_CHANNEL_PORT_ROUT)?"ROUT":"SOUT", (wp_tdm_api_event->wp_api_event_dtmf_type == WAN_EC_TONE_PRESENT)?"PRESENT":"STOP"); - break; case WP_API_EVENT_RXHOOK: @@ -395,10 +347,8 @@ void *TdmApiEventThreadFunc(void *lpdwParam) break; } - free(lpdwParam); LeaveCriticalSection(&TdmEventCriticalSection); - //Done with the Event, exit the thread. - return 0; + return; } #if USE_WP_LOGGER @@ -567,6 +517,8 @@ static int parse_command_line_args(int argc, char* argv[]) #ifdef WP_API_FEATURE_LIBSNG_HWEC "\t-use_hwec \tInitialize/Configure/Use the Hardware Echo Canceller\n" #endif +"\t-real_time \tRun the Program at real-time priority. This maybe\n" +"\t \t\timportant when Audio stream is used for timing.\n" "\n" "Example: sample -c 1 -i 1\n"; @@ -686,9 +638,11 @@ static int parse_command_line_args(int argc, char* argv[]) i++; INFO_MAIN("Setting rxgain to %d.\n", program_settings.txgain); }else if(_stricmp(argv[i], "-use_hwec") == 0){ - INFO_MAIN("Using hardware echo canceller...\n"); program_settings.use_hardware_echo_canceller = 1; + }else if(_stricmp(argv[i], "-real_time") == 0){ + INFO_MAIN("Will be running at real-time priority...\n"); + program_settings.real_time = 1; }else{ INFO_MAIN("Error: Invalid Argument %s\n",argv[i]); return 1; @@ -751,6 +705,10 @@ int __cdecl main(int argc, char* argv[]) InitializeCriticalSection(&PrintCriticalSection); InitializeCriticalSection(&TdmEventCriticalSection); + if (program_settings.real_time) { + sng_set_process_priority_to_real_time(); + } + //////////////////////////////////////////////////////////////////////////// //User may provide Wanpipe Number and Interface Number as a command line arguments: INFO_MAIN("Using wanpipe_number: %d, interface_number: %d\n", program_settings.wanpipe_number, program_settings.interface_number); @@ -842,7 +800,7 @@ int __cdecl main(int argc, char* argv[]) INFO_MAIN("Press 'd' to disable bri bchan loopback\n"); break; } - INFO_MAIN("Press 'o' to enable DTMF events (on Octasic chip)\n"); + INFO_MAIN("Press 'o' to control DTMF events on DSP (Octasic)\n"); if (program_settings.encode_sw_dtmf) { INFO_MAIN("Press 'x' to send software DTMF\n"); } diff --git a/api/libsangoma/sample_cpp/sample.h b/api/libsangoma/sample_cpp/sample.h index d563360..80bd6c2 100644 --- a/api/libsangoma/sample_cpp/sample.h +++ b/api/libsangoma/sample_cpp/sample.h @@ -32,6 +32,7 @@ typedef struct{ int txgain; int rxgain; unsigned char use_hardware_echo_canceller; + unsigned char real_time; }wp_program_settings_t; #define DEV_NAME_LEN 100 @@ -63,9 +64,9 @@ typedef struct{ }callback_functions_t; +#if defined (__WINDOWS__) static void DecodeLastError(LPSTR lpszFunction) { -#if defined (__WINDOWS__) LPVOID lpMsgBuf; DWORD dwLastErr = GetLastError(); FormatMessage( @@ -83,8 +84,32 @@ static void DecodeLastError(LPSTR lpszFunction) printf("Last Error: %s (GetLastError() returned: %d)\n", (char*)lpMsgBuf, dwLastErr); // Free the buffer. LocalFree( lpMsgBuf ); -#endif } +#endif + +//This Program interfaces directly to hardware, it should be real time. +static void sng_set_process_priority_to_real_time() +{ +#if defined (__WINDOWS__) + if (!SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)) { + printf("Failed to set program priority!\n"); + } +#else + //TODO: implement for Linux +#endif +} + +//This Execution Thread interfaces directly to hardware, it should be real time. +static void sng_set_thread_priority_to_real_time() +{ +#if defined (__WINDOWS__) + if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL)) { + printf("Failed to set thread priority!\n"); + } +#else + //TODO: implement for Linux +#endif +} /* This flag controls debugging of time difference between * data receive indications. Disabled by default. */ @@ -118,13 +143,14 @@ debug_print_dbg_struct( const char *caller_name ) { - printf("timediff_deviation_counter: %d\n\tTimeDiff (ms) between '%s()':\n\tHighest:%d Lowest:%d Expected: %d Latest: %d\n", + printf("timediff_deviation_counter: %d\n\tTimeDiff (ms) between '%s()':\n\tHighest:%d Lowest:%d Expected: %d Latest: %d allowed deviation:%d\n", wan_debug_ptr->timediff_deviation_counter, caller_name, wan_debug_ptr->highest_timediff, wan_debug_ptr->lowest_timediff, wan_debug_ptr->high_resolution_timediff_value, - wan_debug_ptr->latest_timediff); + wan_debug_ptr->latest_timediff, + wan_debug_ptr->allowed_deviation_of_timediff_value); } /* Call this function to mesure TimeDiff between some function call. */ diff --git a/api/libsangoma/sample_cpp/sangoma_interface.cpp b/api/libsangoma/sample_cpp/sangoma_interface.cpp index 50265f0..fb6bd58 100644 --- a/api/libsangoma/sample_cpp/sangoma_interface.cpp +++ b/api/libsangoma/sample_cpp/sangoma_interface.cpp @@ -15,8 +15,6 @@ #define DO_COMMAND(wan_udp) DoManagementCommand(sangoma_dev, &wan_udp); -#define NUMBER_OF_WAIT_OBJECTS 1 - #ifdef WP_API_FEATURE_LIBSNG_HWEC /* defined in wanpipe_api_iface.h */ # include "wanpipe_events.h" # include "wanec_api.h" @@ -32,7 +30,8 @@ sangoma_interface::sangoma_interface(int wanpipe_number, int interface_number) memset(device_name, 0x00, DEV_NAME_LEN); memset(&wan_udp, 0x00, sizeof(wan_udp)); memset(&tdm_api_cmd, 0x00, sizeof(tdm_api_cmd)); - memset(&wp_api, 0x00, sizeof(wp_api)); + + SANGOMA_INIT_TDM_API_CMD(wp_api); WanpipeNumber = wanpipe_number; InterfaceNumber = interface_number; @@ -47,7 +46,7 @@ sangoma_interface::sangoma_interface(int wanpipe_number, int interface_number) terminate_tx_rx_threads = 0; is_rbs_monitoring_enabled = 0; - sng_wait_obj = NULL; + memset(sng_wait_obj, 0x00, sizeof(sng_wait_obj)); ////////////////////////////////////////////////////////////////// //receive stuff @@ -79,7 +78,8 @@ sangoma_interface::sangoma_interface(int wanpipe_number, int interface_number) memset(&wan_debug_rx_timing, 0x00, sizeof(wan_debug_t)); debug_set_timing_info( &wan_debug_rx_timing, 20 /* expected timediff in milliseconds */, - 2 /* allowed deviation from expected timediff */); + 2 /* allowed deviation from expected timediff + * (allowed_deviation_of_timediff_value) */); #endif } @@ -95,16 +95,17 @@ int sangoma_interface::init(callback_functions_t *callback_functions_ptr) memcpy(&callback_functions, callback_functions_ptr, sizeof(callback_functions_t)); + DBG_IFACE("%s(): WanpipeNumber: %d, InterfaceNumber: %d\n", __FUNCTION__, WanpipeNumber, InterfaceNumber); //////////////////////////////////////////////////////////////////////////// //open handle for reading and writing data, for events reception and other commands - sangoma_dev = open_api_device(); + sangoma_dev = sangoma_open_api_span_chan(WanpipeNumber, InterfaceNumber); if (sangoma_dev == INVALID_HANDLE_VALUE){ ERR_IFACE( "Unable to open %s for Rx/Tx!\n", device_name); return 1; } - if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj, sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){ - ERR_IFACE("Failed to create 'sangoma_wait_object' for %s\n", device_name); + if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj[SANGOMA_TX_WAIT_OBJECT], sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){ + ERR_IFACE("Failed to create 'Tx/Rx/Event WAIT_OBJECT' for %s\n", device_name); return 1; } @@ -182,13 +183,6 @@ int sangoma_interface::init(callback_functions_t *callback_functions_ptr) return 0; } -sng_fd_t sangoma_interface::open_api_device() -{ - DBG_IFACE("%s(): WanpipeNumber: %d, InterfaceNumber: %d\n", __FUNCTION__, WanpipeNumber, InterfaceNumber); - - return sangoma_open_api_span_chan(WanpipeNumber, InterfaceNumber); -} - void sangoma_interface::generate_bit_rev_table(void) { unsigned char util_char; @@ -589,6 +583,8 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats) { int err; unsigned char firm_ver, cpld_ver; + + SANGOMA_INIT_TDM_API_CMD(wp_api); err=sangoma_get_stats(sangoma_dev, &wp_api, stats); if (err) { @@ -612,9 +608,11 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats) INFO_IFACE("\trx_length_errors: %u\n", stats->rx_length_errors); INFO_IFACE("\trx_over_errors\t: %u\n", stats->rx_over_errors); INFO_IFACE("\trx_crc_errors\t: %u\n", stats->rx_crc_errors); //HDLC CRC mismatch - INFO_IFACE("\trx_frame_errors\t: %u\n", stats->rx_frame_errors);//HDLC "abort" occured + INFO_IFACE("\trx_frame_errors\t: %u\n", stats->rx_frame_errors);//HDLC Frame Start or Stop Flag is missing INFO_IFACE("\trx_fifo_errors\t: %u\n", stats->rx_fifo_errors); INFO_IFACE("\trx_missed_errors: %u\n", stats->rx_missed_errors); + INFO_IFACE("\trx_hdlc_abort_counter: %u\n", stats->rx_hdlc_abort_counter);//Transmitter aborted frame transmission. + //Not an error. INFO_IFACE("\ttx_aborted_errors: %u\n", stats->tx_aborted_errors); INFO_IFACE("\tTx Idle Data\t: %u\n", stats->tx_carrier_errors); @@ -637,6 +635,7 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats) INFO_IFACE("\tHWEC tone (DTMF) events counter: %u\n", stats->rx_events_tone); INFO_IFACE( "*********************************\n"); + SANGOMA_INIT_TDM_API_CMD(wp_api); err=sangoma_get_driver_version(sangoma_dev,&wp_api, NULL); if (err) { return 1; @@ -647,6 +646,7 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats) wp_api.wp_cmd.version.minor1, wp_api.wp_cmd.version.minor2); + SANGOMA_INIT_TDM_API_CMD(wp_api); err=sangoma_get_firmware_version(sangoma_dev, &wp_api, &firm_ver); if (err) { return 1; @@ -654,6 +654,7 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats) INFO_IFACE("\tFirmware Version: %X\n", firm_ver); + SANGOMA_INIT_TDM_API_CMD(wp_api); err=sangoma_get_cpld_version(sangoma_dev, &wp_api, &cpld_ver); if (err) { return 1; @@ -669,11 +670,13 @@ int sangoma_interface::get_operational_stats(wanpipe_chan_stats_t *stats) int sangoma_interface::flush_operational_stats() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_flush_stats(sangoma_dev,&wp_api); } int sangoma_interface::flush_tx_buffers() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_flush_bufs(sangoma_dev,&wp_api); } @@ -702,6 +705,7 @@ int sangoma_interface::enable_rbs_monitoring() // set Idle Transmit flag (BitStream/Voice only). int sangoma_interface::set_tx_idle_flag(unsigned char new_idle_flag) { + SANGOMA_INIT_TDM_API_CMD(wp_api); tdm_api_cmd.cmd = WP_API_CMD_SET_IDLE_FLAG; tdm_api_cmd.idle_flag = new_idle_flag; return tdmv_api_ioctl(&tdm_api_cmd); @@ -712,6 +716,7 @@ char sangoma_interface::get_rbs(rbs_management_t *rbs_management_ptr) { int err; + SANGOMA_INIT_TDM_API_CMD(wp_api); err=sangoma_tdm_read_rbs(sangoma_dev, &wp_api, rbs_management_ptr->channel, &rbs_management_ptr->ABCD_bits); if (err) { ERR_IFACE( "Error: command WANPIPEMON_GET_RBS_BITS failed!\n"); @@ -736,6 +741,7 @@ char sangoma_interface::set_rbs(rbs_management_t *rbs_management_ptr) { int err; + SANGOMA_INIT_TDM_API_CMD(wp_api); err=sangoma_tdm_write_rbs(sangoma_dev, &wp_api, rbs_management_ptr->channel, rbs_management_ptr->ABCD_bits); if (err) { return 1; @@ -833,6 +839,17 @@ int sangoma_interface::get_interface_configuration(if_cfg_t *wanif_conf_ptr) } INFO_IFACE( "****************************\n"); +#if 0 + // Audio Codec can be read for Voice interface. + // For Data interface this setting is ignored by the API. + SANGOMA_INIT_TDM_API_CMD(wp_api); + sangoma_get_hw_coding(sangoma_dev, &wp_api); + if (wp_api.wp_cmd.result == SANG_STATUS_SUCCESS) { + INFO_IFACE("Audio Codec: %s\n", + WP_CODEC_FORMAT_DECODE(wp_api.wp_cmd.hw_tdm_coding)); + } +#endif + return 0; } @@ -841,6 +858,7 @@ void sangoma_interface::get_api_driver_version (PDRIVER_VERSION version) int err; + SANGOMA_INIT_TDM_API_CMD(wp_api); err=sangoma_get_driver_version(sangoma_dev, &wp_api, version); if(err){ ERR_IFACE("Error: command READ_CODE_VERSION failed!\n"); @@ -874,6 +892,7 @@ void sangoma_interface::get_card_customer_id(u_int8_t *customer_id) int sangoma_interface::get_open_handles_counter() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_get_open_cnt(sangoma_dev,&wp_api); } @@ -883,12 +902,15 @@ int sangoma_interface::get_open_handles_counter() //receive data until the LAST handel is closed. void sangoma_interface::cleanup() { + int i; + INFO_IFACE("sangoma_interface::cleanup()\n"); - if(sng_wait_obj){ - sangoma_wait_obj_delete(&sng_wait_obj); + for (i = 0; i < SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS; i++) { + if(sng_wait_obj[i]){ + sangoma_wait_obj_delete(&sng_wait_obj[i]); + } } - #ifdef WIN32 if(sangoma_dev != INVALID_HANDLE_VALUE){ if(is_rbs_monitoring_enabled == 1){ @@ -924,7 +946,7 @@ int sangoma_interface::tdmv_api_ioctl(wanpipe_api_cmd_t *api_cmd) { int err; - memset(&wp_api, 0x00, sizeof(wp_api)); + SANGOMA_INIT_TDM_API_CMD(wp_api); memcpy(&wp_api.wp_cmd, api_cmd, sizeof(wanpipe_api_cmd_t)); @@ -937,11 +959,13 @@ int sangoma_interface::tdmv_api_ioctl(wanpipe_api_cmd_t *api_cmd) int sangoma_interface::tdm_enable_ring_detect_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_ring_detect_events(sangoma_dev,&wp_api); } int sangoma_interface::tdm_disable_ring_detect_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_disable_ring_detect_events(sangoma_dev,&wp_api); } @@ -950,13 +974,15 @@ int sangoma_interface::tdm_disable_ring_detect_events() * 1250 is most used value. To disable flash event set rxflashtime to 0 */ int sangoma_interface::tdm_control_flash_events(int rxflashtime) { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_set_rm_rxflashtime(sangoma_dev, &wp_api, rxflashtime); } int sangoma_interface::tdm_control_rm_txgain(int txgain) { #if WP_API_FEATURE_RM_GAIN - return sangoma_set_rm_tx_gain(sangoma_dev,&wp_api, txgain); + SANGOMA_INIT_TDM_API_CMD(wp_api); + return sangoma_set_rm_tx_gain(sangoma_dev, &wp_api, txgain); #else return SANG_STATUS_UNSUPPORTED_FUNCTION; #endif @@ -965,6 +991,7 @@ int sangoma_interface::tdm_control_rm_txgain(int txgain) int sangoma_interface::tdm_control_rm_rxgain(int rxgain) { #if WP_API_FEATURE_RM_GAIN + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_set_rm_rx_gain(sangoma_dev, &wp_api, rxgain); #else return SANG_STATUS_UNSUPPORTED_FUNCTION; @@ -973,96 +1000,117 @@ int sangoma_interface::tdm_control_rm_rxgain(int rxgain) int sangoma_interface::tdm_enable_ring_trip_detect_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_ring_trip_detect_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_disable_ring_trip_detect_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_disable_ring_trip_detect_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_enable_rm_dtmf_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_rm_dtmf_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_disable_rm_dtmf_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_disable_rm_dtmf_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_enable_dtmf_events(uint8_t channel) { + SANGOMA_INIT_TDM_API_CMD(wp_api); + wp_api.wp_cmd.chan = channel; return sangoma_tdm_enable_dtmf_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_disable_dtmf_events(uint8_t channel) { + SANGOMA_INIT_TDM_API_CMD(wp_api); + wp_api.wp_cmd.chan = channel; return sangoma_tdm_disable_dtmf_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_enable_rxhook_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_rxhook_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_disable_rxhook_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_disable_rxhook_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_enable_ring_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_ring_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_disable_ring_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_disable_ring_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_txsig_onhook() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_txsig_onhook(sangoma_dev, &wp_api); } int sangoma_interface::tdm_txsig_kewl() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_txsig_kewl(sangoma_dev, &wp_api); } int sangoma_interface::tdm_txsig_onhooktransfer() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_txsig_onhooktransfer(sangoma_dev, &wp_api); } int sangoma_interface::tdm_set_rm_polarity(int polarity) { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_set_polarity(sangoma_dev, &wp_api, polarity); } int sangoma_interface::tdm_txsig_offhook() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_txsig_offhook(sangoma_dev, &wp_api); } int sangoma_interface::tdm_enable_tone_events(uint16_t tone_id) { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_tone_events(sangoma_dev, &wp_api, tone_id); } int sangoma_interface::tdm_disable_tone_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_disable_tone_events(sangoma_dev, &wp_api); } int sangoma_interface::tdm_enable_bri_bchan_loopback(u_int8_t channel) { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_enable_bri_bchan_loopback(sangoma_dev, &wp_api, channel); } int sangoma_interface::tdm_disable_bri_bchan_loopback(u_int8_t channel) { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_disable_bri_bchan_loopback(sangoma_dev, &wp_api, channel); } @@ -1073,49 +1121,57 @@ int sangoma_interface::tdm_disable_bri_bchan_loopback(u_int8_t channel) Valid values are between 20 and 100 (including). */ int sangoma_interface::tdm_enable_rbs_events(int polls_per_second) { - return sangoma_tdm_enable_rbs_events(sangoma_dev, &wp_api,polls_per_second); + SANGOMA_INIT_TDM_API_CMD(wp_api); + return sangoma_tdm_enable_rbs_events(sangoma_dev, &wp_api, polls_per_second); } /* Stop monitoring change in state of RBS bits */ int sangoma_interface::tdm_disable_rbs_events() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_disable_rbs_events(sangoma_dev, &wp_api); } /* Activate ISDN BRI line. */ int sangoma_interface::tdm_front_end_activate() { - return sangoma_set_fe_status(sangoma_dev, &wp_api,WAN_FE_CONNECTED); + SANGOMA_INIT_TDM_API_CMD(wp_api); + return sangoma_set_fe_status(sangoma_dev, &wp_api, WAN_FE_CONNECTED); } /* De-activate ISDN BRI line. */ int sangoma_interface::tdm_front_end_deactivate() { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_set_fe_status(sangoma_dev, &wp_api, WAN_FE_DISCONNECTED); } /* get current state of the line - is it Connected or Disconnected */ int sangoma_interface::tdm_get_front_end_status(unsigned char *status) { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_get_fe_status(sangoma_dev, &wp_api, status); } /* Milliseconds interval between receive of Voice Data */ int sangoma_interface::tdm_set_user_period(unsigned int usr_period) { + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_set_usr_period(sangoma_dev, &wp_api, usr_period); } int sangoma_interface::stop() { - int wait_counter = 0; + int wait_counter = 0, i; DBG_IFACE("%s()\n", __FUNCTION__); INFO_IFACE("Stopping."); terminate_tx_rx_threads = 1; - if(sng_wait_obj){ - sangoma_wait_obj_signal(sng_wait_obj); + for (i = 0; i < SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS; i++) { + if(sng_wait_obj[i]){ + sangoma_wait_obj_signal(sng_wait_obj[i]); + } } while(terminate_tx_rx_threads == 1 && wait_counter++ < 5){ @@ -1362,20 +1418,25 @@ void sangoma_interface::TxThreadFunc() void sangoma_interface::RxThreadFunc() { int iResult; - u_int32_t input_flags[NUMBER_OF_WAIT_OBJECTS], output_flags[NUMBER_OF_WAIT_OBJECTS]; - - input_flags[0] = (POLLIN | POLLPRI); + u_int32_t output_flags[SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS]; + u_int32_t input_flags[SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS]; + input_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT] = (WP_POLLIN | WP_POLLPRI); + INFO_IFACE("\n%s: %s() - start\n", device_name, __FUNCTION__); #if defined(__WINDOWS__) INFO_IFACE("ThreadID: %d - Start\n", ::GetCurrentThreadId()); #endif + if (program_settings.real_time) { + sng_set_thread_priority_to_real_time(); + } + while(terminate_tx_rx_threads == 0){ - iResult = sangoma_waitfor_many(&sng_wait_obj, + iResult = sangoma_waitfor_many(sng_wait_obj, input_flags, output_flags, - NUMBER_OF_WAIT_OBJECTS, + SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS, 5000 /* Wait timeout, in milliseconds. Or SANGOMA_INFINITE_API_POLL_WAIT. */ ); if(terminate_tx_rx_threads){ @@ -1391,21 +1452,22 @@ void sangoma_interface::RxThreadFunc() case SANG_STATUS_SUCCESS: /* a wait object was signaled */ - if(output_flags[0] & POLLIN){ + if(output_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT] & WP_POLLIN){ /* data */ if(read_data()){ ERR_IFACE("Error in read_data()!\n"); } } - if(output_flags[0] & POLLPRI){ + if(output_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT] & WP_POLLPRI){ if(read_event()){ ERR_IFACE("Error in read_event()!\n"); } } - if(!output_flags[0] || (output_flags[0] & (~input_flags[0])) ){ - WARN_IFACE("\nUnexpected output_flags[0]: 0x%X\n\n", output_flags[0]); + if( output_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT] & (~input_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT]) ){ + ERR_IFACE("\nUnexpected output_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT]: 0x%X\n\n", output_flags[SANGOMA_RX_AND_EVENT_WAIT_OBJECT]); + iResult = SANG_STATUS_IO_ERROR; } break; @@ -1430,7 +1492,7 @@ int sangoma_interface::read_event() { int err; - memset(&wp_api, 0, sizeof(wp_api)); + SANGOMA_INIT_TDM_API_CMD(wp_api); err = sangoma_read_event(sangoma_dev, &wp_api); if(err){ @@ -1481,6 +1543,13 @@ int sangoma_interface::read_data() #if DBG_TIMING debug_update_timediff(&wan_debug_rx_timing, __FUNCTION__); + if(1){ + static int dbg_counter = 0; + dbg_counter++; + if(!(dbg_counter % 100)){ + debug_print_dbg_struct(&wan_debug_rx_timing, "sangoma_interface::read_data"); + } + } #endif break; @@ -1541,48 +1610,73 @@ int sangoma_interface::write_data(wp_api_hdr_t *hdr, void *tx_buffer) int sangoma_interface::transmit(wp_api_hdr_t *hdr, void *data) { - int iResult; - u_int32_t input_flags[NUMBER_OF_WAIT_OBJECTS], output_flags[NUMBER_OF_WAIT_OBJECTS]; + int iResult, retry_wait; + u_int32_t output_flags[SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS]; + u_int32_t input_flags[SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS]; - input_flags[0] = (POLLOUT); + input_flags[SANGOMA_TX_WAIT_OBJECT] = (WP_POLLOUT); - iResult = sangoma_waitfor_many(&sng_wait_obj, - input_flags, - output_flags, - NUMBER_OF_WAIT_OBJECTS, - 2000 /* wait timeout, in milliseconds */); + do { - switch(iResult) - { - case SANG_STATUS_APIPOLL_TIMEOUT: - //Timeout. It is possible line is disconnected. - DBG_IFACE("%s: Tx Timeout!\n", device_name); - return SANG_STATUS_TX_TIMEOUT; + iResult = sangoma_waitfor_many(sng_wait_obj, + input_flags, + output_flags, + SANGOMA_INTERFACE_NUMBER_OF_WAIT_OBJECTS, + 2000 /* wait timeout, in milliseconds */); - case SANG_STATUS_SUCCESS: - /* a wait object was signaled */ - if(output_flags[0] & POLLOUT){ - /* POLLOUT bit is set - there is at least one free Tx buffer. */ - iResult = write_data(hdr, data); - if(SANG_ERROR(iResult)){ - ERR_IFACE("Error in write_data()!\n"); + retry_wait = 0; + switch(iResult) + { + case SANG_STATUS_APIPOLL_TIMEOUT: + //Timeout. It is possible line is disconnected. + DBG_IFACE("%s: Tx Timeout!\n", device_name); + return SANG_STATUS_TX_TIMEOUT; + + case SANG_STATUS_SUCCESS: + /* a wait object was signaled */ + if(output_flags[SANGOMA_TX_WAIT_OBJECT] & WP_POLLOUT){ + /* WP_POLLOUT bit is set - there is at least one free Tx buffer. */ + iResult = write_data(hdr, data); + if(SANG_ERROR(iResult)){ + ERR_IFACE("Error in write_data()! iResult:%d\n", iResult); + } } - } - if(!output_flags[0] || (output_flags[0] & (~input_flags[0])) ){ - WARN_IFACE("\nUnexpected output_flags[0]: 0x%X\n\n", output_flags[0]); - } - break; + if(!output_flags[SANGOMA_TX_WAIT_OBJECT]){ + // + //For case (1) when there are multiple objects in sng_wait_obj[], + //the wait was woken up by another object in the array. + // + //For case (2) when there is a single object in sng_wait_obj[], + //the Tx wait was woken up by Rx Data or Event. + //This sitation is possible because for each Interface, + //at the kernel-mode driver level, there is a + //SINGLE signalling object which can be signalled for THREE reasons: + //Rx Data, API Event AND by availability of free Tx buffer. + // + //For both cases (1) and (2) the right action is to + //retry the wait for free Tx buffer. + // + retry_wait = 1; + } - default: - /* error */ - ERR_IFACE("iResult: %s (%d)\n", SDLA_DECODE_SANG_STATUS(iResult), iResult); - if(SANG_STATUS_FAILED_ALLOCATE_MEMORY == iResult){ - INFO_IFACE("Fatal Error. Press any key to exit the application.\n"); - _getch(); - exit(1); - } - }//switch(iResult) + if( output_flags[SANGOMA_TX_WAIT_OBJECT] & (~input_flags[SANGOMA_TX_WAIT_OBJECT]) ){ + ERR_IFACE("\nUnexpected output_flags[SANGOMA_TX_WAIT_OBJECT]: 0x%X\n\n", output_flags[SANGOMA_TX_WAIT_OBJECT]); + iResult = SANG_STATUS_IO_ERROR; + } + break; + + default: + /* error */ + ERR_IFACE("iResult: %s (%d)\n", SDLA_DECODE_SANG_STATUS(iResult), iResult); + if(SANG_STATUS_FAILED_ALLOCATE_MEMORY == iResult){ + INFO_IFACE("Fatal Error. Press any key to exit the application.\n"); + _getch(); + exit(1); + } + }//switch(iResult) + + } while(retry_wait); return iResult; } @@ -1590,50 +1684,50 @@ int sangoma_interface::transmit(wp_api_hdr_t *hdr, void *data) /////////////////////////////////////////////////////////////////////// int sangoma_interface::start_ring_tone() { - DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__); + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_tone_events(sangoma_dev, &wp_api, WP_API_EVENT_TONE_RING); } /////////////////////////////////////////////////////////////////////// int sangoma_interface::start_congestion_tone() { - DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__); + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_tone_events(sangoma_dev, &wp_api, WP_API_EVENT_TONE_CONGESTION); } /////////////////////////////////////////////////////////////////////// int sangoma_interface::start_busy_tone() { - DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__); + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_tone_events(sangoma_dev, &wp_api, WP_API_EVENT_TONE_BUSY); } /////////////////////////////////////////////////////////////////////// int sangoma_interface::start_dial_tone() { - DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__); + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_tone_events(sangoma_dev, &wp_api, WP_API_EVENT_TONE_DIAL); } /////////////////////////////////////////////////////////////////////// int sangoma_interface::stop_all_tones() { - DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__); + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_disable_tone_events(sangoma_dev, &wp_api); } /////////////////////////////////////////////////////////////////////// int sangoma_interface::start_ringing_phone() { - DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__); + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_enable_ring_events(sangoma_dev, &wp_api); } int sangoma_interface::stop_ringing_phone() { - DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__); + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_disable_ring_events(sangoma_dev, &wp_api); } /////////////////////////////////////////////////////////////////////// int sangoma_interface::fxo_go_off_hook() { - DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__); + SANGOMA_INIT_TDM_API_CMD(wp_api); if(wanif_conf_struct.sub_media != MOD_TYPE_FXO){ ERR_IFACE( "%s: The 'Go Off Hook' command valid only for FXO!\n", device_name); @@ -1645,19 +1739,21 @@ int sangoma_interface::fxo_go_off_hook() /////////////////////////////////////////////////////////////////////// int sangoma_interface::fxs_txsig_offhook() { - DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__); + SANGOMA_INIT_TDM_API_CMD(wp_api); return sangoma_tdm_txsig_offhook(sangoma_dev,&wp_api); } int sangoma_interface::fxo_go_on_hook() { DBG_IFACE("%s:%s()\n", device_name, __FUNCTION__); + + SANGOMA_INIT_TDM_API_CMD(wp_api); if(wanif_conf_struct.sub_media != MOD_TYPE_FXO){ ERR_IFACE( "%s: The 'Go On Hook' command valid only for FXO!\n", device_name); return 1; } - return sangoma_tdm_txsig_onhook(sangoma_dev,&wp_api); + return sangoma_tdm_txsig_onhook(sangoma_dev, &wp_api); } //set a Telephony interface to it's default state @@ -1793,7 +1889,7 @@ int sangoma_api_ctrl_dev::init(callback_functions_t *callback_functions_ptr) return 1; } - if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj, sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){ + if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj[0], sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){ ERR_IFACE("Failed to create 'sangoma_wait_object' for %s\n", device_name); return 1; } @@ -1833,7 +1929,7 @@ int sangoma_api_logger_dev::init(callback_functions_t *callback_functions_ptr) return 1; } - if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj, sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){ + if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj[0], sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){ ERR_IFACE("Failed to create 'sangoma_wait_object' for %s\n", device_name); return 1; } @@ -1930,26 +2026,40 @@ int sangoma_api_logger_dev::get_logger_dev_operational_stats(wp_logger_stats_t * memcpy(stats, &logger_cmd.stats, sizeof(*stats)); INFO_IFACE("*** Logger Device Statistics ***\n"); - INFO_IFACE("\trx_events\t: %u\n", stats->rx_events); - INFO_IFACE("\trx_events_dropped\t: %u\n", stats->rx_events_dropped); - INFO_IFACE("\tmax_event_queue_length\t: %u\n", stats->max_event_queue_length); - INFO_IFACE("\tcurrent_number_of_events_in_event_queue\t: %u\n", stats->current_number_of_events_in_event_queue); + INFO_IFACE("\trx_events\t: %lu\n", stats->rx_events); + INFO_IFACE("\trx_events_dropped\t: %lu\n", stats->rx_events_dropped); + INFO_IFACE("\tmax_event_queue_length\t: %lu\n", stats->max_event_queue_length); + INFO_IFACE("\tcurrent_number_of_events_in_event_queue\t: %lu\n", stats->current_number_of_events_in_event_queue); INFO_IFACE("\n"); #endif return err; } #ifdef WP_API_FEATURE_LIBSNG_HWEC + +#define WP_HWEC_USE_OPTIONAL_CHIP_CONFIG_PARAMS 1 + /* NOTE: HWEC must NOT be enabled on a d-channel. The 'in_ulChannelMap' should be - * the bitmap of voice channels only. */ + * the bitmap of voice channel(s) only. */ sangoma_status_t config_hwec(char *strDeviceName, unsigned long in_ulChannelMap) { sangoma_status_t rc; +#if WP_HWEC_USE_OPTIONAL_CHIP_CONFIG_PARAMS + wan_custom_param_t custom_params[1];//Optional paramter(s) for chip-wide initialization +#endif DBG_IFACE("%s(): strDeviceName: %s, in_ulChannelMap: 0x%X\n", __FUNCTION__, strDeviceName, in_ulChannelMap); - // Initialize the echo canceller (done once per-physical card) - rc = sangoma_hwec_config_init(strDeviceName); + // Optionally disable output from HWEC API Library and From API Driver. + //sangoma_hwec_config_verbosity(0); + + // Initialize the echo canceller (done once per-port) +#if WP_HWEC_USE_OPTIONAL_CHIP_CONFIG_PARAMS + sangoma_hwec_initialize_custom_parameter_structure(&custom_params[0], "WANEC_EnableAcousticEcho", "TRUE"); + rc = sangoma_hwec_config_init(strDeviceName, custom_params, sizeof(custom_params)/sizeof(custom_params[0])); +#else + rc = sangoma_hwec_config_init(strDeviceName, NULL, 0); +#endif if (SANG_STATUS_SUCCESS != rc) { ERR_IFACE( "Failed to initialize echo canceller. rc: %d\n", rc); return rc; @@ -1982,10 +2092,10 @@ sangoma_status_t config_hwec(char *strDeviceName, unsigned long in_ulChannelMap) } #if 0 -/* "WANEC_SoutAdaptiveNoiseReduction", "WANEC_TailDisplacement", "WANEC_DtmfToneRemoval", "WANEC_AcousticEcho"...*/ + /* "WANEC_SoutAdaptiveNoiseReduction", "WANEC_TailDisplacement", "WANEC_DtmfToneRemoval", "WANEC_AcousticEcho"...*/ // Optionally, Enable noise reduction from PSTN - rc = sangoma_hwec_config_channel_parameters(strDeviceName, + rc = sangoma_hwec_config_channel_parameter(strDeviceName, "WANEC_SoutAdaptiveNoiseReduction", "TRUE", in_ulChannelMap ); @@ -1993,6 +2103,15 @@ sangoma_status_t config_hwec(char *strDeviceName, unsigned long in_ulChannelMap) ERR_IFACE( "Failed to enable noise reduction.\n" ); return rc; } + + rc = sangoma_hwec_config_channel_parameter(strDeviceName, + "WANEC_TailDisplacement", + "32", + in_ulChannelMap ); + if (SANG_STATUS_SUCCESS != rc) { + ERR_IFACE( "Failed to change HWEC tail displacement.\n" ); + return rc; + } #endif return SANG_STATUS_SUCCESS; diff --git a/api/libsangoma/sample_cpp/sangoma_interface.h b/api/libsangoma/sample_cpp/sangoma_interface.h index 9d23857..3154e78 100644 --- a/api/libsangoma/sample_cpp/sangoma_interface.h +++ b/api/libsangoma/sample_cpp/sangoma_interface.h @@ -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); diff --git a/api/libsangoma/sample_cpp/sangoma_port.cpp b/api/libsangoma/sample_cpp/sangoma_port.cpp index 61ff638..3c6be03 100644 --- a/api/libsangoma/sample_cpp/sangoma_port.cpp +++ b/api/libsangoma/sample_cpp/sangoma_port.cpp @@ -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; diff --git a/api/libsangoma/sample_cpp/sangoma_port.h b/api/libsangoma/sample_cpp/sangoma_port.h index a4c4fc0..6156d42 100644 --- a/api/libsangoma/sample_cpp/sangoma_port.h +++ b/api/libsangoma/sample_cpp/sangoma_port.h @@ -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); diff --git a/api/libsangoma/sample_cpp/sangoma_port_configurator.cpp b/api/libsangoma/sample_cpp/sangoma_port_configurator.cpp index fc94b4f..90fee14 100644 --- a/api/libsangoma/sample_cpp/sangoma_port_configurator.cpp +++ b/api/libsangoma/sample_cpp/sangoma_port_configurator.cpp @@ -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; diff --git a/api/libsangoma/sample_cpp/sangoma_port_configurator.h b/api/libsangoma/sample_cpp/sangoma_port_configurator.h index f327ba6..3d00249 100644 --- a/api/libsangoma/sample_cpp/sangoma_port_configurator.h +++ b/api/libsangoma/sample_cpp/sangoma_port_configurator.h @@ -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); diff --git a/api/libsangoma/sample_cpp/sources b/api/libsangoma/sample_cpp/sources index 1e48e55..78e1955 100644 --- a/api/libsangoma/sample_cpp/sources +++ b/api/libsangoma/sample_cpp/sources @@ -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 \ diff --git a/api/libsangoma/sources b/api/libsangoma/sources index d89d9b4..64cfad1 100644 --- a/api/libsangoma/sources +++ b/api/libsangoma/sources @@ -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);\ diff --git a/api/libstelephony/.svn/all-wcprops b/api/libstelephony/.svn/all-wcprops index 7c701ba..4c9d422 100644 --- a/api/libstelephony/.svn/all-wcprops +++ b/api/libstelephony/.svn/all-wcprops @@ -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 diff --git a/api/libstelephony/.svn/entries b/api/libstelephony/.svn/entries index f6bf3fb..121550f 100644 --- a/api/libstelephony/.svn/entries +++ b/api/libstelephony/.svn/entries @@ -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 diff --git a/api/libstelephony/.svn/text-base/PToneDecoder.cpp.svn-base b/api/libstelephony/.svn/text-base/PToneDecoder.cpp.svn-base index a0f2b84..fba1a8b 100644 --- a/api/libstelephony/.svn/text-base/PToneDecoder.cpp.svn-base +++ b/api/libstelephony/.svn/text-base/PToneDecoder.cpp.svn-base @@ -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; diff --git a/api/libstelephony/PToneDecoder.cpp b/api/libstelephony/PToneDecoder.cpp index a0f2b84..fba1a8b 100644 --- a/api/libstelephony/PToneDecoder.cpp +++ b/api/libstelephony/PToneDecoder.cpp @@ -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; diff --git a/api/libstelephony/stel_tone/.svn/entries b/api/libstelephony/stel_tone/.svn/entries index e5a14e2..da92c79 100644 --- a/api/libstelephony/stel_tone/.svn/entries +++ b/api/libstelephony/stel_tone/.svn/entries @@ -1,7 +1,7 @@ 8 dir -59 +60 http://www.sangomapbx.com/svn/stelephony/trunk/stel_tone http://www.sangomapbx.com/svn/stelephony diff --git a/api/tdm_api/aft_tdm_hdlc_test.c b/api/tdm_api/aft_tdm_hdlc_test.c index 4cc4a83..47c4116 100644 --- a/api/tdm_api/aft_tdm_hdlc_test.c +++ b/api/tdm_api/aft_tdm_hdlc_test.c @@ -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); } } diff --git a/api/tdm_api/aft_tdm_voice_api.c b/api/tdm_api/aft_tdm_voice_api.c index 0db5b22..d0b2bbc 100644 --- a/api/tdm_api/aft_tdm_voice_api.c +++ b/api/tdm_api/aft_tdm_voice_api.c @@ -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;xdata[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;idata[i]); + if (i && i%24==0) { + printf("\n"); + } + printf("%02d ", api_rx_el->data[i]); } printf("\n"); #endif diff --git a/api/xmtp2api-v1.6/Makefile b/api/xmtp2api-v1.6/Makefile new file mode 100644 index 0000000..cf9d6dc --- /dev/null +++ b/api/xmtp2api-v1.6/Makefile @@ -0,0 +1,37 @@ +# ============================================================================ +# Makefile Make script for building SS7 MTP2 API +# ---------------------------------------------------------------------------- +# Author: Nenad Corbic +# 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 diff --git a/api/xmtp2api-v1.6/README b/api/xmtp2api-v1.6/README new file mode 100644 index 0000000..d56c266 --- /dev/null +++ b/api/xmtp2api-v1.6/README @@ -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-.tgz + + 3. cd wanpipe- + + 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 diff --git a/api/xmtp2api-v1.6/libxmtp2.c b/api/xmtp2api-v1.6/libxmtp2.c new file mode 100644 index 0000000..452bef2 --- /dev/null +++ b/api/xmtp2api-v1.6/libxmtp2.c @@ -0,0 +1,636 @@ +/***************************************************************************** +* libxmtp2.c SS7 MTP2 API Library +* +* Author(s): Mike Mueller +* +* +* Copyright: (c) 2010 Xygnada Technologies +* Sangoma Technologies Inc. +* +* ============================================================================ +* 1.6 Nenad Corbic +* May 28 2010 +* Updated for 8 E1 worth of links. +* Synched up with latest xmtp2 code +* +* 1.5 Nenad Corbic +* Sep 02 2009 +* Updated for full t1/e1 config +* update freame_per_packet to cfg->mtu +* +* 1.4 Nenad Corbic +* Aug 19 2009 +* Updated for full t1/e1 config +* +* 1.3 Nenad Corbic +* Jun 3 2008 +* Fixed spelling mistake in function names +* xmtp2_restart_facility +* xmtp2_start_facility +* +* 1.2 Nenad Corbic +* May 21 2008 +* Updated so mtp2 links can be configured and +* reconfigured on the fly. +* +* 1.1 Nenad Corbic +* May 1 2008 +* Updated MTP2 Timer configuration +* +* 1.0 Nenad Corbic +* 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 /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); +} + diff --git a/api/xmtp2api-v1.6/libxmtp2.h b/api/xmtp2api-v1.6/libxmtp2.h new file mode 100644 index 0000000..f6d9e7c --- /dev/null +++ b/api/xmtp2api-v1.6/libxmtp2.h @@ -0,0 +1,481 @@ +/***************************************************************************** +* libxmtp2.h SS7 MTP2 API Library +* +* Author(s): Mike Mueller +* +* +* Copyright: (c) 2008 Xygnada Technologies +* Sangoma Technologies Inc. +* +* ============================================================================ +*/ + +#ifndef _LIBXMTP2_ +#define _LIBXMTP2_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + +/* 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 + diff --git a/api/xmtp2api-v1.6/mtp2api.c b/api/xmtp2api-v1.6/mtp2api.c new file mode 100644 index 0000000..46815e7 --- /dev/null +++ b/api/xmtp2api-v1.6/mtp2api.c @@ -0,0 +1,634 @@ +/***************************************************************************** +* mpt2api.c SS7 MTP2 API Example Code +* +* Author(s): Nenad Corbic +* Michael Mueller +* +* Copyright: (c) 2003-2010 Sangoma Technologies Inc. +* Xygnada Technologies. +* ============================================================================ +* +* 1.6 Nenad Corbic +* May 28 2010 +* Updated for 8 E1 worth of links. +* Synched up with latest xmtp2 code +* +* 1.5 Nenad Corbic +* Sep 02 2009 +* Updated for full t1/e1 config +* +* 1.4 Nenad Corbic +* Aug 19 2009 +* Updated for full t1/e1 config +* +* 1.2 Nenad Corbic +* May 21 2008 +* Updated so mtp2 links can be configured and +* reconfigured on the fly. +* +* 1.1 Nenad Corbic +* May 1 2008 +* Updated MTP2 Timer configuration +* +* 1.0 Nenad Corbic +* May 1 2008 +* Initial Version +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 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; +} + diff --git a/api/xmtp2api-v1.6/wanpipe/wanpipe1.conf b/api/xmtp2api-v1.6/wanpipe/wanpipe1.conf new file mode 100644 index 0000000..9275466 --- /dev/null +++ b/api/xmtp2api-v1.6/wanpipe/wanpipe1.conf @@ -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 + + diff --git a/api/xmtp2api-v1.6/wanpipe/wanpipe1.conf.16_channels_e1 b/api/xmtp2api-v1.6/wanpipe/wanpipe1.conf.16_channels_e1 new file mode 100644 index 0000000..fddb9e7 --- /dev/null +++ b/api/xmtp2api-v1.6/wanpipe/wanpipe1.conf.16_channels_e1 @@ -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 + diff --git a/api/xmtp2api-v1.6/wanpipe/wanpipe1.conf.full_e1 b/api/xmtp2api-v1.6/wanpipe/wanpipe1.conf.full_e1 new file mode 100644 index 0000000..19c26ac --- /dev/null +++ b/api/xmtp2api-v1.6/wanpipe/wanpipe1.conf.full_e1 @@ -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 + + diff --git a/api/xmtp2api-v1.6/wanpipe/wanpipe1.conf.single_channel_e1 b/api/xmtp2api-v1.6/wanpipe/wanpipe1.conf.single_channel_e1 new file mode 100644 index 0000000..9275466 --- /dev/null +++ b/api/xmtp2api-v1.6/wanpipe/wanpipe1.conf.single_channel_e1 @@ -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 + + diff --git a/api/xmtp2api-v1.6/wanpipe/wanpipe2.conf b/api/xmtp2api-v1.6/wanpipe/wanpipe2.conf new file mode 100644 index 0000000..ca2c355 --- /dev/null +++ b/api/xmtp2api-v1.6/wanpipe/wanpipe2.conf @@ -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 + diff --git a/api/xmtp2api-v1.6/xmtp2km_in b/api/xmtp2api-v1.6/xmtp2km_in new file mode 100755 index 0000000..34cf5a3 --- /dev/null +++ b/api/xmtp2api-v1.6/xmtp2km_in @@ -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 diff --git a/deb_control/wanpipe.deb b/deb_control/wanpipe.deb index fcbb9a2..72b0948 100644 --- a/deb_control/wanpipe.deb +++ b/deb_control/wanpipe.deb @@ -1,5 +1,5 @@ Package: wanpipe -Version: 3.5.11-0 +Version: 3.5.12-0 Section: networking Priority: optional Architecture: all diff --git a/patches/kdrivers/include/aft_core_private.h b/patches/kdrivers/include/aft_core_private.h index 1b02db0..062ab40 100644 --- a/patches/kdrivers/include/aft_core_private.h +++ b/patches/kdrivers/include/aft_core_private.h @@ -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 */ diff --git a/patches/kdrivers/include/aft_core_user.h b/patches/kdrivers/include/aft_core_user.h index eb583dd..767af84 100644 --- a/patches/kdrivers/include/aft_core_user.h +++ b/patches/kdrivers/include/aft_core_user.h @@ -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 diff --git a/patches/kdrivers/include/sdla_b800_remora.h b/patches/kdrivers/include/sdla_b800_remora.h new file mode 100644 index 0000000..a23cfe0 --- /dev/null +++ b/patches/kdrivers/include/sdla_b800_remora.h @@ -0,0 +1,37 @@ +/******************************************************************************* + * ** sdla_b800_remora.h + * ** + * ** Author: David Yat Sin + * ** + * ** 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 */ diff --git a/patches/kdrivers/include/sdla_front_end.h b/patches/kdrivers/include/sdla_front_end.h index 7c1a13b..2ae1e30 100644 --- a/patches/kdrivers/include/sdla_front_end.h +++ b/patches/kdrivers/include/sdla_front_end.h @@ -219,7 +219,7 @@ typedef struct { unsigned char tx_tristate_mode; unsigned int tdmv_law; unsigned char poll_mode; - int network_sync; + int network_sync; union { sdla_te_cfg_t te_cfg; @@ -236,6 +236,8 @@ typedef struct { /*sdla_te_pmon_t te_pmon;*/ sdla_te3_pmon_t te3_pmon; } u; + u_int32_t tx_alarms; + u_int32_t tx_maint_alarms; #define te_pmon u.te1_stats.pmon } sdla_fe_stats_t; @@ -559,7 +561,7 @@ typedef struct { /* Set extra T1/E1 configuration */ int (*reconfig)(sdla_fe_t*); int (*unconfig)(void *fe); - int (*pre_release)(void*); + int (*post_unconfig)(void*); int (*if_config)(void *fe, u32, u8); int (*if_unconfig)(void *fe, u32, u8); int (*disable_irq)(void *fe); @@ -568,6 +570,7 @@ typedef struct { int (*isr)(sdla_fe_t *fe); int (*process_udp)(sdla_fe_t *fe, void*, unsigned char*); u_int32_t (*read_alarm)(sdla_fe_t *fe, int); + int (*read_pmon)(sdla_fe_t *fe, int); int (*flush_pmon)(sdla_fe_t *fe); /* Set Front-End alarm (T1/E1) */ @@ -626,6 +629,7 @@ typedef struct { int (*isdn_bri_dchan_rx)(sdla_fe_t*, void*, unsigned int); /* Enable/Disable Clock recovery from the line */ int (*clock_ctrl)(sdla_fe_t*, u_int8_t /* WANOPT_NO/WANOPT_YES */); + u_int32_t (*read_tx_alarm)(sdla_fe_t *fe, int); } sdla_fe_iface_t; /* diff --git a/patches/kdrivers/include/sdla_remora.h b/patches/kdrivers/include/sdla_remora.h index c47bb68..b727541 100644 --- a/patches/kdrivers/include/sdla_remora.h +++ b/patches/kdrivers/include/sdla_remora.h @@ -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" diff --git a/patches/kdrivers/include/sdla_te1.h b/patches/kdrivers/include/sdla_te1.h index 991ad47..affe1b4 100644 --- a/patches/kdrivers/include/sdla_te1.h +++ b/patches/kdrivers/include/sdla_te1.h @@ -278,6 +278,7 @@ #define TE_CONFIGURED 0x06 #define TE_TIMER_EVENT_PENDING 0x07 #define TE_TIMER_EVENT_INPROGRESS 0x08 +#define TE_AIS_TX_STARTUP 0x09 /* TE1 sw irq types */ enum { @@ -453,6 +454,7 @@ typedef struct sdla_te_cfg { u_int8_t te_ref_clock; u_int8_t sig_mode; u_int8_t ignore_yel_alarm; + u_int8_t ais_maintenance; } sdla_te_cfg_t; /* Performamce monitor counters */ @@ -784,6 +786,9 @@ typedef struct { wan_ticks_t bert_start; sdla_te_bert_cfg_t bert_cfg; sdla_te_bert_stats_t bert_stats; + + uint8_t tx_ais_alarm; + wan_ticks_t tx_ais_startup_timeout; } sdla_te_param_t; diff --git a/patches/kdrivers/include/sdladrv.h b/patches/kdrivers/include/sdladrv.h index 625b2b3..cb830c0 100644 --- a/patches/kdrivers/include/sdladrv.h +++ b/patches/kdrivers/include/sdladrv.h @@ -168,6 +168,7 @@ enum { #define SDLA_MAGIC_RC(hw,rc) WAN_ASSERT_RC((hw)->magic != SDLADRV_MAGIC, (rc)) #define SDLA_MAGIC_VOID(hw) WAN_ASSERT_VOID((hw)->magic != SDLADRV_MAGIC) +#define WAN_BUS_ID_SIZE 20 /* ****************************************************************** @@ -385,6 +386,7 @@ typedef struct sdlahw_pci_ #define SDLA_USB_OPMODE_VOICE 0x01 #define SDLA_USB_OPMODE_API 0x02 +#define SDLA_URB_STATUS_READY 1 struct wan_urb { void *pvt; int id; @@ -428,22 +430,26 @@ typedef struct { int tx_overrun_cnt; int tx_notready_cnt; - unsigned char fifo_status; - unsigned char uart_status; - unsigned char hostif_status; + unsigned char dev_fifo_status; + unsigned char dev_uart_status; + unsigned char dev_hostif_status; + int dev_sync_err_cnt; } sdla_usb_comm_err_stats_t; - typedef struct sdlahw_usb_ { int opmode; /* Voice or API Data protocol */ + unsigned char hw_rev; /* hardware (pcb) revision */ # if defined(__LINUX__) + char bus_id[WAN_BUS_ID_SIZE]; struct usb_device *usb_dev; struct usb_interface *usb_intf; # endif + + unsigned char reg_cpu_ctrl; /* Reg 0x03 */ int urbcount_read; int urb_read_ind; struct wan_urb dataread[MAX_READ_URB_COUNT]; @@ -458,6 +464,7 @@ typedef struct sdlahw_usb_ wan_spinlock_t cmd_lock; wan_spinlock_t lock; + wan_spinlock_t tx_lock; int rxtx_len; /* number of data bytes in record */ int rxtx_count; /* number records in single transcation */ @@ -468,13 +475,14 @@ typedef struct sdlahw_usb_ int write_buf_len; /* size of write cycle buffer */ int rx_sync; + int tx_sync; int next_rx_ind; int next_read_ind; - char readbuf[MAX_READ_BUF_LEN+MAX_USB_RX_LEN+10]; // 10 for safety + char *readbuf; int next_tx_ind; int next_write_ind; - char writebuf[MAX_WRITE_BUF_LEN+MAX_USB_TX_LEN+10]; // 10 for safety + char *writebuf; char idlebuf[MAX_USB_TX_LEN+1]; @@ -484,6 +492,8 @@ typedef struct sdlahw_usb_ unsigned int status; + wan_ticks_t tx_cmd_start; + wan_skb_queue_t tx_cmd_list; wan_skb_queue_t tx_cmd_free_list; wan_skb_queue_t rx_cmd_list; @@ -504,6 +514,7 @@ typedef struct sdlahw_usb_ /* This structure keeps common parameters per physical card */ typedef struct sdlahw_card { int internal_used; + unsigned char name[SDLA_NAME_SIZE]; /* Card name */ unsigned int hw_type; /* ISA/PCI */ unsigned int type; /* S50x/S514/ADSL/SDLA_AFT */ unsigned char cfg_type; /* Config card type WANOPT_XXX */ @@ -712,21 +723,23 @@ typedef struct sdlahw_iface char* (*hwec_name)(void *phw); int (*get_hwec_index)(void *phw); - /* usb function interface (FIXME) */ + /* usb function interface (FIXME) */ int (*usb_cpu_read)(void *phw, unsigned char off, unsigned char *data); int (*usb_cpu_write)(void *phw, unsigned char off, unsigned char data); int (*usb_write_poll)(void *phw, unsigned char off, unsigned char data); int (*usb_read_poll)(void *phw, unsigned char off, unsigned char *data); + int (*usb_hwec_enable)(void *phw, int, int); int (*usb_rxevent_enable)(void *phw, int, int); int (*usb_rxevent)(void *phw, int, u8*, int); int (*usb_rxtx_data_init)(void *phw, int, unsigned char**, unsigned char**); int (*usb_rxdata_enable)(void *phw, int enable); - int (*usb_rxdata)(void *phw, unsigned char*, int); - int (*usb_txdata)(void *phw, unsigned char*, int); - int (*usb_txdata_ready)(void *phw); + int (*usb_fwupdate_enable)(void *phw); + int (*usb_txdata_raw)(void *phw, unsigned char*, int); + int (*usb_txdata_raw_ready)(void *phw); + int (*usb_rxdata_raw)(void *phw, unsigned char*, int); int (*usb_err_stats)(void *phw, void*, int); int (*usb_flush_err_stats)(void *phw); - void (*reset_fe)(void*); + void (*reset_fe)(void*); } sdlahw_iface_t; @@ -746,13 +759,14 @@ typedef struct sdla_hw_type_cnt unsigned char aft_a600_adapters; unsigned char aft_b601_adapters; unsigned char aft_a700_adapters; + unsigned char aft_b800_adapters; unsigned char aft_x_adapters; unsigned char usb_adapters; }sdla_hw_type_cnt_t; typedef struct sdladrv_callback_ { - int (*add_device)(char*, void*); + int (*add_device)(void); int (*delete_device)(char*); } sdladrv_callback_t; diff --git a/patches/kdrivers/include/sdladrv_usb.h b/patches/kdrivers/include/sdladrv_usb.h new file mode 100644 index 0000000..fa5002a --- /dev/null +++ b/patches/kdrivers/include/sdladrv_usb.h @@ -0,0 +1,124 @@ +/** + * \file sdladrv_usb.h + * \brief SDLADRV USB Interface + * + * Authors: Alex Feldman + * + * 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 */ diff --git a/patches/kdrivers/include/sdlapci.h b/patches/kdrivers/include/sdlapci.h index 103f7e2..23e98cd 100644 --- a/patches/kdrivers/include/sdlapci.h +++ b/patches/kdrivers/include/sdlapci.h @@ -88,6 +88,9 @@ #define AFT_A600_SUBSYS_VENDOR 0xA600 /* AFT-600 Series board */ #define AFT_B601_SUBSYS_VENDOR 0xA601 /* AFT-600 Series board */ +/* DAVIDY change to B800 ID when B800 ID is ready */ +#define AFT_B800_SUBSYS_VENDOR 0xB800 /* AFT-800 Series board */ + #define AFT_2SERIAL_V35X21_SUBSYS_VENDOR 0xA031 /* AFT-A142 2 Port V.35/X.21 board */ #define AFT_4SERIAL_V35X21_SUBSYS_VENDOR 0xA032 /* AFT-A144 4 Port V.35/X.21 board */ #define AFT_2SERIAL_RS232_SUBSYS_VENDOR 0xA033 /* AFT-A142 2 Port RS232 board */ diff --git a/patches/kdrivers/include/sdlasfm.h b/patches/kdrivers/include/sdlasfm.h index 0695078..58c067d 100644 --- a/patches/kdrivers/include/sdlasfm.h +++ b/patches/kdrivers/include/sdlasfm.h @@ -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" diff --git a/patches/kdrivers/include/wanpipe_abstr_types.h b/patches/kdrivers/include/wanpipe_abstr_types.h index b34ac00..8e818dd 100644 --- a/patches/kdrivers/include/wanpipe_abstr_types.h +++ b/patches/kdrivers/include/wanpipe_abstr_types.h @@ -161,5 +161,14 @@ typedef u32 gfp_t; #endif #endif/* !defined(WAN_KERNEL) */ +#endif /* __WINDOWS__ */ + +#if defined(__WINDOWS__) +/* Do NOT use "POINTER_64" - some versions of MS compiler + * will expand it incorrectly to __ptr32. */ +# define WP_POINTER_64 __ptr64 +#else +# define WP_POINTER_64 #endif + #endif /* __WANPIPE_ABSTR_TYPES_H */ diff --git a/patches/kdrivers/include/wanpipe_api.h b/patches/kdrivers/include/wanpipe_api.h index 0e51fef..75e1a7b 100644 --- a/patches/kdrivers/include/wanpipe_api.h +++ b/patches/kdrivers/include/wanpipe_api.h @@ -39,7 +39,7 @@ #include "aft_core_user.h" #include "wanpipe_api_hdr.h" #include "wanpipe_api_iface.h" - +#include "wanpipe_codec_iface.h" /***************************************************************//** * WANPIPE API HEADER & EVENT STRUCTURE @@ -273,6 +273,13 @@ enum wanpipe_aft_devel_events { SIOC_WAN_GET_CARD_TYPE, SIOC_WAN_USB_READ_REG, SIOC_WAN_USB_WRITE_REG, + SIOC_WAN_USB_CPU_WRITE_REG, + SIOC_WAN_USB_CPU_READ_REG, + SIOC_WAN_USB_FE_WRITE_REG, + SIOC_WAN_USB_FE_READ_REG, + SIOC_WAN_USB_FW_DATA_READ, + SIOC_WAN_USB_FW_DATA_WRITE, + SIOC_WAN_USB_FWUPDATE_ENABLE, }; #include "wanpipe_api_deprecated.h" diff --git a/patches/kdrivers/include/wanpipe_api_hdr.h b/patches/kdrivers/include/wanpipe_api_hdr.h index 4951443..5b49f05 100644 --- a/patches/kdrivers/include/wanpipe_api_hdr.h +++ b/patches/kdrivers/include/wanpipe_api_hdr.h @@ -174,15 +174,17 @@ typedef struct wp_api_hdr The rx_h and tx_h are to be used with all AFT Hardware ****************************************************/ struct { - u_int16_t crc; /*!< number of crc/abort/data errors */ + u_int16_t crc; /*!< bit map of possible errors: CRC/ABORT/FRAME/DMA */ u_int8_t max_rx_queue_length; /*!< max data queue configured */ u_int8_t current_number_of_frames_in_rx_queue; /*!< current buffers in device rx queue */ + u_int32_t errors; /*!< number of rx errors since driver start */ }rx_h; struct { u_int8_t max_tx_queue_length; /*!< max data queue configured */ u_int8_t current_number_of_frames_in_tx_queue; /*!< current buffers in device tx queue */ u_int32_t tx_idle_packets; /*!< number of tx idle packes transmitted */ + u_int32_t errors; /*!< number of tx errors since driver start */ }tx_h; /***********************************************//** @@ -193,28 +195,18 @@ typedef struct wp_api_hdr u_int8_t status; }serial; struct { - u_int32_t time_stamp_sec; - u_int32_t time_stamp_usec; u_int8_t exception; u_int8_t pf; }lapb; struct { - u_int32_t time_stamp_sec; - u_int32_t time_stamp_usec; u_int8_t state; u_int8_t address; u_int16_t exception; }xdlc; struct { - u_int32_t time_stamp_sec; - u_int32_t time_stamp_usec; u_int8_t channel; u_int8_t direction; }bitstrm; - struct { - u_int32_t time_stamp_sec; - u_int32_t time_stamp_usec; - }chdlc,fr,ppp; struct { u_int8_t repeat; u_int8_t len; @@ -241,16 +233,19 @@ typedef struct wp_api_hdr #define wp_api_hdr_time_stamp_use time_stamp_usec #define wp_api_rx_hdr_crc rx_h.crc +#define wp_api_rx_hdr_error_map rx_h.crc #define wp_api_rx_hdr_max_queue_length rx_h.max_rx_queue_length #define wp_api_rx_hdr_number_of_frames_in_queue rx_h.current_number_of_frames_in_rx_queue #define wp_api_rx_hdr_time_stamp_sec time_stamp_sec #define wp_api_rx_hdr_time_stamp_use time_stamp_usec +#define wp_api_rx_hdr_errors rx_h.errors #define wp_api_tx_hdr_max_queue_length tx_h.max_tx_queue_length #define wp_api_tx_hdr_number_of_frames_in_queue tx_h.current_number_of_frames_in_tx_queue #define wp_api_tx_hdr_tx_idle_packets tx_h.tx_idle_packets #define wp_api_tx_hdr_time_stamp_sec time_stamp_sec #define wp_api_tx_hdr_time_stamp_use time_stamp_usec +#define wp_api_tx_hdr_errors tx_h.errors /***********************************************//** Defines below are Deprecated and are for @@ -283,8 +278,8 @@ typedef struct wp_api_hdr /* CHDLC Old backdward comptabile */ #define wp_api_rx_hdr_chdlc_error_flag wp_api_rx_hdr_error_flag #define wp_api_rx_hdr_chdlc_time_stamp wp_api_rx_hdr_time_stamp -#define wp_api_rx_hdr_chdlc_time_sec chdlc.time_stamp_sec -#define wp_api_rx_hdr_chdlc_time_usec chdlc.time_stamp_usec +#define wp_api_rx_hdr_chdlc_time_sec time_stamp_sec +#define wp_api_rx_hdr_chdlc_time_usec time_stamp_usec #define wan_hdr_chdlc_error_flag wp_api_rx_hdr_chdlc_error_flag #define wan_hdr_chdlc_time_stamp wp_api_rx_hdr_chdlc_time_stamp @@ -294,8 +289,8 @@ typedef struct wp_api_hdr /* BITSTRM Old backdward comptabile */ #define wp_api_rx_hdr_bitstrm_error_flag wp_api_rx_hdr_error_flag #define wp_api_rx_hdr_bitstrm_time_stamp wp_api_rx_hdr_time_stamp -#define wp_api_rx_hdr_bitstrm_time_sec bitstrm.time_stamp_sec -#define wp_api_rx_hdr_bitstrm_time_usec bitstrm.time_stamp_usec +#define wp_api_rx_hdr_bitstrm_time_sec time_stamp_sec +#define wp_api_rx_hdr_bitstrm_time_usec time_stamp_usec #define wp_api_rx_hdr_bitstrm_channel bitstrm.channel #define wp_api_rx_hdr_bitstrm_direction bitstrm.direction @@ -309,8 +304,8 @@ typedef struct wp_api_hdr /* HDLC Old backdward comptabile */ #define wp_api_rx_hdr_hdlc_error_flag wp_api_rx_hdr_error_flag #define wp_api_rx_hdr_hdlc_time_stamp wp_api_rx_hdr_time_stamp -#define wp_api_rx_hdr_hdlc_time_sec hdlc.time_stamp_sec -#define wp_api_rx_hdr_hdlc_time_usec hdlc.time_stamp_usec +#define wp_api_rx_hdr_hdlc_time_sec time_stamp_sec +#define wp_api_rx_hdr_hdlc_time_usec time_stamp_usec #define wan_hdr_hdlc_error_flag wp_api_rx_hdr_error_flag #define wan_hdr_hdlc_time_stamp wp_api_rx_hdr_time_stamp @@ -318,8 +313,8 @@ typedef struct wp_api_hdr /* LAPBS Old backdward comptabile */ #define wp_api_rx_hdr_lapb_pf lapb.pf #define wp_api_rx_hdr_lapb_exception lapb.exception -#define wp_api_rx_hdr_lapb_time_sec lapb.time_stamp_sec -#define wp_api_rx_hdr_lapb_time_usec lapb.time_stamp_usec +#define wp_api_rx_hdr_lapb_time_sec time_stamp_sec +#define wp_api_rx_hdr_lapb_time_usec time_stamp_usec #define wan_hdr_lapb_pf wp_api_rx_hdr_lapb_pf #define wan_hdr_lapb_exception wp_api_rx_hdr_lapb_exception @@ -327,8 +322,8 @@ typedef struct wp_api_hdr /* FR Old backdward comptabile */ #define wp_api_rx_hdr_fr_attr wp_api_rx_hdr_error_flag #define wp_api_rx_hdr_fr_time_stamp wp_api_rx_hdr_time_stamp -#define wp_api_rx_hdr_fr_time_sec fr.time_stamp_sec -#define wp_api_rx_hdr_fr_time_usec fr.time_stamp_usec +#define wp_api_rx_hdr_fr_time_sec time_stamp_sec +#define wp_api_rx_hdr_fr_time_usec time_stamp_usec #define wan_hdr_fr_attr wp_api_rx_hdr_fr_attr #define wan_hdr_fr_time_stamp wp_api_rx_hdr_fr_time_stamp @@ -469,7 +464,7 @@ typedef enum SANG_STATUS SANG_STATUS_UNSUPPORTED_FUNCTION, /*!< Unsupported command or function */ SANG_STATUS_UNSUPPORTED_PROTOCOL, /*!< Unsupported protocol selected */ SANG_STATUS_DEVICE_ALREADY_EXIST, /*!< Device already exists */ - SANG_STATUS_DEV_INIT_INCOMPLETE, /*!< Device initialization failed */ + SANG_STATUS_DEV_INIT_INCOMPLETE, /*!< Device initialization failed or not done */ SANG_STATUS_TRACE_QUEUE_EMPTY, /*!< Trace queue empty */ SANG_STATUS_OPTION_NOT_SUPPORTED, /*!< Unsupported command or option */ diff --git a/patches/kdrivers/include/wanpipe_api_iface.h b/patches/kdrivers/include/wanpipe_api_iface.h index 22c5f30..5ca1002 100644 --- a/patches/kdrivers/include/wanpipe_api_iface.h +++ b/patches/kdrivers/include/wanpipe_api_iface.h @@ -67,6 +67,12 @@ typedef int sng_fd_t; \brief Indicates to developer that loop feature is available \def WP_API_FEATURE_HWEC \brief Indicates to developer that Hardware Echo canceller feature is available + \def WP_API_FEATURE_BUFFER_MULT + \brief Indicates to developer that buffer multiplier featere is available + \def WP_API_FEATURE_RX_TX_ERRS + \brief Indicates to developer that rx tx error reporting feature is available + \def WP_API_FEATURE_EC_CHAN_STAT + \brief Indicates to developer that echo channel status feature is available */ #define WP_API_FEATURE_DTMF_EVENTS 1 #define WP_API_FEATURE_FE_ALARM 1 @@ -77,6 +83,9 @@ typedef int sng_fd_t; #define WP_API_FEATURE_FAX_EVENTS 1 #define WP_API_FEATURE_RM_GAIN 1 #define WP_API_FEATURE_LOOP 1 +#define WP_API_FEATURE_BUFFER_MULT 1 +#define WP_API_FEATURE_RX_TX_ERRS 1 +#define WP_API_FEATURE_EC_CHAN_STAT 1 #if defined(__WINDOWS__) #define WP_API_FEATURE_LIBSNG_HWEC 1 #endif @@ -253,7 +262,7 @@ enum wanpipe_api_cmds WP_API_CMD_GET_TX_Q_SIZE, /*!< Get TX Queue Size */ WP_API_CMD_SET_RX_Q_SIZE, /*!< Set RX Queue Size */ WP_API_CMD_GET_RX_Q_SIZE, /*!< Get RX Queue Size */ - WP_API_CMD_EVENT_CTRL, + WP_API_CMD_EVENT_CTRL, /*!< */ WP_API_CMD_NOTSUPP, /*!< */ WP_API_CMD_SET_RM_RXFLASHTIME, /*!< Set rxflashtime for FXS */ WP_API_CMD_SET_IDLE_FLAG, /*!< Set Idle Flag (char) for a BitStream (Voice) channel */ @@ -261,6 +270,8 @@ enum wanpipe_api_cmds WP_API_CMD_GET_HW_FAX_DETECT, /*!< Check Status of HW Fax Detect. Enabled(1) or Disabled(0) */ WP_API_CMD_ENABLE_LOOP, /*!< Remote Loop the channel */ WP_API_CMD_DISABLE_LOOP, /*!< Disable remote loop */ + WP_API_CMD_BUFFER_MULTIPLIER, /*!< Set Buffer Multiplier - for SPAN voice mode only */ + WP_API_CMD_GET_HW_EC_CHAN, /*!< Get status of hwec for the current timeslot */ /* Add only debugging commands here */ WP_API_CMD_GEN_FIFO_ERR_TX=500, @@ -547,12 +558,31 @@ typedef struct wanpipe_chan_stats unsigned int rx_events_dropped; unsigned int rx_events_tone; + + unsigned int rx_hdlc_abort_counter; /* this is not an error */ }wanpipe_chan_stats_t; #define WP_AFT_CHAN_ERROR_STATS(chan_stats,var) chan_stats.var++;chan_stats.errors++ +#define WP_AFT_RX_ERROR_SUM(chan_stats) chan_stats.rx_errors+ \ + chan_stats.rx_dropped+ \ + chan_stats.rx_length_errors + \ + chan_stats.rx_crc_errors + \ + chan_stats.rx_frame_errors + \ + chan_stats.rx_fifo_errors + \ + chan_stats.rx_missed_errors + \ + chan_stats.rx_hdlc_abort_counter + +#define WP_AFT_TX_ERROR_SUM(chan_stats) chan_stats.tx_errors+ \ + chan_stats.tx_dropped + \ + chan_stats.tx_aborted_errors + \ + chan_stats.tx_carrier_errors + \ + chan_stats.tx_fifo_errors+ \ + chan_stats.tx_heartbeat_errors + \ + chan_stats.tx_window_errors + typedef struct _DRIVER_VERSION { unsigned int major; unsigned int minor; @@ -561,7 +591,7 @@ typedef struct _DRIVER_VERSION { }wan_driver_version_t, DRIVER_VERSION, *PDRIVER_VERSION; #define WANPIPE_API_CMD_SZ 512 -#define WANPIPE_API_DEV_CFG_MAX_SZ 333 +#define WANPIPE_API_DEV_CFG_MAX_SZ 337 /* The the union size is max-cmd-result-span-chan-data_len */ #define WANPIPE_API_CMD_SZ_UNION WANPIPE_API_CMD_SZ - (sizeof(unsigned int)*3) - (sizeof(unsigned char)*2) diff --git a/patches/kdrivers/include/wanpipe_cfg.h b/patches/kdrivers/include/wanpipe_cfg.h index e747082..8b6817b 100644 --- a/patches/kdrivers/include/wanpipe_cfg.h +++ b/patches/kdrivers/include/wanpipe_cfg.h @@ -150,7 +150,7 @@ enum { card_type == WANOPT_AFT104 || \ card_type == WANOPT_AFT108) ? "A101/1D/A102/2D/4/4D/8" : \ (card_type == WANOPT_AFT300) ? "A300" : \ - (card_type == WANOPT_AFT_ANALOG) ? "A200/A400/B600/B700" : \ + (card_type == WANOPT_AFT_ANALOG) ? "A200/A400/B600/B700/B800" : \ (card_type == WANOPT_AFT_ISDN) ? "A500/B700" : \ (card_type == WANOPT_AFT_56K) ? "A056" : \ (card_type == WANOPT_AFT_SERIAL) ? "A14x" : \ @@ -655,6 +655,14 @@ typedef struct wan_hwec_conf_ unsigned char noise_reduction; /* Noise Reduction control */ unsigned char noise_reduction_disable; /* Noise Reduction control - because now its on by default */ unsigned int tone_disabler_delay; /* delay in a fax mode */ + unsigned char dtmf_removal; /* remove dtmf */ + unsigned char operation_mode; + unsigned char acustic_echo; + unsigned char nlp_disable; + int rx_auto_gain; + int tx_auto_gain; + int rx_gain; + int tx_gain; } wan_hwec_conf_t; typedef struct wan_hwec_dev_state @@ -678,7 +686,7 @@ typedef struct wan_custom_param_ typedef struct wan_custom_conf_ { unsigned int param_no; - wan_custom_param_t *params; + wan_custom_param_t *WP_POINTER_64 params; } wan_custom_conf_t; @@ -721,7 +729,8 @@ typedef struct wandev_conf /****** arbitrary data ***************/ unsigned data_size; /* data buffer size */ - void* data; /* data buffer, e.g. firmware */ + + void *WP_POINTER_64 data; /* data buffer, e.g. firmware */ union{ /****** protocol-specific ************/ wan_x25_conf_t x25; /* X.25 configuration */ diff --git a/patches/kdrivers/include/wanpipe_cfg_def.h b/patches/kdrivers/include/wanpipe_cfg_def.h index cc41bfc..f62f923 100644 --- a/patches/kdrivers/include/wanpipe_cfg_def.h +++ b/patches/kdrivers/include/wanpipe_cfg_def.h @@ -226,4 +226,11 @@ enum { #define WAN_CLK_IN_2000HZ 0x06 #define WAN_CLK_IN_1500HZ 0x07 + +enum { + WANOPT_OCT_CHAN_OPERMODE_NORMAL, + WANOPT_OCT_CHAN_OPERMODE_SPEECH, + WANOPT_OCT_CHAN_OPERMODE_NO_ECHO, +}; + #endif /* __WANPIPE_CFG_DEF_H__ */ diff --git a/patches/kdrivers/include/wanpipe_codec_iface.h b/patches/kdrivers/include/wanpipe_codec_iface.h index d5d8301..f0acc0a 100644 --- a/patches/kdrivers/include/wanpipe_codec_iface.h +++ b/patches/kdrivers/include/wanpipe_codec_iface.h @@ -31,6 +31,11 @@ enum wan_codec_source_format{ WP_ALAW }; +#define WP_CODEC_FORMAT_DECODE(codec) \ +codec == WP_MULAW ? "WP_MULAW" : \ +codec == WP_ALAW ? "WP_ALAW" : \ +"Invalid Codec" + #if 0 enum wan_codec_format{ WP_NONE, diff --git a/patches/kdrivers/include/wanpipe_common.h b/patches/kdrivers/include/wanpipe_common.h index da9eb4c..1b8df96 100644 --- a/patches/kdrivers/include/wanpipe_common.h +++ b/patches/kdrivers/include/wanpipe_common.h @@ -13,6 +13,9 @@ * * ========================================================================== * + * Apr 26, 2010 David Rokhvarg Added "Global Irq lock" and "Mutex" + * functions. + * * Nov 09, 2009 David Rokhvarg Added wan_get_timestamp() * * Nov 27, 2007 David Rokhvarg Implemented functions/definitions for @@ -2807,6 +2810,7 @@ static __inline void wan_spin_unlock_irq(void *lock, wan_smp_flag_t *flag) # define wplip_spin_unlock_irq wan_spin_unlock_irq #endif +/* SPINLOCK functions */ static __inline int wan_spin_trylock(void *lock, wan_smp_flag_t *flag) { #if defined(__LINUX__) @@ -2818,7 +2822,7 @@ static __inline int wan_spin_trylock(void *lock, wan_smp_flag_t *flag) #elif defined(__NetBSD__) #warning "FIXME: Complete this code.!!!!!!!!!!!" #elif defined(__WINDOWS__) - return spin_trylock((wan_spinlock_t*)lock, flag); + return wp_spin_trylock((wan_spinlock_t*)lock, flag); #else # warning "wan_spin_trylock() function is not supported yet!" #endif @@ -2851,11 +2855,12 @@ static __inline void wan_spin_lock(void *lock, wan_smp_flag_t *flag) *((wan_spinlock_t*)lock) = splimp(); # endif #elif defined(__WINDOWS__) - spin_lock((wan_spinlock_t*)lock, flag); + wp_spin_lock((wan_spinlock_t*)lock, flag); #else # warning "wan_spin_lock() function is not supported yet!" #endif } + static __inline void wan_spin_unlock(void *lock, wan_smp_flag_t *flag) { #if defined(__LINUX__) @@ -2874,12 +2879,42 @@ static __inline void wan_spin_unlock(void *lock, wan_smp_flag_t *flag) #elif defined(__OpenBSD__) || defined(__NetBSD__) splx(*(wan_spinlock_t*)lock); #elif defined(__WINDOWS__) - spin_unlock((wan_spinlock_t*)lock, flag); + wp_spin_unlock((wan_spinlock_t*)lock, flag); #else # warning "wan_spin_unlock() function is not supported yet!" #endif } +/*============================================================== + * MUTEX functions. + */ + +static __inline void wan_mutex_lock(void *mutex, wan_smp_flag_t *flag /* FIXME: 'flag' should be removed */) +{ +#if defined(__WINDOWS__) + wp_mutex_lock(mutex); +#else + wan_spin_lock(mutex, flag); +#endif +} + +static __inline void wan_mutex_unlock(void *mutex, wan_smp_flag_t *flag /* FIXME: 'flag' should be removed */) +{ +#if defined(__WINDOWS__) + wp_mutex_unlock(mutex); +#else + wan_spin_unlock(mutex, flag); +#endif +} + +static __inline int wan_mutex_trylock(void *mutex, wan_smp_flag_t *flag /* FIXME: 'flag' should be removed */) +{ +#if defined(__WINDOWS__) + return wp_mutex_trylock(mutex); +#else + return wan_spin_trylock(mutex, flag); +#endif +} #if 0 diff --git a/patches/kdrivers/include/wanpipe_defines.h b/patches/kdrivers/include/wanpipe_defines.h index eb597c8..737d3aa 100644 --- a/patches/kdrivers/include/wanpipe_defines.h +++ b/patches/kdrivers/include/wanpipe_defines.h @@ -52,7 +52,7 @@ # define wp_unlink _unlink #else/* ! __WINDOWS__ */ # define wp_strlcpy strlcpy -# define wp_strncasecmp strnicmp +# define wp_strncasecmp wp_linux_strncasecmp # define wp_strcasecmp strcasecmp # define wp_snprintf snprintf # define wp_vsnprintf vsnprintf diff --git a/patches/kdrivers/include/wanpipe_includes.h b/patches/kdrivers/include/wanpipe_includes.h index d1bbdfb..9c427cb 100644 --- a/patches/kdrivers/include/wanpipe_includes.h +++ b/patches/kdrivers/include/wanpipe_includes.h @@ -358,7 +358,7 @@ # if defined( NDIS_MINIPORT_DRIVER ) # undef BINARY_COMPATIBLE # define BINARY_COMPATIBLE 0 /* Windows 2000 and later (no Win98 support) */ -# define NDIS50_MINIPORT 1 +/*# define NDIS51_MINIPORT 1 */ # include # include # include "wanpipe_abstr_types.h" diff --git a/patches/kdrivers/include/wanpipe_kernel.h b/patches/kdrivers/include/wanpipe_kernel.h index 5d86121..56871df 100644 --- a/patches/kdrivers/include/wanpipe_kernel.h +++ b/patches/kdrivers/include/wanpipe_kernel.h @@ -149,8 +149,7 @@ typedef int (wan_get_info_t)(char *, char **, off_t, int); #define IRQF_SHARED SA_SHIRQ #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) -static inline int strncasecmp(const char *s1, const char *s2, size_t n) +static inline int wp_linux_strncasecmp(const char *s1, const char *s2, size_t n) { if (n == 0) return 0; @@ -165,7 +164,6 @@ static inline int strncasecmp(const char *s1, const char *s2, size_t n) return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2); } -#endif /*========================================================================== KERNEL 2.6. @@ -702,8 +700,20 @@ static inline int open_dev_check(netdevice_t *dev) INIT_WORK((task),func) # endif # define WAN_IS_TASKQ_SCHEDULE + +#if 0 # define WAN_TASKQ_SCHEDULE(task) \ - wan_schedule_task(task) + { int err; \ + err =wan_schedule_task(task); \ + if (err) { \ + printk(KERN_INFO "%s:%d Error: Failed to schedule a Task (err=%i)!\n", __FUNCTION__,__LINE__,err); \ + } \ + } +#else +# define WAN_TASKQ_SCHEDULE(task) \ + wan_schedule_task(task); +#endif + # define WAN_TASKQ_STOP(task) \ wan_task_cancel(task) diff --git a/patches/kdrivers/include/wanpipe_lip.h b/patches/kdrivers/include/wanpipe_lip.h index 8667ce4..3600910 100644 --- a/patches/kdrivers/include/wanpipe_lip.h +++ b/patches/kdrivers/include/wanpipe_lip.h @@ -33,7 +33,7 @@ # include "wanpipe_katm_iface.h" #endif #if defined(CONFIG_PRODUCT_WANPIPE_XDLC) -# include "/wanpipe_xdlc_iface.h" +# include "wanpipe_xdlc_iface.h" #endif #if defined(CONFIG_PRODUCT_WANPIPE_XMTP2) # include "wanpipe_xmtp2_iface.h" diff --git a/patches/kdrivers/include/wanpipe_tdm_api.h b/patches/kdrivers/include/wanpipe_tdm_api.h index 1e76cbd..178f41d 100644 --- a/patches/kdrivers/include/wanpipe_tdm_api.h +++ b/patches/kdrivers/include/wanpipe_tdm_api.h @@ -104,6 +104,7 @@ static _inline unsigned char wp_get_next_expected_digit(unsigned char current_di #define WPTDM_WIN_LEGACY_API_MODE(tdm_api) (tdm_api->api_mode==WP_TDM_API_MODE_LEGACY_WIN_API) +#define TDMAPI_MAX_BUFFER_MULTIPLIER 8 typedef struct wanpipe_tdm_api_card_dev { @@ -124,6 +125,7 @@ typedef struct wanpipe_tdm_api_dev { void *card;/* pointer to sdla_t */ char name[WAN_IFNAME_SZ]; wan_spinlock_t lock; + wan_spinlock_t irq_lock; u32 used, open_cnt; u8 tdm_span; @@ -133,9 +135,9 @@ typedef struct wanpipe_tdm_api_dev { u32 active_ch; /* ALEX */ u8 *rx_buf; - int rx_buf_len; + u32 rx_buf_len; u8 *tx_buf; - int tx_buf_len; + u32 tx_buf_len; wanpipe_api_dev_cfg_t cfg; @@ -182,23 +184,27 @@ typedef struct wanpipe_tdm_api_dev { int (*read_rbs_bits)(void *chan, u32 ch, u8 *rbs_bits); int (*write_rbs_bits)(void *chan, u32 ch, u8 rbs_bits); int (*write_hdlc_frame)(void *chan, netskb_t *skb, wp_api_hdr_t *hdr); - int (*write_hdlc_check)(void *chan, int lock); + int (*write_hdlc_check)(void *chan, int lock, int bufs); int (*write_hdlc_timeout)(void *chan, int lock); int (*pipemon)(void* card, void* chan, void *udata); int (*driver_ctrl)(void *chan_ptr, int cmd, wanpipe_api_cmd_t *api_cmd); - unsigned int rbs_rx_bits[NUM_OF_E1_CHANNELS]; /* Rx RBS Bits */ + u32 rbs_rx_bits[NUM_OF_E1_CHANNELS]; /* Rx RBS Bits */ #ifdef WAN_TDMAPI_DTMF_TEST wp_dtmf_seq_t dtmf_check[NUM_OF_E1_CHANNELS+1]; /* Rx RBS Bits */ wp_dtmf_seq_t dtmf_check_event[NUM_OF_E1_CHANNELS+1]; /* Rx RBS Bits */ #endif - uint8_t dtmfsupport; + u8 dtmfsupport; void *cdev; - uint8_t operation_mode;/* WP_TDM_OPMODE */ - uint8_t api_mode; - int mtu_mru; + u8 operation_mode;/* WP_TDM_OPMODE */ + u8 api_mode; + u32 mtu_mru; void * mtp1_dev; + u32 buffer_multiplier; + u32 timeslots; + u8 loop_reenable_hwec; + }wanpipe_tdm_api_dev_t; diff --git a/patches/kdrivers/include/wanpipe_version.h b/patches/kdrivers/include/wanpipe_version.h index 148aff6..f535c56 100644 --- a/patches/kdrivers/include/wanpipe_version.h +++ b/patches/kdrivers/include/wanpipe_version.h @@ -6,11 +6,11 @@ #define __WANPIPE_VERSION__ -#define WANPIPE_COPYRIGHT_DATES "(c) 1994-2009" +#define WANPIPE_COPYRIGHT_DATES "(c) 1994-2010" #define WANPIPE_COMPANY "Sangoma Technologies Inc" /********** LINUX **********/ -#define WANPIPE_VERSION "3.5.11" +#define WANPIPE_VERSION "3.5.12" #define WANPIPE_SUB_VERSION "0" #define WANPIPE_LITE_VERSION "1.1.1" @@ -42,7 +42,7 @@ # define WANPIPE_VERSION_MAJOR 6 /* major upgrade */ # define WANPIPE_VERSION_MINOR 0 -# define WANPIPE_VERSION_MINOR1 19 /* frozen feature number */ +# define WANPIPE_VERSION_MINOR1 30 /* frozen feature number */ # define WANPIPE_VERSION_MINOR2 0 /* patch number for WANPIPE_VERSION_MINOR1 */ # undef VER_PRODUCTVERSION @@ -50,12 +50,12 @@ # undef VER_PRODUCTNAME_STR # undef VER_COMPANYNAME_STR -# define VER_PRODUCTVERSION 6,0,19,0 -# define VER_PRODUCTVERSION_STR "6.0.19.0" -# define __BUILDDATE__ February 25, 2010 +# define VER_PRODUCTVERSION 6,0,30,0 +# define VER_PRODUCTVERSION_STR "6.0.30.0" +# define __BUILDDATE__ June 22, 2010 # define VER_COMPANYNAME_STR "Sangoma Technologies Corporation" -# define VER_LEGALCOPYRIGHT_YEARS "1984-2011" +# define VER_LEGALCOPYRIGHT_YEARS "1984-2010" # define VER_LEGALCOPYRIGHT_STR "Copyright (c) Sangoma Technologies Corp." # define VER_PRODUCTNAME_STR "Sangoma WANPIPE (TM)" @@ -63,7 +63,7 @@ # undef WANPIPE_VERSION_BETA # undef WANPIPE_SUB_VERSION -# define WANPIPE_VERSION_Windows "6.0.19" +# define WANPIPE_VERSION_Windows "6.0.30" # define WANPIPE_SUB_VERSION_Windows "0" # define WANPIPE_VERSION_BETA_Windows 0 diff --git a/patches/kdrivers/include/wanrouter.h b/patches/kdrivers/include/wanrouter.h index 805324b..edcd615 100644 --- a/patches/kdrivers/include/wanrouter.h +++ b/patches/kdrivers/include/wanrouter.h @@ -343,7 +343,7 @@ typedef struct wan_device int (*get_info)(void*, struct seq_file* m, int *); void (*fe_enable_timer) (void* card_id); void (*te_report_rbsbits) (void* card_id, int channel, unsigned char rbsbits); - void (*te_report_alarms) (void* card_id, unsigned long alarams); + void (*te_report_alarms) (void* card_id, uint32_t alarms); void (*te_link_state) (void* card_id); void (*te_link_reset) (void* card_id); int (*te_signaling_config) (void* card_id, unsigned long); diff --git a/patches/kdrivers/include/zapcompat.h b/patches/kdrivers/include/zapcompat.h index 77b29d3..6224216 100644 --- a/patches/kdrivers/include/zapcompat.h +++ b/patches/kdrivers/include/zapcompat.h @@ -36,6 +36,12 @@ #undef DAHDI_22 #endif +#ifdef DAHDI_AUDIO_NOTIFY +#define DAHDI_23 +#else +#undef DAHDI_23 +#endif + // defines #define ZT_CODE DAHDI_CODE diff --git a/patches/kdrivers/src/lip/wanpipe_lip_prot.c b/patches/kdrivers/src/lip/wanpipe_lip_prot.c index b801d8c..e2bfe57 100644 --- a/patches/kdrivers/src/lip/wanpipe_lip_prot.c +++ b/patches/kdrivers/src/lip/wanpipe_lip_prot.c @@ -332,7 +332,7 @@ int wplip_prot_oob(wplip_dev_t *lip_dev, unsigned char *data, int len) rx_el=(wan_api_rx_hdr_t*)wan_skb_push(skb,sizeof(wan_api_rx_hdr_t)); /* FIXME: */ - rx_el->u.lapb.exception=0; + rx_el->lapb.exception=0; skb->protocol=htons(ETH_P_X25); break; #endif @@ -346,9 +346,9 @@ int wplip_prot_oob(wplip_dev_t *lip_dev, unsigned char *data, int len) return -1; } rx_el=(wan_api_rx_hdr_t*)wan_skb_push(skb,sizeof(wan_api_rx_hdr_t)); - rx_el->u.xdlc.state=xdlc_excep->state; - rx_el->u.xdlc.address=xdlc_excep->address; - rx_el->u.xdlc.exception=xdlc_excep->exception; + rx_el->xdlc.state=xdlc_excep->state; + rx_el->xdlc.address=xdlc_excep->address; + rx_el->xdlc.exception=xdlc_excep->exception; skb->protocol=htons(ETH_P_X25); } break; diff --git a/patches/kdrivers/src/net/Makefile b/patches/kdrivers/src/net/Makefile index 5227c38..5db6792 100644 --- a/patches/kdrivers/src/net/Makefile +++ b/patches/kdrivers/src/net/Makefile @@ -15,14 +15,7 @@ CONFIG_WANPIPE_CHDLC=n CONFIG_WANPIPE_PPP=n CONFIG_WANPIPE_MULTPPP=n -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 +EXTRA_CFLAGS=$(EXTRA_FLAGS) wanpipe-y := sdlamain.o diff --git a/patches/kdrivers/src/net/Module.symvers b/patches/kdrivers/src/net/Module.symvers new file mode 100644 index 0000000..9a237e9 --- /dev/null +++ b/patches/kdrivers/src/net/Module.symvers @@ -0,0 +1,135 @@ +0x7c19de34 got_new_syncer /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xc6edf870 vpmadt032_free /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/voicebus/dahdi_voicebus EXPORT_SYMBOL +0xc877a4cb put_xframe /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x8c78cb9b xframe_next_packet /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x92e7bb62 xframe_queue_clearstats /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x19e75bf2 voicebus_stop /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/voicebus/dahdi_voicebus EXPORT_SYMBOL +0x6072c8a2 dahdi_transcoder_register /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi_transcode EXPORT_SYMBOL +0x597475a3 dahdi_register_chardev /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0x48bddc3c voicebus_current_latency /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/voicebus/dahdi_voicebus EXPORT_SYMBOL +0xe5a5dabe dahdi_transcoder_alloc /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi_transcode EXPORT_SYMBOL +0x0c3b63d8 pcmtx_chan /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x12dfa58e dahdi_qevent_nolock /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0xf5d22416 get_xframe /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xce69e3a7 dahdi_hooksig /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0xe6ce6bea sync_mode_name /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x2cc2381f update_wanted_pcm_mask /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x47151521 xbus_activate /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xa79ecb53 xbus_disconnect /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x2974b24a generic_card_pcm_tospan /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xc945873d dahdi_register /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0x8e0e566e xproto_register /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x537eb672 xframe_receive /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x12cb4707 xpd_post_init /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xd7eeeeb5 report_bad_ioctl /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xd63e1d87 voicebus_release /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/voicebus/dahdi_voicebus EXPORT_SYMBOL +0xb522bb3f vpmadt032_reset /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/voicebus/dahdi_voicebus EXPORT_SYMBOL +0x425ddbab xbus_request_removal /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x60c154c5 update_xpd_status /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x599e779b vpmadt032_echocan_free /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/voicebus/dahdi_voicebus EXPORT_SYMBOL +0x006a2198 __dahdi_mulaw /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0xc5fb06b9 xproto_name /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xddf2e333 xpp_open /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x9513f4ff run_initialize_registers /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x01b0f433 xpd_alloc /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x635a1d83 gpakConfigurePorts /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/voicebus/dahdi_voicebus EXPORT_SYMBOL +0xf4a2bf8e xframe_queue_init /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xa78a3f8f notify_rxsig /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x592e5c90 xbus_setstate /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x55b59227 vpmadt032_echocan_create /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/voicebus/dahdi_voicebus EXPORT_SYMBOL +0x13c7069b dahdi_transcode_fops /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0xd083d5c4 send_pcm_frame /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x8b05ea95 xbus_deactivate /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xdc3a2c77 xbus_free /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x38e1c7fd xpp_close /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xcd6633df dahdi_set_dynamic_ioctl /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0xc2b56d8c vpmadt032_get_default_parameters /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/voicebus/dahdi_voicebus EXPORT_SYMBOL +0x97eb6143 xframe_enqueue /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x624e96fa xframe_dequeue /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x9c462e00 voicebus_set_minlatency /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/voicebus/dahdi_voicebus EXPORT_SYMBOL +0xe0c9b849 dahdi_transcoder_unregister /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi_transcode EXPORT_SYMBOL +0xf42f429a dahdi_init_tone_state /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0xaf8e1806 xpd_driver_register /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x06403f91 put_xpd /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xbdc234d9 vpmadtreg_register /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/voicebus/dahdi_voicebus EXPORT_SYMBOL +0x71aafde0 vpmadtreg_unregister /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/voicebus/dahdi_voicebus EXPORT_SYMBOL +0xad0e46e6 debug /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xbdd1b41c dahdi_unregister_echocan_factory /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0xb3af45ff generic_card_pcm_recompute /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xb48548fa __dahdi_lin2a /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0x2d6794f0 xpd_byaddr /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xb1d6d6be hookstate_changed /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xef11c1ba dahdi_unregister /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0x3d183b5d get_xpd /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x82e127c6 send_cmd_frame /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x72d0bb1d dahdi_hdlc_getbuf /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0x0cca3f0e __dahdi_lin2mu /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0x6a062e24 xframe_queue_disable /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x373bca89 xbus_receive_xframe /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xad1272e5 dump_reg_cmd /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x4ce4fe8b dahdi_qevent_lock /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0x8f9e9e1f dahdi_alarm_notify /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0x8f645409 dahdi_sync_tick /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x068090ff notify_bad_xpd /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x91c86c35 dahdi_register_echocan_factory /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0x8e04fd95 dump_xframe /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xb2cc48ff elect_syncer /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x3d8bebde mark_offhook /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x0231f4ab transportops_get /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xd5c12072 transportops_put /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x05d662e5 dahdi_unregister_chardev /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0x5a8b7434 voicebus_vbb_cache /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/voicebus/dahdi_voicebus EXPORT_SYMBOL +0xa72dc741 dahdi_transcoder_alert /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi_transcode EXPORT_SYMBOL +0x4b8cdbf2 xproto_global_entry /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x8ba85e84 xbus_connect /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xe5eb1132 gpakPingDsp /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/voicebus/dahdi_voicebus EXPORT_SYMBOL +0xec7b087b gpakConfigureChannel /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/voicebus/dahdi_voicebus EXPORT_SYMBOL +0xd07870ea xpd_of /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xfdd623b4 valid_xpd_addr /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xf0f056a0 xpd_free /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x64a6fdeb alarm2str /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xcf1a0233 xpp_ioctl /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x23e9e447 dahdi_dynamic_receive /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi_dynamic EXPORT_SYMBOL +0xdd7bc49e dahdi_receive /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0x058098af xframe_queue_clear /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x141f7b48 xproto_card_entry /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x0a29c949 generic_card_pcm_fromspan /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x28c9b161 dump_packet /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x8ceddc4b vpmadt032_alloc /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/voicebus/dahdi_voicebus EXPORT_SYMBOL +0x7cc79ec0 dahdi_alarm_channel /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0x6045e8cb dahdi_dynamic_register /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi_dynamic EXPORT_SYMBOL +0x430a8848 dahdi_mf_tone /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0x821b2778 dump_poll /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x65e6b5eb vpmadt032_init /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/voicebus/dahdi_voicebus EXPORT_SYMBOL +0x7817cb58 xbus_reset_counters /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xa2d6910d oht_pcm /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x67428f4d dahdi_ec_span /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0xed5e8380 dahdi_transcoder_free /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi_transcode EXPORT_SYMBOL +0x528a0730 xframe_queue_count /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xa9b5f188 xbus_command_queue_tick /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xa407ff09 voicebus_start /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/voicebus/dahdi_voicebus EXPORT_SYMBOL +0xc4071a06 __dahdi_alaw /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0x7b40a84d dahdi_hdlc_putbuf /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0x31386140 dahdi_hdlc_abort /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0x529d6203 dahdi_lboname /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0x2dfb51e3 create_xpd /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xc95646c8 voicebus_transmit /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/voicebus/dahdi_voicebus EXPORT_SYMBOL +0xc80ea69b xpp_maint /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xb53d0d74 __voicebus_init /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/voicebus/dahdi_voicebus EXPORT_SYMBOL +0xc11b8c26 xpd_driver_unregister /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x782bbc32 dahdi_transmit /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0x3ee7da88 dahdi_hdlc_finish /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0xfaa93356 xpp_register_request /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x6aa023ac xbus_statename /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xeb2ef21c xbus_request_sync /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x4914a44f dahdi_rbsbits /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0x8019389a gpakAlgControl /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/voicebus/dahdi_voicebus EXPORT_SYMBOL +0x120e8bb6 send_multibyte_request /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xf22c9714 xframe_init /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x2ef28734 pcmtx /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x71672675 dahdi_dynamic_unregister /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi_dynamic EXPORT_SYMBOL +0xe5a73e62 dahdi_set_hpec_ioctl /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0x6d91edc4 xproto_unregister /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0x0bd2816a dahdi_ec_chunk /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/dahdi EXPORT_SYMBOL +0xbff0a11c xbus_num /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL +0xd296bbaa xbus_new /usr/src/ast1.6/dahdi-linux-2.3.0.1/drivers/dahdi/xpp/xpp EXPORT_SYMBOL diff --git a/patches/kdrivers/src/net/aft_a104.c b/patches/kdrivers/src/net/aft_a104.c index c262bef..315ec97 100644 --- a/patches/kdrivers/src/net/aft_a104.c +++ b/patches/kdrivers/src/net/aft_a104.c @@ -1303,10 +1303,6 @@ int a104_chip_unconfig(sdla_t *card) AFT_FUNC_DEBUG(); #if INIT_FE_ONLY - if (card->wandev.fe_iface.pre_release){ - card->wandev.fe_iface.pre_release(&card->fe); - } - if (card->wandev.fe_iface.unconfig){ card->wandev.fe_iface.unconfig(&card->fe); } @@ -1336,16 +1332,14 @@ int a104_chip_unconfig(sdla_t *card) if (IS_TE1_CARD(card)) { wan_smp_flag_t smp_flags1; - if (card->wandev.fe_iface.pre_release){ - card->wandev.fe_iface.pre_release(&card->fe); - } card->hw_iface.hw_lock(card->hw,&smp_flags1); - aft_fe_intr_ctrl(card,0); + aft_fe_intr_ctrl(card,0); if (card->wandev.fe_iface.unconfig){ card->wandev.fe_iface.unconfig(&card->fe); } - aft_fe_intr_ctrl(card,1); + aft_fe_intr_ctrl(card,1); card->hw_iface.hw_unlock(card->hw,&smp_flags1); + }else if (IS_56K_CARD(card)) { //reset_on_LXT441PE(card); aft_56k_write_cpld(card, 0x00,0x00); diff --git a/patches/kdrivers/src/net/aft_bri.c b/patches/kdrivers/src/net/aft_bri.c index c61fc62..1bf87f8 100644 --- a/patches/kdrivers/src/net/aft_bri.c +++ b/patches/kdrivers/src/net/aft_bri.c @@ -885,18 +885,13 @@ int aft_bri_chip_unconfig(sdla_t *card) card->wandev.hwec_enable = NULL; card->wandev.ec_dev = NULL; - /* Unconfiging, only on shutdown */ - if (card->wandev.fe_iface.pre_release){ - card->wandev.fe_iface.pre_release(&card->fe); - } - card->hw_iface.hw_lock(card->hw,&smp_flags1); wan_spin_lock_irq(&card->wandev.lock, &smp_flags); __aft_fe_intr_ctrl(card,0); if (card->wandev.fe_iface.unconfig){ card->wandev.fe_iface.unconfig(&card->fe); } - __aft_fe_intr_ctrl(card,0); + __aft_fe_intr_ctrl(card,0 /* FIXME: should it be 1? */); wan_spin_unlock_irq(&card->wandev.lock, &smp_flags); card->hw_iface.hw_unlock(card->hw,&smp_flags1); diff --git a/patches/kdrivers/src/net/aft_core.c b/patches/kdrivers/src/net/aft_core.c index ffd27b7..493daf1 100644 --- a/patches/kdrivers/src/net/aft_core.c +++ b/patches/kdrivers/src/net/aft_core.c @@ -1,11 +1,11 @@ /***************************************************************************** * aft_core.c * -* WANPIPE(tm) AFT CORE Hardware Support +* WANPIPE(tm) AFT CORE Hardware Support * * Authors: Nenad Corbic * -* Copyright: (c) 2003-2009 Sangoma Technologies Inc. +* Copyright: (c) 2003-2010 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 @@ -237,6 +237,8 @@ #endif #endif + + WAN_DECLARE_NETDEV_OPS(wan_netdev_ops) /*================================================================= @@ -408,7 +410,6 @@ static void aft_data_mux_cfg(sdla_t *card); static void aft_data_mux_get_cfg(sdla_t *card); static int aft_ss7_tx_mangle(sdla_t *card,private_area_t *chan, netskb_t *skb); -static int aft_hdlc_repeat_mangle(sdla_t *card,private_area_t *chan, netskb_t *skb, netskb_t **rkb); static int aft_tdmv_init(sdla_t *card, wandev_conf_t *conf); #if defined(CONFIG_PRODUCT_WANPIPE_TDM_VOICE) @@ -602,12 +603,16 @@ int wp_aft_analog_init (sdla_t *card, wandev_conf_t* conf) ASSERT_AFT_HWDEV(card->wandev.card_type); - if (card->adptr_type != A200_ADPTR_ANALOG && - card->adptr_type != A400_ADPTR_ANALOG && - card->adptr_type != AFT_ADPTR_FLEXBRI) { - DEBUG_ERROR( "%s: Error: Attempting to configure for Analog on non A200/A400/B700 analog hw!\n", + switch(card->adptr_type) { + case A200_ADPTR_ANALOG: + case A400_ADPTR_ANALOG: + case AFT_ADPTR_FLEXBRI: + case AFT_ADPTR_B800: + break; + default: + DEBUG_ERROR( "%s: Error: Attempting to configure for Analog on non A200/A400/B700/B800 analog hw!\n", card->devname); - return -EINVAL; + return -EINVAL; } card->hw_iface.getcfg(card->hw, SDLA_COREREV, &card->u.aft.firm_ver); @@ -1343,15 +1348,19 @@ static int wan_aft_init (sdla_t *card, wandev_conf_t* conf) wan_set_bit(AFT_TDM_FREE_RUN_ISR,&card->u.aft.chip_cfg_status); } - if ((card->adptr_type == A108_ADPTR_8TE1 && - card->u.aft.firm_ver >= 0x40) || + if (card->adptr_type == A108_ADPTR_8TE1 && + card->u.aft.firm_ver >= 0x40) { +#if 0 + /* NC: The A104/2/1 do not have this feature yet! */ + || (card->adptr_type == A104_ADPTR_4TE1 && card->u.aft.firm_ver >= 0x37) || (card->adptr_type == A101_ADPTR_2TE1 && card->u.aft.firm_ver >= 0x37) || (card->adptr_type == A101_ADPTR_1TE1 && card->u.aft.firm_ver >= 0x37)) { - wan_set_bit(AFT_TDM_FE_SYNC_CNT,&card->u.aft.chip_cfg_status); +#endif + wan_set_bit(AFT_TDM_FE_SYNC_CNT,&card->u.aft.chip_cfg_status); } @@ -1810,17 +1819,6 @@ static int new_if_private (wan_device_t* wandev, netdevice_t* dev, wanif_conf_t* conf->hdlc_streaming=1; } - if (chan->cfg.hdlc_repeat) { - if (!conf->hdlc_streaming) { - DEBUG_EVENT("%s: HDLC Repeat configured for non hdlc channel!\n", - chan->if_name); - err= -EINVAL; - goto new_if_error; - } - chan->dma_chain_opmode = WAN_AFT_DMA_CHAIN_SINGLE; - conf->hdlc_streaming=1; - } - chan->channelized_cfg=channelized; chan->wp_api_iface_mode=0; @@ -2537,7 +2535,16 @@ static int new_if_private (wan_device_t* wandev, netdevice_t* dev, wanif_conf_t* goto new_if_error; } + /* HDLC repeat does not work in hdlc eng mode */ + chan->cfg.hdlc_repeat=0; + }else{ + + /* In case hdlc repeat is on, make sure we disable dma chain */ + if (chan->cfg.hdlc_repeat) { + chan->dma_chain_opmode = WAN_AFT_DMA_CHAIN_SINGLE; + } + /* If hardware HDLC engine is enabled: * 1. Force Disable DATA MUX option * just in case user made a mistake @@ -2981,11 +2988,11 @@ static int new_if (wan_device_t* wandev, netdevice_t* dev, wanif_conf_t* conf) return -EINVAL; } - if(IS_BRI_CARD(card)) { + if (IS_BRI_CARD(card)) { wan_set_bit(BRI_DCHAN_LOGIC_CHAN,&card->u.aft.tdmv_dchan); } - if (card->wandev.fe_iface.active_map){ + if (card->wandev.fe_iface.active_map) { conf->active_ch = card->wandev.fe_iface.active_map(&card->fe, 0); if(IS_BRI_CARD(card)) { @@ -3012,8 +3019,14 @@ static int new_if (wan_device_t* wandev, netdevice_t* dev, wanif_conf_t* conf) #endif conf->active_ch=active_ch&~(card->tdmv_conf.dchan); + + /* If only dchan timeslots are configured allow it */ conf->u.aft.tdmv_master_if=1; - err=new_if_private(wandev,dev,conf,0,-1,if_cnt); + if (conf->active_ch == 0 && card->tdmv_conf.dchan) { + err=0; + } else { + err=new_if_private(wandev,dev,conf,0,-1,if_cnt); + } if (!err){ /* Setup DCHAN if any */ @@ -3216,7 +3229,7 @@ static int del_if_private (wan_device_t* wandev, netdevice_t* dev) #ifdef CONFIG_PRODUCT_WANPIPE_ANNEXG - if (chan->common.usedby == ANNEXG && chan->annexg_dev){ + if (chan->common.usedby == ANNEXG && chan->annexg_dev) { netdevice_t *tmp_dev; int err; @@ -3330,6 +3343,9 @@ static int del_if_private (wan_device_t* wandev, netdevice_t* dev) WAN_IFQ_PURGE(&chan->wp_dealloc_list); WAN_IFQ_DESTROY(&chan->wp_dealloc_list); + WAN_IFQ_PURGE(&chan->wp_tx_hdlc_rpt_list); + WAN_IFQ_DESTROY(&chan->wp_tx_hdlc_rpt_list); + if (chan->tx_idle_skb){ wan_skb_free(chan->tx_idle_skb); chan->tx_idle_skb=NULL; @@ -3385,6 +3401,8 @@ static int del_if (wan_device_t* wandev, netdevice_t* dev) int card_use_cnt=0; int err=0; + + if (!chan){ DEBUG_ERROR("%s: Critical Error del_if() chan=NULL!\n", wan_netif_name(dev)); @@ -3397,6 +3415,7 @@ static int del_if (wan_device_t* wandev, netdevice_t* dev) return 0; } + WAN_DEBUG_FUNC_START; card->hw_iface.getcfg(card->hw, SDLA_HWCPU_USEDCNT, &card_use_cnt); @@ -3496,6 +3515,8 @@ static int del_if (wan_device_t* wandev, netdevice_t* dev) wan_free(chan); } + WAN_DEBUG_FUNC_END; + return err; } @@ -3533,6 +3554,8 @@ static void disable_comm (sdla_t *card) int port_task_timeout=0; int err=0; + WAN_DEBUG_FUNC_START; + card->hw_iface.getcfg(card->hw, SDLA_HWCPU_USEDCNT, &used_cnt); card->hw_iface.getcfg(card->hw, SDLA_HWTYPE_USEDCNT, &used_type_cnt); @@ -3542,13 +3565,70 @@ static void disable_comm (sdla_t *card) AFT_FUNC_DEBUG(); #if INIT_FE_ONLY + /* purposely fail compile here. this option is valid only on debug */ ... aft_chip_unconfigure(card); #else - /* Make sure that Task is disabled for this card */ + + aft_background_timer_kill(card); + + card->hw_iface.hw_lock(card->hw,&smp_flags1); + wan_spin_lock_irq(&card->wandev.lock, &smp_flags); + if (card->wandev.fe_iface.unconfig){ + card->wandev.fe_iface.unconfig(&card->fe); + } + wan_spin_unlock_irq(&card->wandev.lock, &smp_flags); + card->hw_iface.hw_unlock(card->hw,&smp_flags1); + + + + /* Disable DMA ENGINE before we perform + * core reset. Otherwise, we will receive + * rx fifo errors on subsequent resetart. */ + wan_spin_lock_irq(&card->wandev.lock,&smp_flags); + disable_data_error_intr(card,DEVICE_DOWN); + +#if defined(AFT_RTP_SUPPORT) + aft_rtp_unconfig(card); +#endif + + wan_spin_unlock_irq(&card->wandev.lock,&smp_flags); + + aft_handle_clock_master(card); + + aft_chip_unconfigure(card); + + + /* Confirm that interrupts are disabled */ + wan_spin_lock_irq(&card->wandev.lock,&smp_flags); + disable_data_error_intr(card,DEVICE_DOWN); + wan_set_bit(CARD_DOWN,&card->wandev.critical); + wan_spin_unlock_irq(&card->wandev.lock,&smp_flags); + + card->hw_iface.hw_lock(card->hw,&smp_flags1); + wan_spin_lock_irq(&card->wandev.lock,&smp_flags); + aft_hwdev[card->wandev.card_type].aft_led_ctrl(card, WAN_AFT_RED, 0,WAN_AFT_ON); + aft_hwdev[card->wandev.card_type].aft_led_ctrl(card, WAN_AFT_GREEN, 0, WAN_AFT_ON); + + __sdla_pull_ptr_isr_array(card->hw,card,WAN_FE_LINENO(&card->fe)); wan_set_bit(CARD_PORT_TASK_DOWN,&card->wandev.critical); + wan_spin_unlock_irq(&card->wandev.lock,&smp_flags); + card->hw_iface.hw_unlock(card->hw,&smp_flags1); + + wp_timer_device_unreg(card); + + +#if defined(WAN_TASKQ_STOP) + err=WAN_TASKQ_STOP((&card->u.aft.port_task)); + DEBUG_EVENT("%s: %s\n",card->devname, err?"TASKQ Successfully Stopped":"TASKQ Not Running"); +#endif + + /* Make sure that Task is disabled for this card */ + /* NC: moved this section down from top of the file because + if one sets this bit while interrups are still no + a race condition is possible */ while (wan_test_bit(CARD_PORT_TASK_RUNNING,&card->wandev.critical)) { disable_comm_delay(); /* 100 ms */ port_task_timeout++; @@ -3558,64 +3638,10 @@ static void disable_comm (sdla_t *card) } } -#if defined(WAN_TASKQ_STOP) - err=WAN_TASKQ_STOP((&card->u.aft.port_task)); - DEBUG_EVENT("%s: %s\n",card->devname, err?"TASKQ Successfully Stopped":"TASKQ Not Running"); -#endif - - aft_background_timer_kill(card); - - /* Unconfiging, only on shutdown */ - if (card->wandev.fe_iface.pre_release){ - card->wandev.fe_iface.pre_release(&card->fe); + /* Release front end resources only after all interrupts and tasks have been shut down */ + if (card->wandev.fe_iface.post_unconfig) { + card->wandev.fe_iface.post_unconfig(&card->fe); } - card->hw_iface.hw_lock(card->hw,&smp_flags1); - wan_spin_lock_irq(&card->wandev.lock, &smp_flags); - if (card->wandev.fe_iface.unconfig){ - card->wandev.fe_iface.unconfig(&card->fe); - } - wan_spin_unlock_irq(&card->wandev.lock, &smp_flags); - card->hw_iface.hw_unlock(card->hw,&smp_flags1); - - /* Disable DMA ENGINE before we perform - * core reset. Otherwise, we will receive - * rx fifo errors on subsequent resetart. */ - wan_spin_lock_irq(&card->wandev.lock,&smp_flags); - disable_data_error_intr(card,DEVICE_DOWN); - -#if defined(AFT_RTP_SUPPORT) - aft_rtp_unconfig(card); -#endif - - __aft_fe_intr_ctrl(card, 0); - wan_spin_unlock_irq(&card->wandev.lock,&smp_flags); - - aft_handle_clock_master(card); - - aft_chip_unconfigure(card); - - /* Only disable the irq completely once the - chip unconfigure is executed */ - wan_spin_lock_irq(&card->wandev.lock,&smp_flags); - disable_data_error_intr(card,DEVICE_DOWN); - wan_set_bit(CARD_DOWN,&card->wandev.critical); - wan_spin_unlock_irq(&card->wandev.lock,&smp_flags); - - WP_DELAY(10); - - - - card->hw_iface.hw_lock(card->hw,&smp_flags1); - wan_spin_lock_irq(&card->wandev.lock,&smp_flags); - aft_hwdev[card->wandev.card_type].aft_led_ctrl(card, WAN_AFT_RED, 0,WAN_AFT_ON); - aft_hwdev[card->wandev.card_type].aft_led_ctrl(card, WAN_AFT_GREEN, 0, WAN_AFT_ON); - - __sdla_pull_ptr_isr_array(card->hw,card,WAN_FE_LINENO(&card->fe)); - - wan_spin_unlock_irq(&card->wandev.lock,&smp_flags); - card->hw_iface.hw_unlock(card->hw,&smp_flags1); - - wp_timer_device_unreg(card); if (used_type_cnt<=1){ DEBUG_EVENT("%s: Global Chip Shutdown Usage=%d, Used_type_cnt=%d\n", @@ -3628,16 +3654,15 @@ static void disable_comm (sdla_t *card) aft_global_chip_disable(card); wan_spin_unlock_irq(&card->wandev.lock,&smp_flags); card->hw_iface.hw_unlock(card->hw,&smp_flags1); - } else { - /* only re-enable front end interrupt if this - * card is not last card */ - aft_fe_intr_ctrl(card, 1); } /* Initialize the AFT operation structure so on subsequent restart - the card->u.aft strcutre is fully initialized */ + the card->u.aft strcutre is fully initialized */ memset(&card->u.aft,0,sizeof(card->u.aft)); #endif + + WAN_DEBUG_FUNC_END; + return; } @@ -4136,8 +4161,8 @@ static int if_send(netdevice_t *dev, netskb_t *skb, struct sockaddr *dst,struct } /* For TDM_VOICE_API no tx is supported in if_send */ - if (chan->common.usedby == TDM_VOICE_API || chan->wp_api_op_mode){ - DEBUG_WARNING("%s: Warning: IF SEND TX: Chan in VOICE API Mode\n", + if (chan->common.usedby == TDM_VOICE_API || chan->wp_api_op_mode || chan->common.usedby == XMTP2_API){ + DEBUG_WARNING("%s: Warning: IF SEND TX: Chan in VOICE API/XMTP2 Mode\n", card->devname); WAN_NETIF_STATS_INC_TX_ERRORS(&chan->common); WP_AFT_CHAN_ERROR_STATS(chan->chan_stats,tx_errors); @@ -4185,8 +4210,8 @@ static int if_send(netdevice_t *dev, netskb_t *skb, struct sockaddr *dst,struct err=0; goto if_send_exit_crit; } - } else if (chan->cfg.hdlc_repeat) { - err=aft_hdlc_repeat_mangle(card,chan,skb,&rskb); + } else if (chan->hdlc_eng && chan->cfg.hdlc_repeat) { + err=aft_hdlc_repeat_mangle(card,chan,skb,(wp_api_hdr_t*)wan_skb_data(skb),&rskb); if (err){ wan_skb_free(skb); WAN_NETIF_STATS_INC_TX_ERRORS(&chan->common); @@ -4196,6 +4221,9 @@ static int if_send(netdevice_t *dev, netskb_t *skb, struct sockaddr *dst,struct err=0; goto if_send_exit_crit; } + + wan_skb_pull(skb,sizeof(wp_api_hdr_t)); + } else { wan_skb_pull(skb,sizeof(wp_api_hdr_t)); } @@ -5072,7 +5100,7 @@ static void aft_rx_post_complete (sdla_t *card, private_area_t *chan, unsigned char *pkt_error) { - unsigned int len,data_error = 0; + unsigned int len,data_error = 0; unsigned char *buf; wp_rx_element_t *rx_el; u32 dma_status; @@ -5105,7 +5133,12 @@ static void aft_rx_post_complete (sdla_t *card, private_area_t *chan, WAN_NETIF_STATS_INC_RX_ERRORS(&chan->common); //chan->if_stats.rx_errors++; chan->errstats.Rx_dma_descr_err++; WP_AFT_CHAN_ERROR_STATS(chan->chan_stats,rx_errors); - goto rx_comp_error; + + wan_set_bit(WP_DMA_ERROR_BIT,&rx_el->pkt_error); + + if (chan->common.usedby != API && chan->common.usedby != TDM_VOICE_DCHAN) { + goto rx_comp_error; + } } /* Checking Rx DMA PCI error status. Has to be '0's */ @@ -5113,34 +5146,38 @@ static void aft_rx_post_complete (sdla_t *card, private_area_t *chan, if (wan_test_bit(AFT_RXDMA_HIDMASTATUS_PCI_M_ABRT,&dma_status)){ if (WAN_NET_RATELIMIT()){ - DEBUG_ERROR("%s:%s: Rx Error: Abort from Master: pci fatal error 0x%X!\n", - card->devname,chan->if_name,rx_el->reg); + DEBUG_ERROR("%s:%s: Rx Error: Abort from Master: pci fatal error 0x%X!\n", + card->devname,chan->if_name,rx_el->reg); } - } + } if (wan_test_bit(AFT_RXDMA_HIDMASTATUS_PCI_T_ABRT,&dma_status)){ - if (WAN_NET_RATELIMIT()){ - DEBUG_ERROR("%s:%s: Rx Error: Abort from Target: pci fatal error 0x%X!\n", + if (WAN_NET_RATELIMIT()){ + DEBUG_ERROR("%s:%s: Rx Error: Abort from Target: pci fatal error 0x%X!\n", card->devname,chan->if_name,rx_el->reg); } - } + } if (wan_test_bit(AFT_RXDMA_HIDMASTATUS_PCI_DS_TOUT,&dma_status)){ - if (WAN_NET_RATELIMIT()){ - DEBUG_ERROR("%s:%s: Rx Error: No 'DeviceSelect' from target: pci fatal error 0x%X!\n", + if (WAN_NET_RATELIMIT()){ + DEBUG_ERROR("%s:%s: Rx Error: No 'DeviceSelect' from target: pci fatal error 0x%X!\n", card->devname,chan->if_name,rx_el->reg); } - } + } if (wan_test_bit(AFT_RXDMA_HIDMASTATUS_PCI_RETRY,&dma_status)){ - if (WAN_NET_RATELIMIT()){ - DEBUG_ERROR("%s:%s: Rx Error: 'Retry' exceeds maximum (64k): pci fatal error 0x%X!\n", + if (WAN_NET_RATELIMIT()){ + DEBUG_ERROR("%s:%s: Rx Error: 'Retry' exceeds maximum (64k): pci fatal error 0x%X!\n", card->devname,chan->if_name,rx_el->reg); } - } + } chan->errstats.Rx_pci_errors++; WAN_NETIF_STATS_INC_RX_ERRORS(&chan->common); //chan->if_stats.rx_errors++; card->wandev.stats.rx_errors++; WP_AFT_CHAN_ERROR_STATS(chan->chan_stats,rx_errors); - goto rx_comp_error; + + wan_set_bit(WP_DMA_ERROR_BIT,&rx_el->pkt_error); + if (chan->common.usedby != API && chan->common.usedby != TDM_VOICE_DCHAN) { + goto rx_comp_error; + } } if (chan->hdlc_eng){ @@ -5154,7 +5191,11 @@ static void aft_rx_post_complete (sdla_t *card, private_area_t *chan, chan->errstats.Rx_hdlc_corrupiton++; card->wandev.stats.rx_errors++; WP_AFT_CHAN_ERROR_STATS(chan->chan_stats,rx_frame_errors); - goto rx_comp_error; + wan_set_bit(WP_FRAME_ERROR_BIT,&rx_el->pkt_error); + + if (chan->common.usedby != API && chan->common.usedby != TDM_VOICE_DCHAN) { + goto rx_comp_error; + } } /* Checking Rx DMA Frame end bit. (information for api) */ @@ -5166,7 +5207,11 @@ static void aft_rx_post_complete (sdla_t *card, private_area_t *chan, chan->errstats.Rx_hdlc_corrupiton++; card->wandev.stats.rx_errors++; WP_AFT_CHAN_ERROR_STATS(chan->chan_stats,rx_frame_errors); - goto rx_comp_error; + wan_set_bit(WP_FRAME_ERROR_BIT,&rx_el->pkt_error); + + if (chan->common.usedby != API && chan->common.usedby != TDM_VOICE_DCHAN) { + goto rx_comp_error; + } } else { /* Check CRC error flag only if this is the end of Frame */ @@ -5190,26 +5235,68 @@ static void aft_rx_post_complete (sdla_t *card, private_area_t *chan, WAN_NETIF_STATS_INC_RX_FRAME_ERRORS(&chan->common); //chan->if_stats.rx_frame_errors++; chan->errstats.Rx_hdlc_corrupiton++; card->wandev.stats.rx_frame_errors++; - WP_AFT_CHAN_ERROR_STATS(chan->chan_stats,rx_frame_errors); + /* for API increment counter for HDLC Aborts - not an error */ + WP_AFT_CHAN_ERROR_STATS(chan->chan_stats,rx_hdlc_abort_counter); wan_set_bit(WP_ABORT_ERROR_BIT,&rx_el->pkt_error); data_error = 1; } - if (chan->common.usedby != API && data_error){ + if (chan->common.usedby != API && chan->common.usedby != TDM_VOICE_DCHAN && data_error) { goto rx_comp_error; } } } len = rx_el->len; + + if (chan->hdlc_eng) { + /* HDLC packets contain 2 byte crc and 1 byte + * flag. If data is not greater than 3, then + * we have a 0 length frame. Thus discard + * (only if HDLC engine enabled) */ + if (len <= 3) { + + /* if we got an invalid hdlc frame and pkt_error is not set. + we must indicate that the packet is bad and update statistics */ + if (!rx_el->pkt_error) { + WAN_NETIF_STATS_INC_RX_ERRORS(&chan->common); //++chan->if_stats.rx_errors; + WP_AFT_CHAN_ERROR_STATS(chan->chan_stats,rx_errors); + wan_set_bit(WP_FRAME_ERROR_BIT,&rx_el->pkt_error); + } + + if (chan->common.usedby != API && chan->common.usedby != TDM_VOICE_DCHAN) { + goto rx_comp_error; + } + + /* Set the length to 1 so its not ZERO we have already flagged it + as bad frame */ + len=1; + + } else { + /* default case is to remove crc values */ + if (card->u.aft.cfg.rx_crc_bytes == 0) { + len-=3; + } else if (card->u.aft.cfg.rx_crc_bytes == 2) { + len-=1; + } else { + /* Leave crc in the frame */ + } + } + } else { + if (len != chan->mru) { + WAN_NETIF_STATS_INC_RX_ERRORS(&chan->common); //++chan->if_stats.rx_errors; + WP_AFT_CHAN_ERROR_STATS(chan->chan_stats,rx_errors); + wan_set_bit(WP_FRAME_ERROR_BIT,&rx_el->pkt_error); + len=chan->mru; + } + } - *pkt_error=(u8)rx_el->pkt_error; /* After a RX FIFO overflow, we must mark max 7 * subsequent frames since firmware, cannot * guarantee the contents of the fifo */ - if (wan_test_bit(WP_FIFO_ERROR_BIT,&rx_el->pkt_error)){ + if (wan_test_bit(WP_FIFO_ERROR_BIT,&rx_el->pkt_error)) { if (chan->hdlc_eng){ if (++chan->rx_fifo_err_cnt >= WP_MAX_FIFO_FRAMES){ chan->rx_fifo_err_cnt=0; @@ -5217,19 +5304,21 @@ static void aft_rx_post_complete (sdla_t *card, private_area_t *chan, }else{ chan->rx_fifo_err_cnt=0; } - wan_set_bit(WP_FIFO_ERROR_BIT,pkt_error); - }else{ - if (chan->rx_fifo_err_cnt){ + wan_set_bit(WP_FIFO_ERROR_BIT,&rx_el->pkt_error); + } else { + if (chan->rx_fifo_err_cnt) { if (++chan->rx_fifo_err_cnt >= WP_MAX_FIFO_FRAMES){ - chan->rx_fifo_err_cnt=0; + chan->rx_fifo_err_cnt=0; } - wan_set_bit(WP_FIFO_ERROR_BIT,pkt_error); + wan_set_bit(WP_FIFO_ERROR_BIT,&rx_el->pkt_error); } } + + *pkt_error=(u8)rx_el->pkt_error; #if !defined(__WINDOWS__) /* Note for Windows: this will always be true */ - if (len > aft_rx_copyback){ + if (len > aft_rx_copyback) { /* The rx size is big enough, thus * send this buffer up the stack * and allocate another one */ @@ -5242,7 +5331,7 @@ static void aft_rx_post_complete (sdla_t *card, private_area_t *chan, *new_skb=skb; aft_alloc_rx_dma_buff(card,chan,1,1); - }else{ + } else { #endif /* The rx packet is very @@ -5398,14 +5487,6 @@ static void wp_bh_rx(private_area_t* chan, netskb_t *new_skb, u8 pkt_error, int { sdla_t *card = chan->card; - if (chan->hdlc_eng){ - if (card->u.aft.cfg.rx_crc_bytes == 3){ - wan_skb_put(new_skb,3); - }else if (card->u.aft.cfg.rx_crc_bytes == 2){ - wan_skb_put(new_skb,2); - } - } - if(chan->common.usedby == WANPIPE || chan->common.usedby == STACK){ if (wanpipe_lip_rx(chan, new_skb) != 0){ @@ -5450,6 +5531,8 @@ static void wp_bh_rx(private_area_t* chan, netskb_t *new_skb, u8 pkt_error, int rx_hdr->rx_h.crc=pkt_error; rx_hdr->rx_h.current_number_of_frames_in_rx_queue = (u8)wan_skb_queue_len(&chan->wp_rx_complete_list); rx_hdr->rx_h.max_rx_queue_length = (u8)chan->dma_per_ch; + rx_hdr->rx_h.errors = WP_AFT_RX_ERROR_SUM(chan->chan_stats); + err=wanpipe_tdm_api_span_rx(chan->wp_tdm_api_dev, new_skb); if (err) { @@ -5508,7 +5591,8 @@ static void wp_bh_rx(private_area_t* chan, netskb_t *new_skb, u8 pkt_error, int rx_hdr->rx_h.crc=pkt_error; rx_hdr->rx_h.current_number_of_frames_in_rx_queue = wan_skb_queue_len(&chan->wp_rx_complete_list); rx_hdr->rx_h.max_rx_queue_length = chan->dma_per_ch; - + rx_hdr->rx_h.errors = WP_AFT_RX_ERROR_SUM(chan->chan_stats); + err=wanpipe_tdm_api_span_rx(chan->wp_tdm_api_dev, new_skb); if (err) { WAN_NETIF_STATS_INC_RX_DROPPED(&chan->common); /* ++chan->if_stats.rx_dropped; */ @@ -5520,14 +5604,6 @@ static void wp_bh_rx(private_area_t* chan, netskb_t *new_skb, u8 pkt_error, int } else { - - if (chan->hdlc_eng){ - if (card->u.aft.cfg.rx_crc_bytes == 3){ - wan_skb_put(new_skb,3); - }else if (card->u.aft.cfg.rx_crc_bytes == 2){ - wan_skb_put(new_skb,2); - } - } if (chan->common.sk == NULL){ DEBUG_TEST("%s: No sock bound to channel rx dropping!\n", @@ -5623,7 +5699,8 @@ static void wp_bh_rx(private_area_t* chan, netskb_t *new_skb, u8 pkt_error, int }else #endif - if (chan->tdmv_zaptel_cfg){ + /* Zaptel does not care about errored packets */ + if (chan->tdmv_zaptel_cfg && !pkt_error){ #if defined(CONFIG_PRODUCT_WANPIPE_TDM_VOICE_DCHAN) && defined(CONFIG_PRODUCT_WANPIPE_TDM_VOICE) int err; @@ -5646,16 +5723,13 @@ static void wp_bh_rx(private_area_t* chan, netskb_t *new_skb, u8 pkt_error, int * function returns void */ } else { - if (WAN_NET_RATELIMIT()){ - DEBUG_ERROR("%s: DCHAN Rx Packet critical error op not supported\n",card->devname); - } WAN_NETIF_STATS_INC_RX_DROPPED(&chan->common); /* ++chan->if_stats.rx_dropped; */ WP_AFT_CHAN_ERROR_STATS(chan->chan_stats,rx_dropped); wan_skb_free(new_skb); return; } - }else if (chan->common.usedby == TDM_VOICE){ + }else if (chan->common.usedby == TDM_VOICE) { if (WAN_NET_RATELIMIT()){ DEBUG_EVENT("%s: TDM VOICE CRITICAL: IN BH!!!!\n",card->devname); @@ -5665,7 +5739,7 @@ static void wp_bh_rx(private_area_t* chan, netskb_t *new_skb, u8 pkt_error, int wan_skb_free(new_skb); return; - }else if (chan->common.usedby == STACK){ + }else if (chan->common.usedby == STACK) { wan_skb_set_csum(new_skb,0); @@ -5677,8 +5751,9 @@ static void wp_bh_rx(private_area_t* chan, netskb_t *new_skb, u8 pkt_error, int } #if defined(AFT_XMTP2_API_SUPPORT) - }else if (chan->common.usedby == XMTP2_API){ + }else if (chan->common.usedby == XMTP2_API) { netskb_t *tskb; + wan_smp_flag_t smp_flags; wan_skb_set_csum(new_skb,0); @@ -5710,7 +5785,10 @@ static void wp_bh_rx(private_area_t* chan, netskb_t *new_skb, u8 pkt_error, int wan_skb_queue_tail(&chan->wp_tx_pending_list,tskb); + + wan_spin_lock_irq(&card->wandev.lock, &smp_flags); aft_dma_tx(card,chan); + wan_spin_unlock_irq(&card->wandev.lock, &smp_flags); #endif @@ -5887,23 +5965,6 @@ static void wp_bh (void *data, int pending) len=wan_skb_len(new_skb); - if (chan->hdlc_eng){ - /* HDLC packets contain 2 byte crc and 1 byte - * flag. If data is not greater than 3, then - * we have a 0 length frame. Thus discard - * (only if HDLC engine enabled) */ - if (len <= 3){ - WAN_NETIF_STATS_INC_RX_ERRORS(&chan->common); //++chan->if_stats.rx_errors; - WP_AFT_CHAN_ERROR_STATS(chan->chan_stats,rx_errors); - wan_skb_free(new_skb); - continue; - } - - wan_skb_trim(new_skb,wan_skb_len(new_skb)-3); - len-=3; - } - - if (top_chan) { wan_capture_trace_packet(chan->card, &top_chan->trace_info, new_skb,TRC_INCOMING_FRM); @@ -6416,8 +6477,9 @@ static void front_end_interrupt(sdla_t *card, unsigned long reg, int lock) if (tmp_card->wandev.fe_iface.isr && tmp_card->wandev.fe_iface.isr(&tmp_card->fe)) { - - handle_front_end_state(tmp_card,lock); + if (!wan_test_bit(CARD_PORT_TASK_DOWN,&tmp_card->wandev.critical)){ + handle_front_end_state(tmp_card,lock); + } } } } @@ -6513,26 +6575,32 @@ static WAN_IRQ_RETVAL wp_aft_global_isr (sdla_t* card) fe_intr=1; #if defined (__LINUX__) || defined(__FreeBSD__) || defined(__WINDOWS__) - if (!wan_test_bit(CARD_PORT_TASK_DOWN,&card->wandev.critical)){ - /* Only execute front end interrupt on very first card - In the list. This way we do not get into a race condition - between port task on wanpipe1 versus trigger from wanpipe2. - Since Front end interrupt is global interrupt per card */ - if (aft_is_first_card_in_list(card, AFT_CARD_TYPE_ALL, 1) == 0) { - + /* Only execute front end interrupt on very first card + In the list. This way we do not get into a race condition + between port task on wanpipe1 versus trigger from wanpipe2. + Since Front end interrupt is global interrupt per card */ + if (aft_is_first_card_in_list(card, AFT_CARD_TYPE_ALL, 1) == 0) { + + if (!wan_test_bit(CARD_PORT_TASK_DOWN,&card->wandev.critical)){ wan_set_bit(AFT_FE_INTR,&card->u.aft.port_task_cmd); WAN_TASKQ_SCHEDULE((&card->u.aft.port_task)); - - __aft_fe_intr_ctrl(card,AFT_CARD_TYPE_ALL); - card->front_end_irq_timeout=SYSTEM_TICKS; - - /* NC: Bug fix we must update the reg value */ - __sdla_bus_read_4(card->hw,AFT_PORT_REG(card,AFT_CHIP_CFG_REG), ®); - - DEBUG_TEST("%s: Launching Front End Interrupt\n", - card->devname); + } else { + DEBUG_FE("%s: Error: First card down not launching fe\n", + card->devname); } + + __aft_fe_intr_ctrl(card,0); + card->front_end_irq_timeout=SYSTEM_TICKS; + + /* NC: Bug fix we must update the reg value */ + __sdla_bus_read_4(card->hw,AFT_PORT_REG(card,AFT_CHIP_CFG_REG), ®); + + DEBUG_FE("%s: Launching Front End Interrupt\n", card->devname); + } else { + + DEBUG_FE("%s: Card not first in the list\n",card->devname); } + #else #error "Undefined OS- Front End Interrupt not allowed in IRQ!" #if 0 @@ -6544,8 +6612,11 @@ static WAN_IRQ_RETVAL wp_aft_global_isr (sdla_t* card) #endif } else if (aft_is_first_card_in_list(card,AFT_CARD_TYPE_ALL, 1) == 0 && !card->fe_no_intr) { - DEBUG_TEST("%s: Got Front end interrupt but MASK is not set!\n",card->devname); - check_fe_isr=1; + DEBUG_FE("%s: Got Front end interrupt on First Card but MASK is not set!\n",card->devname); + __aft_fe_intr_ctrl(card,1); + + } else { + DEBUG_FE("%s: Got Front end interrupt but MASK is not set!\n",card->devname); } } else if (!card->fe_no_intr) { /* if (wan_test_bit(AFT_CHIPCFG_FE_INTR_STAT_BIT,®)) */ check_fe_isr=1; @@ -6599,7 +6670,7 @@ static WAN_IRQ_RETVAL wp_aft_global_isr (sdla_t* card) } if (wan_test_bit(AFT_TDM_FREE_RUN_ISR,&card->u.aft.chip_cfg_status)) { - u32 free_reg; + u32 free_reg=0; /* Free run register is GLOBAL for all ports on a card therefore do not use MACRO to offset by port number */ __sdla_bus_read_4(card->hw,AFT_FREE_RUN_TIMER_CTRL_REG, &free_reg); @@ -7029,7 +7100,7 @@ if (1){ card->u.aft.sec_chk_cnt=SYSTEM_TICKS; if (card->u.aft.firm_id == AFT_DS_FE_CORE_ID) { - u32 lcfg_reg; + u32 lcfg_reg=0; __sdla_bus_read_4(card->hw,AFT_PORT_REG(card,AFT_LINE_CFG_REG), &lcfg_reg); card->u.aft.lcfg_reg=lcfg_reg; @@ -7048,7 +7119,8 @@ if (1){ card->u.aft.chip_security_cnt=0; if (wan_test_bit(AFT_TDM_FE_SYNC_CNT,&card->u.aft.chip_cfg_status) && - !aft_fe_loop_back_status(card)) { + !aft_fe_loop_back_status(card) && + card->wandev.state == WAN_CONNECTED) { u32 sync_cnt = aft_lcfg_get_fe_sync_cnt(lcfg_reg); if (sync_cnt) { DEBUG_ERROR("%s: Warning: Front End Lost Synchronization (sync_cnt=%i)\n", @@ -7773,6 +7845,12 @@ static void handle_front_end_state(void *card_id,int lock) return; } + if (wan_test_bit(CARD_PORT_TASK_DOWN,&card->wandev.critical)){ + DEBUG_EVENT("%s: Skipping Front Front End State CARD_PORT_TASK_DOWN\n", + card->devname); + return; + } + if (card->fe.fe_status == FE_CONNECTED || card->wandev.ignore_front_end_status == WANOPT_YES){ if (card->wandev.state != WAN_CONNECTED){ @@ -9274,6 +9352,7 @@ int aft_dma_tx (sdla_t *card,private_area_t *chan) } if (chan->tx_chain_indx >= MAX_AFT_DMA_CHAINS){ + wan_clear_bit(TX_DMA_BUSY,&chan->dma_status); DEBUG_ERROR("%s: MAJOR ERROR: TE1 Tx: Dma tx chain = %d\n", chan->if_name,chan->tx_chain_indx); return -EBUSY; @@ -9701,7 +9780,7 @@ aft_dma_single_chain_rx_exit: } -static int aft_dma_rx(sdla_t *card, private_area_t *chan) +static int aft_dma_rx (sdla_t *card, private_area_t *chan) { int err=0, intr=0; wan_dma_descr_t *dma_chain; @@ -10418,6 +10497,8 @@ static void aft_port_task (IN PKDPC Dpc, IN PVOID card_ptr, IN PVOID SystemArgum #endif + + #if defined(__LINUX__) # if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) static void aft_port_task (void * card_ptr) @@ -10443,34 +10524,38 @@ static void aft_port_task (void * card_ptr, int arg) wan_smp_flag_t smp_flags; wan_smp_flag_t smp_irq_flags; + DEBUG_TEST("%s: PORT TASK \n",card->devname); + wan_set_bit(CARD_PORT_TASK_RUNNING,&card->wandev.critical); AFT_PERF_STAT_INC(card,port_task,all); if (wan_test_bit(CARD_PORT_TASK_DOWN,&card->wandev.critical)){ wan_clear_bit(CARD_PORT_TASK_RUNNING,&card->wandev.critical); + DEBUG_ERROR("%s: Warning: CARD_PORT_TASK_DOWN set on port task\n",card->devname); return; } if (wan_test_bit(AFT_CRITICAL_DOWN, &card->u.aft.port_task_cmd)) { aft_critical_shutdown(card); wan_clear_bit(CARD_PORT_TASK_RUNNING,&card->wandev.critical); + DEBUG_ERROR("%s: AFT_CRITICAL_DOWN set on port task\n",card->devname); return; } if (wan_test_bit(CARD_DOWN,&card->wandev.critical)){ wan_clear_bit(CARD_PORT_TASK_RUNNING,&card->wandev.critical); + DEBUG_ERROR("%s: Warning: CARD_DOWN set on port task\n",card->devname); return; } - DEBUG_TEST("%s: PORT TASK: 0x%X\n", card->devname,card->u.aft.port_task_cmd); #ifdef AFT_IRQ_STAT_DEBUG card->wandev.stats.rx_missed_errors++; #endif - if (wan_test_bit(AFT_FE_INTR,&card->u.aft.port_task_cmd)){ + if (wan_test_and_clear_bit(AFT_FE_INTR,&card->u.aft.port_task_cmd)){ DEBUG_TEST("%s: PORT TASK: FE INTER\n", card->devname); @@ -10479,18 +10564,12 @@ static void aft_port_task (void * card_ptr, int arg) card->hw_iface.hw_lock(card->hw,&smp_flags); aft_fe_intr_ctrl(card, 0); front_end_interrupt(card,0,1); - - - wan_spin_lock_irq(&card->wandev.lock,&smp_irq_flags); - wan_clear_bit(AFT_FE_INTR,&card->u.aft.port_task_cmd); - __aft_fe_intr_ctrl(card, 1); - wan_spin_unlock_irq(&card->wandev.lock,&smp_irq_flags); - - card->hw_iface.hw_unlock(card->hw,&smp_flags); + aft_fe_intr_ctrl(card, 1); + card->hw_iface.hw_unlock(card->hw,&smp_flags); } - if (wan_test_bit(AFT_FE_POLL,&card->u.aft.port_task_cmd)){ + if (wan_test_and_clear_bit(AFT_FE_POLL,&card->u.aft.port_task_cmd)){ DEBUG_TEST("%s: PORT TASK: FE POLL\n", card->devname); @@ -10504,16 +10583,14 @@ static void aft_port_task (void * card_ptr, int arg) handle_front_end_state(card,1); - wan_spin_lock_irq(&card->wandev.lock,&smp_irq_flags); - wan_clear_bit(AFT_FE_POLL,&card->u.aft.port_task_cmd); - wan_spin_unlock_irq(&card->wandev.lock,&smp_irq_flags); - card->hw_iface.hw_unlock(card->hw,&smp_flags); } - if (wan_test_bit(AFT_FE_LED,&card->u.aft.port_task_cmd)){ + if (wan_test_and_clear_bit(AFT_FE_LED,&card->u.aft.port_task_cmd)){ + AFT_PERF_STAT_INC(card,port_task,led); DEBUG_TEST("%s: PORT TASK: FE LED\n", card->devname); + card->hw_iface.hw_lock(card->hw,&smp_flags); if (card->wandev.state == WAN_CONNECTED){ aft_hwdev[card->wandev.card_type].aft_led_ctrl(card, WAN_AFT_RED, 0,WAN_AFT_OFF); @@ -10523,22 +10600,18 @@ static void aft_port_task (void * card_ptr, int arg) aft_hwdev[card->wandev.card_type].aft_led_ctrl(card, WAN_AFT_GREEN, 0, WAN_AFT_OFF); } - wan_spin_lock_irq(&card->wandev.lock,&smp_irq_flags); - wan_clear_bit(AFT_FE_LED,&card->u.aft.port_task_cmd); - wan_spin_unlock_irq(&card->wandev.lock,&smp_irq_flags); - card->hw_iface.hw_unlock(card->hw,&smp_flags); } - if (wan_test_bit(AFT_FE_TDM_RBS,&card->u.aft.port_task_cmd)){ - int err; - DEBUG_TEST("%s: PORT TASK: FE RBS\n", card->devname); - card->hw_iface.hw_lock(card->hw,&smp_flags); - err=0; + if (wan_test_and_clear_bit(AFT_FE_TDM_RBS,&card->u.aft.port_task_cmd)) { + int err=0; AFT_PERF_STAT_INC(card,port_task,rbs); + DEBUG_TEST("%s: PORT TASK: FE RBS\n", card->devname); + card->hw_iface.hw_lock(card->hw,&smp_flags); + #ifdef CONFIG_PRODUCT_WANPIPE_TDM_VOICE if (card->wan_tdmv.sc) { WAN_TDMV_CALL(rbsbits_poll, (&card->wan_tdmv, card), err); @@ -10551,18 +10624,15 @@ static void aft_port_task (void * card_ptr, int arg) } #endif - wan_spin_lock_irq(&card->wandev.lock,&smp_irq_flags); - wan_clear_bit(AFT_FE_TDM_RBS,&card->u.aft.port_task_cmd); - wan_spin_unlock_irq(&card->wandev.lock,&smp_irq_flags); - card->hw_iface.hw_unlock(card->hw,&smp_flags); } -#if defined(CONFIG_WANPIPE_HWEC) - if (wan_test_bit(AFT_FE_EC_POLL,&card->u.aft.port_task_cmd)){ + + if (wan_test_and_clear_bit(AFT_FE_EC_POLL,&card->u.aft.port_task_cmd)){ AFT_PERF_STAT_INC(card,port_task,ec); +#if defined(CONFIG_WANPIPE_HWEC) DEBUG_TEST("%s: PORT TASK: FE EC INTR\n", card->devname); if (card->wandev.ec_dev){ int pending = 0; @@ -10572,17 +10642,14 @@ static void aft_port_task (void * card_ptr, int arg) ** If EC poll return 1 (pending), re-schedule port_task again ** (more dtmf events are available) */ if (pending == 1){ + wan_set_bit(AFT_FE_EC_POLL,&card->u.aft.port_task_cmd); WAN_TASKQ_SCHEDULE((&card->u.aft.port_task)); - }else{ - wan_spin_lock_irq(&card->wandev.lock,&smp_irq_flags); - wan_clear_bit(AFT_FE_EC_POLL,&card->u.aft.port_task_cmd); - wan_spin_unlock_irq(&card->wandev.lock,&smp_irq_flags); } } - } #endif + } - if (wan_test_bit(AFT_FE_RESTART,&card->u.aft.port_task_cmd)){ + if (wan_test_and_clear_bit(AFT_FE_RESTART,&card->u.aft.port_task_cmd)){ AFT_PERF_STAT_INC(card,port_task,restart); @@ -10601,7 +10668,6 @@ static void aft_port_task (void * card_ptr, int arg) wan_spin_lock_irq(&card->wandev.lock,&smp_irq_flags); wan_clear_bit(0,&card->u.aft.comm_enabled); enable_data_error_intr(card); - wan_clear_bit(AFT_FE_RESTART,&card->u.aft.port_task_cmd); wan_spin_unlock_irq(&card->wandev.lock,&smp_irq_flags); card->hw_iface.hw_unlock(card->hw,&smp_flags); @@ -10615,40 +10681,34 @@ static void aft_port_task (void * card_ptr, int arg) /* Purposely leave comm_enabled flag set so that enable_data_error_intr will restart comms */ enable_data_error_intr(card); - wan_clear_bit(AFT_FE_RESTART,&card->u.aft.port_task_cmd); wan_spin_unlock_irq(&card->wandev.lock,&smp_irq_flags); card->hw_iface.hw_unlock(card->hw,&smp_flags); - } } -#if defined(AFT_RTP_SUPPORT) - if (wan_test_bit(AFT_RTP_TAP_Q,&card->u.aft.port_task_cmd)){ + if (wan_test_and_clear_bit(AFT_RTP_TAP_Q,&card->u.aft.port_task_cmd)){ netskb_t *skb; AFT_PERF_STAT_INC(card,port_task,tap_q); - wan_spin_lock_irq(&card->wandev.lock,&smp_irq_flags); - wan_clear_bit(AFT_RTP_TAP_Q,&card->u.aft.port_task_cmd); - wan_spin_unlock_irq(&card->wandev.lock,&smp_irq_flags); + +#if defined(AFT_RTP_SUPPORT) while ((skb=wan_skb_dequeue(&card->u.aft.rtp_tap_list))) { dev_queue_xmit(skb); } - } #endif + } - if (wan_test_bit(AFT_SERIAL_STATUS,&card->u.aft.port_task_cmd)){ + if (wan_test_and_clear_bit(AFT_SERIAL_STATUS,&card->u.aft.port_task_cmd)){ AFT_PERF_STAT_INC(card,port_task,serial_status); - wan_spin_lock_irq(&card->wandev.lock,&smp_irq_flags); - wan_clear_bit(AFT_SERIAL_STATUS,&card->u.aft.port_task_cmd); - wan_spin_unlock_irq(&card->wandev.lock,&smp_irq_flags); aft_core_send_serial_oob_msg(card); } wan_clear_bit(CARD_PORT_TASK_RUNNING,&card->wandev.critical); - if (wan_test_bit(CARD_DOWN,&card->wandev.critical)){ - return; + if (wan_test_bit(CARD_PORT_TASK_DOWN,&card->wandev.critical) || + wan_test_bit(CARD_DOWN,&card->wandev.critical)){ + return; } /* If there are more commands pending requeue the task */ @@ -10658,6 +10718,7 @@ static void aft_port_task (void * card_ptr, int arg) return; } + #ifdef AFT_FE_INTR_DEBUG void ___aft_fe_intr_ctrl(sdla_t *card, int status, char *func, int line) @@ -10666,7 +10727,6 @@ void __aft_fe_intr_ctrl(sdla_t *card, int status) #endif { u32 reg; - int retry=5; /* if fe_no_intr is set then only allow disabling of fe interrupt */ #ifdef AFT_FE_INTR_DEBUG @@ -10674,7 +10734,7 @@ void __aft_fe_intr_ctrl(sdla_t *card, int status) func,line,card->devname,status); #endif - if (!card->fe_no_intr || !status){ + if (!card->fe_no_intr || !status) { card->hw_iface.bus_read_4(card->hw,AFT_PORT_REG(card, AFT_CHIP_CFG_REG),®); if (status){ wan_set_bit(AFT_CHIPCFG_FE_INTR_CFG_BIT,®); @@ -10686,18 +10746,17 @@ void __aft_fe_intr_ctrl(sdla_t *card, int status) wan_clear_bit(AFT_CHIPCFG_FE_INTR_CFG_BIT,®); } - do { - card->hw_iface.bus_write_4(card->hw,AFT_PORT_REG(card, AFT_CHIP_CFG_REG),reg); + card->hw_iface.bus_write_4(card->hw,AFT_PORT_REG(card, AFT_CHIP_CFG_REG),reg); - if (status) { - u32 treg; - card->hw_iface.bus_read_4(card->hw,AFT_PORT_REG(card, AFT_CHIP_CFG_REG),&treg); - if (wan_test_bit(AFT_CHIPCFG_FE_INTR_CFG_BIT,&treg)) { - break; - } - DEBUG_WARNING("%s: Warning failed to enable front end ... retry %i!\n",card->devname,retry); + if (status) { + u32 treg; + card->hw_iface.bus_read_4(card->hw,AFT_PORT_REG(card, AFT_CHIP_CFG_REG),&treg); + if (!wan_test_bit(AFT_CHIPCFG_FE_INTR_CFG_BIT,&treg)) { + DEBUG_ERROR("%s: Critical Error failed to enable front end interrupt!\n", + card->devname); } - }while(--retry); + + } } } @@ -10736,26 +10795,7 @@ static void aft_data_mux_get_cfg(sdla_t *card) } -static int aft_hdlc_repeat_mangle(sdla_t *card,private_area_t *chan, netskb_t *skb, netskb_t **rskb) -{ - unsigned char *buf; - wp_api_hdr_t *tx_hdr = (wp_api_hdr_t *)wan_skb_data(skb); - if (tx_hdr->wp_api_tx_hdr_hdlc_rpt_len == 0 || tx_hdr->wp_api_tx_hdr_hdlc_rpt_len > 8) { - return -1; - } - - *rskb=wan_skb_alloc(128); - if (!rskb) { - return -1; - } - - buf=wan_skb_put(*rskb,tx_hdr->wp_api_tx_hdr_hdlc_rpt_len); - memcpy(buf,tx_hdr->wp_api_tx_hdr_hdlc_rpt_data,tx_hdr->wp_api_tx_hdr_hdlc_rpt_len); - wan_skb_pull(skb,sizeof(wp_api_hdr_t)); - - return 0; -} static int aft_ss7_tx_mangle(sdla_t *card,private_area_t *chan, netskb_t *skb) { @@ -11602,10 +11642,6 @@ static void aft_critical_shutdown (sdla_t *card) DEBUG_ERROR("%s: Error: Card Critically Shutdown!\n", card->devname); - if (card->wandev.fe_iface.pre_release){ - card->wandev.fe_iface.pre_release(&card->fe); - } - card->hw_iface.hw_lock(card->hw,&smp_flags1); wan_spin_lock_irq(&card->wandev.lock, &smp_flags); @@ -11632,10 +11668,6 @@ static void aft_critical_shutdown (sdla_t *card) if (tmp_card && !wan_test_bit(CARD_DOWN,&tmp_card->wandev.critical)) { - if (tmp_card->wandev.fe_iface.pre_release){ - tmp_card->wandev.fe_iface.pre_release(&tmp_card->fe); - } - if (tmp_card->wandev.fe_iface.disable_irq){ tmp_card->wandev.fe_iface.disable_irq(&tmp_card->fe); } diff --git a/patches/kdrivers/src/net/aft_core_api_events.c b/patches/kdrivers/src/net/aft_core_api_events.c index 89257ab..f72e354 100644 --- a/patches/kdrivers/src/net/aft_core_api_events.c +++ b/patches/kdrivers/src/net/aft_core_api_events.c @@ -42,7 +42,7 @@ static void wan_aft_api_ringdetect (void* card_id, wan_event_t *event); static int aft_read_rbs_bits(void *chan_ptr, u32 ch, u8 *rbs_bits); static int aft_write_rbs_bits(void *chan_ptr, u32 ch, u8 rbs_bits); static int aft_write_hdlc_frame(void *chan_ptr, netskb_t *skb, wp_api_hdr_t *hdr); -static int aft_write_hdlc_check(void *chan_ptr, int lock); +static int aft_write_hdlc_check(void *chan_ptr, int lock, int buffers); static int aft_write_hdlc_timeout(void *chan_ptr, int lock); /*-------------------------------------------------------- @@ -423,22 +423,44 @@ static void wan_aft_api_ringdetect (void* card_id, wan_event_t *event) return; } -static int aft_write_hdlc_check(void *chan_ptr, int lock) +static int aft_write_hdlc_check(void *chan_ptr, int lock, int buffers) { private_area_t *chan = (private_area_t *)chan_ptr; sdla_t *card=chan->card; - wan_smp_flag_t smp_flags; - int rc; - - if (IS_BRI_CARD(card) && (chan->dchan_time_slot >= 0)){ - /* For BRI rely on upper layer checking */ + wan_smp_flag_t smp_flags=0; + int rc=0; + + + /* If we are disconnected do now allow tx */ + if (chan->common.state != WAN_CONNECTED) { return 1; } + if (IS_BRI_CARD(card) && (chan->dchan_time_slot >= 0)){ + + rc=aft_bri_dchan_transmit(card, chan, + NULL, + 0); + + if (rc) { + /* Tx busy */ + return 1; + } + + return 0; + } + + if (lock) { wan_spin_lock_irq(&card->wandev.lock, &smp_flags); } + rc = wan_chan_dev_stopped(chan); + if (!rc && buffers > 1) { + if (chan->max_tx_bufs - wan_skb_queue_len(&chan->wp_tx_pending_list) <= buffers) { + rc=1; + } + } if (lock) { wan_spin_unlock_irq(&card->wandev.lock, &smp_flags); @@ -477,6 +499,7 @@ static int aft_write_hdlc_frame(void *chan_ptr, netskb_t *skb, wp_api_hdr_t *hd wan_smp_flag_t smp_flags; int err=-EINVAL; private_area_t *top_chan; + netskb_t *rskb=NULL; if (!chan_ptr || !chan->common.dev || !card){ WAN_ASSERT(1); @@ -484,6 +507,10 @@ static int aft_write_hdlc_frame(void *chan_ptr, netskb_t *skb, wp_api_hdr_t *hd } if (wan_skb_len(skb) > chan->mtu) { + if (WAN_NET_RATELIMIT()) { + DEBUG_ERROR("%s: %s Error: skb len %i > mtu = %i \n", + chan->if_name,__FUNCTION__,wan_skb_len(skb),chan->mtu); + } return -EINVAL; } #if defined(__WINDOWS__) @@ -496,6 +523,12 @@ static int aft_write_hdlc_frame(void *chan_ptr, netskb_t *skb, wp_api_hdr_t *hd } #endif + if (chan->common.state != WAN_CONNECTED){ + DEBUG_TEST("%s: %s Error Device disconnected!\n", + chan->if_name,__FUNCTION__); + return -EBUSY; + } + #if defined(CONFIG_PRODUCT_WANPIPE_AFT_BRI) if(IS_BRI_CARD(card) && (chan->dchan_time_slot >= 0)){ /* BRI D-chan data NOT transmitted using DMA. */ @@ -540,6 +573,13 @@ static int aft_write_hdlc_frame(void *chan_ptr, netskb_t *skb, wp_api_hdr_t *hd } #endif + if (chan->hdlc_eng && chan->cfg.hdlc_repeat) { + err=aft_hdlc_repeat_mangle(card,chan,skb,hdr,&rskb); + if (err) { + return err; + } + } + wan_spin_lock_irq(&card->wandev.lock, &smp_flags); if (wan_skb_queue_len(&chan->wp_tx_pending_list) >= chan->max_tx_bufs){ @@ -561,12 +601,18 @@ static int aft_write_hdlc_frame(void *chan_ptr, netskb_t *skb, wp_api_hdr_t *hd wan_skb_unlink(skb); wan_skb_queue_tail(&chan->wp_tx_pending_list,skb); + + if (rskb) { + wan_skb_queue_tail(&chan->wp_tx_hdlc_rpt_list,rskb); + } + aft_dma_tx(card,chan); hdr->tx_h.max_tx_queue_length = (u8)chan->max_tx_bufs; hdr->tx_h.current_number_of_frames_in_tx_queue = (u8)wan_skb_queue_len(&chan->wp_tx_pending_list); hdr->tx_h.tx_idle_packets = chan->chan_stats.tx_idle_packets; - + hdr->tx_h.errors = WP_AFT_TX_ERROR_SUM(chan->chan_stats); + if (chan->dma_chain_opmode != WAN_AFT_DMA_CHAIN_SINGLE) { hdr->tx_h.max_tx_queue_length += MAX_AFT_DMA_CHAINS; hdr->tx_h.current_number_of_frames_in_tx_queue += chan->tx_chain_data_sz; diff --git a/patches/kdrivers/src/net/aft_core_utils.c b/patches/kdrivers/src/net/aft_core_utils.c index 26dccf1..926510b 100644 --- a/patches/kdrivers/src/net/aft_core_utils.c +++ b/patches/kdrivers/src/net/aft_core_utils.c @@ -871,14 +871,14 @@ int if_change_mtu(netdevice_t *dev, int new_mtu) return -EINVAL; } - if (new_mtu < 16) { + if (new_mtu < sizeof(wp_api_hdr_t)) { return -EINVAL; } if (chan->common.usedby == API){ new_mtu+=sizeof(wp_api_hdr_t); }else if (chan->common.usedby == STACK){ - new_mtu+=32; + new_mtu+=sizeof(wp_api_hdr_t); } if (new_mtu > chan->dma_mru) { @@ -2319,7 +2319,7 @@ void wanpipe_wake_stack(private_area_t* chan) if (chan->common.usedby == API){ if (chan->wp_api_op_mode){ #ifdef AFT_TDM_API_SUPPORT - if (is_tdm_api(chan,chan->wp_tdm_api_dev)){ + if (is_tdm_api(chan,chan->wp_tdm_api_dev)) { wanpipe_tdm_api_kick(chan->wp_tdm_api_dev); } #endif @@ -3416,4 +3416,32 @@ void wp_bert_print_state(wp_bert_t *bert) } +int aft_hdlc_repeat_mangle(sdla_t *card,private_area_t *chan, netskb_t *skb, wp_api_hdr_t *tx_hdr, netskb_t **rskb) +{ + unsigned char *buf; + + if (tx_hdr->wp_api_tx_hdr_hdlc_rpt_len == 0) { + /* Nothing to repeat */ + return 0; + } + + if (tx_hdr->wp_api_tx_hdr_hdlc_rpt_len > 8) { + DEBUG_ERROR("%s: hdlc repeat error rpt_len=%i (max=8)\n", + chan->if_name,tx_hdr->wp_api_tx_hdr_hdlc_rpt_len); + return -1; + } + + *rskb=wan_skb_alloc(128); + if (!rskb) { + DEBUG_ERROR("%s: %s() failed to allocate mem\n", + chan->if_name, __FUNCTION__); + return -ENOMEM; + } + + buf=wan_skb_put(*rskb,tx_hdr->wp_api_tx_hdr_hdlc_rpt_len); + memcpy(buf,tx_hdr->wp_api_tx_hdr_hdlc_rpt_data,tx_hdr->wp_api_tx_hdr_hdlc_rpt_len); + + return 0; +} + /************** EOF *************/ diff --git a/patches/kdrivers/src/net/sdla_8te1.c b/patches/kdrivers/src/net/sdla_8te1.c index ec3218e..01aa3ac 100644 --- a/patches/kdrivers/src/net/sdla_8te1.c +++ b/patches/kdrivers/src/net/sdla_8te1.c @@ -226,7 +226,7 @@ static int sdla_ds_te1_config(void* pfe); /* Change to static */ static int sdla_ds_te1_reconfig(sdla_fe_t* fe); static int sdla_ds_te1_post_init(void *pfe); static int sdla_ds_te1_unconfig(void* pfe); /* Change to static */ -static int sdla_ds_te1_pre_release(void* pfe); +static int sdla_ds_te1_post_unconfig(void* pfe); static int sdla_ds_te1_TxChanCtrl(sdla_fe_t* fe, int channel, int enable); static int sdla_ds_te1_RxChanCtrl(sdla_fe_t* fe, int channel, int enable); static int sdla_ds_te1_disable_irq(void* pfe); /* Change to static */ @@ -239,7 +239,8 @@ static int sdla_ds_te1_pmon(sdla_fe_t *fe, int action); static int sdla_ds_te1_rxlevel(sdla_fe_t* fe); static int sdla_ds_te1_polling(sdla_fe_t* fe); static int sdla_ds_te1_update_alarms(sdla_fe_t*, u_int32_t); -static unsigned int sdla_ds_te1_read_alarms(sdla_fe_t *fe, int read); +static u_int32_t sdla_ds_te1_read_alarms(sdla_fe_t *fe, int read); +static u_int32_t sdla_ds_te1_read_tx_alarms(sdla_fe_t *fe, int action); static int sdla_ds_te1_set_alarms(sdla_fe_t* fe, u_int32_t alarms); static int sdla_ds_te1_clear_alarms(sdla_fe_t* fe, u_int32_t alarms); static int sdla_ds_te1_set_status(sdla_fe_t* fe, u_int32_t alarms); @@ -407,27 +408,28 @@ int sdla_ds_te1_iface_init(void *p_fe, void *p_fe_iface) sdla_fe_t *fe = (sdla_fe_t*)p_fe; sdla_fe_iface_t *fe_iface = (sdla_fe_iface_t*)p_fe_iface; - fe_iface->reset = &sdla_ds_te1_reset; + fe_iface->reset = &sdla_ds_te1_reset; fe_iface->global_config = &sdla_ds_te1_global_config; fe_iface->global_unconfig = &sdla_ds_te1_global_unconfig; fe_iface->chip_config = &sdla_ds_te1_chip_config; - fe_iface->config = &sdla_ds_te1_config; - fe_iface->post_init = &sdla_ds_te1_post_init; - fe_iface->reconfig = &sdla_ds_te1_reconfig; - fe_iface->unconfig = &sdla_ds_te1_unconfig; - fe_iface->pre_release = &sdla_ds_te1_pre_release; + fe_iface->config = &sdla_ds_te1_config; + fe_iface->post_init = &sdla_ds_te1_post_init; + fe_iface->reconfig = &sdla_ds_te1_reconfig; + fe_iface->unconfig = &sdla_ds_te1_unconfig; + fe_iface->post_unconfig = &sdla_ds_te1_post_unconfig; fe_iface->disable_irq = &sdla_ds_te1_disable_irq; - fe_iface->isr = &sdla_ds_te1_intr; - fe_iface->check_isr = &sdla_ds_te1_check_intr; - fe_iface->intr_ctrl = &sdla_ds_te1_intr_ctrl; - fe_iface->polling = &sdla_ds_te1_polling; + fe_iface->isr = &sdla_ds_te1_intr; + fe_iface->check_isr = &sdla_ds_te1_check_intr; + fe_iface->intr_ctrl = &sdla_ds_te1_intr_ctrl; + fe_iface->polling = &sdla_ds_te1_polling; fe_iface->process_udp = &sdla_ds_te1_udp; fe_iface->print_fe_alarm = &sdla_ds_te1_print_alarms; /*fe_iface->print_fe_act_channels = &sdla_te_print_channels;*/ fe_iface->read_alarm = &sdla_ds_te1_read_alarms; - /*fe_iface->set_fe_alarm = &sdla_te_set_alarms;*/ - fe_iface->read_pmon = &sdla_ds_te1_pmon; + fe_iface->read_tx_alarm = &sdla_ds_te1_read_tx_alarms; + //fe_iface->set_fe_alarm = &sdla_ds_te1_set_alarms; + fe_iface->read_pmon = &sdla_ds_te1_pmon; fe_iface->flush_pmon = &sdla_ds_te1_flush_pmon; fe_iface->get_fe_status = &sdla_ds_te1_get_fe_status; fe_iface->get_fe_media = &sdla_ds_te1_get_fe_media; @@ -440,12 +442,23 @@ int sdla_ds_te1_iface_init(void *p_fe, void *p_fe_iface) fe_iface->report_rbsbits = &sdla_ds_te1_rbs_report; fe_iface->set_rbsbits = &sdla_ds_te1_set_rbsbits; fe_iface->set_fe_sigctrl = &sdla_ds_te1_sigctrl; + #if 0 fe_iface->led_ctrl = &sdla_te_led_ctrl; #endif /* Initial FE state */ fe->fe_status = FE_UNITIALIZED; //FE_DISCONNECTED; + if (IS_E1_FEMEDIA(fe)) { + if (WAN_FE_FRAME(fe) == WAN_FR_UNFRAMED){ + fe->fe_alarm = WAN_TE1_UNFRAMED_ALARMS; + } else { + fe->fe_alarm = WAN_E1_FRAMED_ALARMS; + } + } else { + fe->fe_alarm = WAN_T1_FRAMED_ALARMS; + } + WAN_LIST_INIT(&fe->event); wan_spin_lock_irq_init(&fe->lockirq, "wan_8te1_lock"); return 0; @@ -1296,12 +1309,31 @@ static int sdla_ds_te1_chip_config(void* pfe) DEBUG_EVENT("%s: Disable TX (tri-state mode)\n", fe->name); }else{ - /* Sep 17, 2009 - Auto AIS transmition (experimental) */ - WRITE_REG(REG_LMCR, BIT_LMCR_ATAIS | BIT_LMCR_TE); + if (IS_E1_FEMEDIA(fe)){ + WRITE_REG(REG_LMCR, BIT_LMCR_TE); + }else{ + /* Sep 17, 2009 - Auto AIS transmition (experimental) */ + WRITE_REG(REG_LMCR, BIT_LMCR_ATAIS | BIT_LMCR_TE); + } + + /* Always configure with AIS alarm enabled */ + sdla_ds_te1_set_alarms(fe,WAN_TE_BIT_ALARM_AIS); + + /* If port started in maintenance mode then do not + remove AIS alarm until done manually */ + if (fe->fe_cfg.cfg.te_cfg.ais_maintenance == WANOPT_YES){ + fe->te_param.tx_ais_startup_timeout=0; + fe->fe_stats.tx_maint_alarms |= WAN_TE_BIT_ALARM_AIS; + } else { + fe->te_param.tx_ais_startup_timeout=SYSTEM_TICKS; + } } /* INIT RBS bits to 1 */ sdla_ds_te1_rbs_init(fe); + + + return 0; } @@ -1484,7 +1516,8 @@ static int sdla_ds_te1_config(void* pfe) memset(fe->swirq, 0, WAN_TE1_SWIRQ_MAX*sizeof(sdla_fe_swirq_t)); wan_set_bit(TE_CONFIGURED,(void*)&fe->te_param.critical); - + + #if 0 /* FIXME: Enable all interrupt only when link is connected (event global) */ /* Enable interrupts */ @@ -1520,20 +1553,23 @@ static int sdla_ds_te1_post_init(void* pfe) WAN_TE1_SWIRQ_TYPE_LINK, WAN_TE1_SWIRQ_SUBTYPE_LINKDOWN, POLLING_TE1_TIMER); - sdla_ds_te1_add_timer(fe, POLLING_TE1_TIMER); + + /* Give the system time to start the rest of the card before + we start polling */ + sdla_ds_te1_add_timer(fe, POLLING_TE1_TIMER*5); return 0; } /* ****************************************************************************** - * sdla_ds_te1_pre_release() + * sdla_ds_te1_post_unconfig() * - * Description: T1/E1 pre release function (not locked routines) + * Description: T1/E1 post_unconfig function (not locked routines) * Arguments: * Returns: ****************************************************************************** */ -static int sdla_ds_te1_pre_release(void* pfe) +static int sdla_ds_te1_post_unconfig(void* pfe) { sdla_fe_t *fe = (sdla_fe_t*)pfe; sdla_fe_timer_event_t *fe_event = NULL; @@ -1580,16 +1616,11 @@ static int sdla_ds_te1_unconfig(void* pfe) { sdla_fe_t *fe = (sdla_fe_t*)pfe; - /* Verify if FE timer is stopped */ - if (!wan_test_bit(TE_TIMER_KILL,(void*)&fe->te_param.critical)){ - DEBUG_EVENT("%s: %s(): Front-End timer is not stopped!\n", - fe->name, __FUNCTION__); - return -EINVAL; - } - DEBUG_EVENT("%s: %s Front End unconfigation!\n", fe->name, FE_MEDIA_DECODE(fe)); - + + sdla_ds_te1_set_alarms(fe,WAN_TE_BIT_ALARM_AIS); + /* FIXME: Alex to disable interrupts here */ sdla_ds_te1_disable_irq(fe); @@ -1599,6 +1630,7 @@ static int sdla_ds_te1_unconfig(void* pfe) WRITE_REG(REG_TMMR, BIT_RMMR_SFTRST); /* Clear configuration flag */ + wan_set_bit(TE_TIMER_KILL,(void*)&fe->te_param.critical); wan_clear_bit(TE_CONFIGURED,(void*)&fe->te_param.critical); //sdla_ds_te1_reset(fe, WAN_FE_LINENO(fe)+1, 1); @@ -1760,6 +1792,18 @@ static int sdla_ds_te1_set_status(sdla_fe_t* fe, u_int32_t alarms) if (fe->fe_status == new_fe_status){ + DEBUG_TE1("%s: NoCH TxYel=%i Valid_rx=0x%08X\n", + fe->name,fe->te_param.tx_yel_alarm,valid_rx_alarms); + + /* We must keep checking for RAI transmission here as well as on state change + otherwise we could fail to tx RAI if the first reason for state change is RAI + and then other other alarms get activated */ + if (!fe->te_param.tx_yel_alarm && (valid_rx_alarms & WAN_TE_BIT_RED_ALARM)){ + sdla_ds_te1_set_alarms(fe, WAN_TE_BIT_ALARM_YEL); + } + + /* Special case where we tx RAI alarm and only incoming alarm is RAI + in this case we should disable our RAI. Usual case is loopback */ if (fe->te_param.tx_yel_alarm && valid_rx_alarms == WAN_TE_BIT_RAI_ALARM){ sdla_ds_te1_clear_alarms(fe, WAN_TE_BIT_YEL_ALARM); } @@ -1772,11 +1816,14 @@ static int sdla_ds_te1_set_status(sdla_fe_t* fe, u_int32_t alarms) fe->te_param.status_cnt); return 0; } + if (new_fe_status == FE_CONNECTED){ if (fe->te_param.status_cnt > WAN_TE1_STATUS_THRESHOLD){ + if (fe->te_param.tx_yel_alarm){ sdla_ds_te1_clear_alarms(fe, WAN_TE_BIT_ALARM_YEL); } + DEBUG_EVENT("%s: %s connected!\n", fe->name, FE_MEDIA_DECODE(fe)); @@ -1803,8 +1850,12 @@ static int sdla_ds_te1_set_status(sdla_fe_t* fe, u_int32_t alarms) FE_MEDIA_DECODE(fe)); fe->fe_status = FE_DISCONNECTED; - /* Special case, if remote alarms is ONLY RAI, then do not transmit yellow */ - if (!fe->te_param.tx_yel_alarm && !(valid_rx_alarms == WAN_TE_BIT_RAI_ALARM)){ + DEBUG_TE1("%s: TxYel=%i Valid_rx=0x%08X\n", + fe->name,fe->te_param.tx_yel_alarm,valid_rx_alarms); + + /* Line went down due to alarm (not just RAI) if yellow alarm was not + transmited then do so now */ + if (!fe->te_param.tx_yel_alarm && (valid_rx_alarms & WAN_TE_BIT_RED_ALARM)){ sdla_ds_te1_set_alarms(fe, WAN_TE_BIT_ALARM_YEL); } @@ -1833,17 +1884,14 @@ static int sdla_ds_te1_set_status(sdla_fe_t* fe, u_int32_t alarms) */ static int sdla_ds_te1_print_alarms(sdla_fe_t* fe, unsigned int alarms) { + uint32_t tx_alarms=0; - if (!alarms){ - DEBUG_EVENT("%s: %s Alarms status: No alarms detected!\n", - fe->name, - FE_MEDIA_DECODE(fe)); - return 0; - } - DEBUG_EVENT("%s: %s Framer Alarms status (%08X):\n", + + DEBUG_EVENT("%s: %s Framer Alarms status: RX (%08X):\n", fe->name, FE_MEDIA_DECODE(fe), alarms & WAN_TE_ALARM_FRAMER_MASK); + if (alarms & WAN_TE_BIT_ALARM_RAI){ DEBUG_EVENT("%s: RAI : ON\n", fe->name); } @@ -1873,6 +1921,27 @@ static int sdla_ds_te1_print_alarms(sdla_fe_t* fe, unsigned int alarms) fe->name); } + if (fe->te_param.tx_yel_alarm) { + tx_alarms |= WAN_TE_BIT_ALARM_YEL; + } + + if (fe->te_param.tx_ais_alarm) { + tx_alarms |= WAN_TE_BIT_ALARM_AIS; + } + + DEBUG_EVENT("%s: %s Framer Alarms status: TX (%08X):\n", + fe->name, + FE_MEDIA_DECODE(fe), + tx_alarms); + + if (fe->te_param.tx_yel_alarm) { + DEBUG_EVENT("%s: YEL : TX\n", fe->name); + } + + if (fe->te_param.tx_ais_alarm) { + DEBUG_EVENT("%s: AIS : TX\n", fe->name); + } + return 0; } @@ -2039,6 +2108,28 @@ static unsigned int sdla_ds_te1_read_liu_alarms(sdla_fe_t *fe) return alarm; } + +static u_int32_t sdla_ds_te1_read_tx_alarms(sdla_fe_t *fe, int action) +{ + u_int32_t alarm=0; + + if (IS_FE_ALARM_READ(action)){ + if (fe->te_param.tx_yel_alarm) { + alarm |= WAN_TE_BIT_ALARM_YEL; + } + + if (fe->te_param.tx_ais_alarm) { + alarm |= WAN_TE_BIT_ALARM_AIS; + } + } + + if (IS_FE_ALARM_PRINT(action)){ + sdla_ds_te1_print_alarms(fe, fe->fe_alarm); + } + + return alarm; +} + static u_int32_t sdla_ds_te1_read_alarms(sdla_fe_t *fe, int action) { u_int32_t alarm = fe->fe_alarm; @@ -2053,7 +2144,8 @@ static u_int32_t sdla_ds_te1_read_alarms(sdla_fe_t *fe, int action) } if (IS_FE_ALARM_UPDATE(action)){ fe->fe_alarm = alarm; - } + } + return fe->fe_alarm; } @@ -2158,27 +2250,43 @@ static int sdla_ds_te1_set_alarms(sdla_fe_t* fe, u_int32_t alarms) { u8 value; + + /* NC: Always set yellow alarm no need to check whether * yellow alarm is ignored */ if (alarms & WAN_TE_BIT_ALARM_YEL){ if (IS_T1_FEMEDIA(fe)){ value = READ_REG(REG_TCR1); if (!(value & BIT_TCR1_T1_TRAI)){ - DEBUG_EVENT("%s: Enable transmit RAI alarm\n", + DEBUG_EVENT("%s: Enable transmit YEL alarm\n", fe->name); WRITE_REG(REG_TCR1, value | BIT_TCR1_T1_TRAI); - fe->te_param.tx_yel_alarm = 1; } + fe->te_param.tx_yel_alarm = 1; + fe->fe_stats.tx_alarms |= WAN_TE_BIT_ALARM_YEL; }else{ value = READ_REG(REG_E1TNAF); if (!(value & BIT_E1TNAF_A)){ - DEBUG_TE1("%s: Enable transmit RAI alarm\n", + DEBUG_EVENT("%s: Enable transmit YEL alarm\n", fe->name); WRITE_REG(REG_E1TNAF, value | BIT_E1TNAF_A); - fe->te_param.tx_yel_alarm = 1; } + fe->te_param.tx_yel_alarm = 1; + fe->fe_stats.tx_alarms |= WAN_TE_BIT_ALARM_YEL; } } + + if (alarms & WAN_TE_BIT_ALARM_AIS) { + value = READ_REG(REG_TCR1); + if (!(value & BIT_TCR1_T1_TAIS)){ + DEBUG_EVENT("%s: Enable transmit AIS alarm\n", + fe->name); + WRITE_REG(REG_TCR1, value | BIT_TCR1_T1_TAIS); + } + fe->te_param.tx_ais_alarm = 1; + fe->fe_stats.tx_alarms |= WAN_TE_BIT_ALARM_AIS; + } + return 0; } @@ -2192,29 +2300,44 @@ static int sdla_ds_te1_set_alarms(sdla_fe_t* fe, u_int32_t alarms) static int sdla_ds_te1_clear_alarms(sdla_fe_t* fe, u_int32_t alarms) { u8 value; + + /* NC: Always set yellow alarm no need to check whether * yellow alarm is ignored */ - if (alarms & WAN_TE_BIT_ALARM_YEL){ + if (alarms & WAN_TE_BIT_ALARM_YEL) { if (IS_T1_FEMEDIA(fe)){ value = READ_REG(REG_TCR1); - if (value & BIT_TCR1_T1_TRAI){ - DEBUG_EVENT("%s: Disable transmit RAI alarm\n", + if (value & BIT_TCR1_T1_TRAI) { + DEBUG_EVENT("%s: Disable transmit YEL alarm\n", fe->name); WRITE_REG(REG_TCR1, value & ~BIT_TCR1_T1_TRAI); - fe->te_param.tx_yel_alarm = 0; } + fe->te_param.tx_yel_alarm = 0; + fe->fe_stats.tx_alarms &= ~WAN_TE_BIT_ALARM_YEL; }else{ value = READ_REG(REG_E1TNAF); - if (value & BIT_E1TNAF_A){ - DEBUG_TE1("%s: Disable transmit RAI alarm\n", + if (value & BIT_E1TNAF_A) { + DEBUG_EVENT("%s: Disable transmit YEL alarm\n", fe->name); WRITE_REG(REG_E1TNAF, value & ~BIT_E1TNAF_A); - fe->te_param.tx_yel_alarm = 0; - } + fe->te_param.tx_yel_alarm = 0; + fe->fe_stats.tx_alarms &= ~WAN_TE_BIT_ALARM_YEL; } } + + if (alarms & WAN_TE_BIT_ALARM_AIS) { + value = READ_REG(REG_TCR1); + if (value & BIT_TCR1_T1_TAIS) { + DEBUG_EVENT("%s: Disable transmit AIS alarm\n", + fe->name); + WRITE_REG(REG_TCR1, value & ~BIT_TCR1_T1_TAIS); + } + fe->te_param.tx_ais_alarm = 1; + fe->fe_stats.tx_alarms &= ~WAN_TE_BIT_ALARM_AIS; + } + return 0; } @@ -3929,12 +4052,134 @@ static int sdla_ds_te1_swirq(sdla_fe_t* fe) ** Returns: 0 - There are no more event. Do not need to schedule sw timer ** number - delay to schedule next event. ******************************************************************************/ +static int sdla_ds_te1_exec_event(sdla_fe_t* fe, sdla_fe_timer_event_t *event, uint8_t *pending) +{ + int err=0; + + *pending = 0; + + + switch(event->type){ + case TE_RBS_READ: + /* Physically read RBS status and print */ + err=sdla_ds_te1_rbs_print(fe, 0); + break; + + case TE_SET_RBS: + /* Set RBS bits */ + DEBUG_TE1("%s: Set ABCD bits (%X) for channel %d!\n", + fe->name, + event->te_event.rbs_abcd, + event->te_event.rbs_channel); + err=sdla_ds_te1_set_rbsbits(fe, + event->te_event.rbs_channel, + event->te_event.rbs_abcd); + break; + + case TE_RBS_ENABLE: + case TE_RBS_DISABLE: + if (event->type == TE_RBS_ENABLE){ + err=sdla_ds_te1_rbs_ctrl(fe, event->te_event.ch_map, WAN_TRUE); + }else{ + err=sdla_ds_te1_rbs_ctrl(fe, event->te_event.ch_map, WAN_FALSE); + } + break; + + case TE_SET_LB_MODE: + err=sdla_ds_te1_set_lb(fe, event->te_event.lb_type, event->mode, ENABLE_ALL_CHANNELS); + break; + + case TE_POLL_CONFIG: + DEBUG_EVENT("%s: Re-configuring %s Front-End chip...\n", + fe->name, FE_MEDIA_DECODE(fe)); + if ((err=sdla_ds_te1_chip_config(fe))){ + DEBUG_EVENT("%s: Failed to re-configuring Front-End chip!\n", + fe->name); + break; + } + /* Do not enable interrupts here */ + event->type = TE_LINKDOWN_TIMER; + event->delay = POLLING_TE1_TIMER; + *pending = 1; + + break; +#if 0 + case TE_POLL_CONFIG_VERIFY: + DEBUG_EVENT("%s: Verifing %s Front-End chip configuration...\n", + fe->name, FE_MEDIA_DECODE(fe)); + if (sdla_ds_te1_chip_config_verify(fe)){ + DEBUG_EVENT("%s: Failed to verify Front-End chip configuration!\n", + fe->name); + } + break; +#endif + case TE_POLL_READ: + fe->te_param.reg_dbg_value = READ_REG(event->te_event.reg); + DEBUG_TE1("%s: Read %s Front-End Reg:%04X=%02X\n", + fe->name, FE_MEDIA_DECODE(fe), + event->te_event.reg, + fe->te_param.reg_dbg_value); + fe->te_param.reg_dbg_ready = 1; +#if 0 + DEBUG_EVENT("%s: Reading %s Front-End Registers:\n", + fe->name, FE_MEDIA_DECODE(fe)); + for(reg=0x0;reg<=0x1ff;reg++){ + DEBUG_EVENT("%s: REG[%04X]=%02X\n", + fe->name, reg, READ_REG(reg)); + } + DEBUG_EVENT("%s: Reading %s Front-End LIU Registers:\n", + fe->name, FE_MEDIA_DECODE(fe)); + for(reg=0x1000;reg<=0x1007;reg++){ + DEBUG_EVENT("%s: REG[%04X]=%02X\n", + fe->name, reg, READ_REG(reg)); + } + DEBUG_EVENT("%s: Reading %s Front-End BERT Registers:\n", + fe->name, FE_MEDIA_DECODE(fe)); + for(reg=0x1100;reg<=0x110F;reg++){ + DEBUG_EVENT("%s: REG[%04X]=%02X\n", + fe->name, reg, READ_REG(reg)); + } +#endif + break; + + case TE_POLL_WRITE: + DEBUG_EVENT("%s: Write %s Front-End Reg:%04X=%02X\n", + fe->name, FE_MEDIA_DECODE(fe), + event->te_event.reg, + event->te_event.value); + WRITE_REG(event->te_event.reg, event->te_event.value); + break; + + case TE_LINELB_TIMER: + if (IS_T1_FEMEDIA(fe)){ + err=sdla_ds_te1_txlbcode_done(fe); + } + break; + + case WAN_TE_POLL_BERT: + err=sdla_ds_te1_bert_read_status(fe); + if (!err){ + *pending = 1; + } + break; + + default: + DEBUG_EVENT("%s: Unknown DS TE1 Polling type %02X\n", + fe->name, event->type); + err=-1; + break; + } + + return err; +} + static int sdla_ds_te1_poll_events(sdla_fe_t* fe) { sdla_fe_timer_event_t *event; wan_smp_flag_t smp_flags; u_int8_t pending = 0; - + int err; + wan_spin_lock_irq(&fe->lockirq,&smp_flags); if (WAN_LIST_EMPTY(&fe->event)){ wan_spin_unlock_irq(&fe->lockirq,&smp_flags); @@ -3952,113 +4197,9 @@ static int sdla_ds_te1_poll_events(sdla_fe_t* fe) DEBUG_TE1("%s: TE1 Polling event:0x%02X State=%s!\n", fe->name, event->type, WAN_FE_STATUS_DECODE(fe)); - switch(event->type){ - case TE_RBS_READ: - /* Physically read RBS status and print */ - sdla_ds_te1_rbs_print(fe, 0); - break; - case TE_SET_RBS: - /* Set RBS bits */ - DEBUG_TE1("%s: Set ABCD bits (%X) for channel %d!\n", - fe->name, - event->te_event.rbs_abcd, - event->te_event.rbs_channel); - sdla_ds_te1_set_rbsbits(fe, - event->te_event.rbs_channel, - event->te_event.rbs_abcd); - break; + err=sdla_ds_te1_exec_event(fe,event,&pending); - case TE_RBS_ENABLE: - case TE_RBS_DISABLE: - if (event->type == TE_RBS_ENABLE){ - sdla_ds_te1_rbs_ctrl(fe, event->te_event.ch_map, WAN_TRUE); - }else{ - sdla_ds_te1_rbs_ctrl(fe, event->te_event.ch_map, WAN_FALSE); - } - break; - - case TE_SET_LB_MODE: - sdla_ds_te1_set_lb(fe, event->te_event.lb_type, event->mode, ENABLE_ALL_CHANNELS); - break; - - case TE_POLL_CONFIG: - DEBUG_EVENT("%s: Re-configuring %s Front-End chip...\n", - fe->name, FE_MEDIA_DECODE(fe)); - if (sdla_ds_te1_chip_config(fe)){ - DEBUG_EVENT("%s: Failed to re-configuring Front-End chip!\n", - fe->name); - break; - } - /* Do not enable interrupts here */ - event->type = TE_LINKDOWN_TIMER; - event->delay = POLLING_TE1_TIMER; - pending = 1; - break; -#if 0 - case TE_POLL_CONFIG_VERIFY: - DEBUG_EVENT("%s: Verifing %s Front-End chip configuration...\n", - fe->name, FE_MEDIA_DECODE(fe)); - if (sdla_ds_te1_chip_config_verify(fe)){ - DEBUG_EVENT("%s: Failed to verify Front-End chip configuration!\n", - fe->name); - } - break; -#endif - case TE_POLL_READ: - fe->te_param.reg_dbg_value = READ_REG(event->te_event.reg); - DEBUG_TE1("%s: Read %s Front-End Reg:%04X=%02X\n", - fe->name, FE_MEDIA_DECODE(fe), - event->te_event.reg, - fe->te_param.reg_dbg_value); - fe->te_param.reg_dbg_ready = 1; -#if 0 - DEBUG_EVENT("%s: Reading %s Front-End Registers:\n", - fe->name, FE_MEDIA_DECODE(fe)); - for(reg=0x0;reg<=0x1ff;reg++){ - DEBUG_EVENT("%s: REG[%04X]=%02X\n", - fe->name, reg, READ_REG(reg)); - } - DEBUG_EVENT("%s: Reading %s Front-End LIU Registers:\n", - fe->name, FE_MEDIA_DECODE(fe)); - for(reg=0x1000;reg<=0x1007;reg++){ - DEBUG_EVENT("%s: REG[%04X]=%02X\n", - fe->name, reg, READ_REG(reg)); - } - DEBUG_EVENT("%s: Reading %s Front-End BERT Registers:\n", - fe->name, FE_MEDIA_DECODE(fe)); - for(reg=0x1100;reg<=0x110F;reg++){ - DEBUG_EVENT("%s: REG[%04X]=%02X\n", - fe->name, reg, READ_REG(reg)); - } -#endif - break; - - case TE_POLL_WRITE: - DEBUG_EVENT("%s: Write %s Front-End Reg:%04X=%02X\n", - fe->name, FE_MEDIA_DECODE(fe), - event->te_event.reg, - event->te_event.value); - WRITE_REG(event->te_event.reg, event->te_event.value); - break; - - case TE_LINELB_TIMER: - if (IS_T1_FEMEDIA(fe)){ - sdla_ds_te1_txlbcode_done(fe); - } - break; - - case WAN_TE_POLL_BERT: - if (!sdla_ds_te1_bert_read_status(fe)){ - pending = 1; - } - break; - - default: - DEBUG_EVENT("%s: Unknown DS TE1 Polling type %02X\n", - fe->name, event->type); - break; - } /* Add new event */ if (pending){ sdla_ds_te1_add_event(fe, event); @@ -4079,9 +4220,18 @@ static int sdla_ds_te1_poll_events(sdla_fe_t* fe) ******************************************************************************/ static int sdla_ds_te1_polling(sdla_fe_t* fe) { + WAN_ASSERT(fe == NULL); + + if (wan_test_bit(TE_TIMER_KILL,(void*)&fe->te_param.critical)) { + DEBUG_EVENT("%s: Device is shutting down ignoring poll!\n", + fe->name, __FUNCTION__); + return 0; + } WAN_ASSERT_RC(fe->write_fe_reg == NULL, 0); WAN_ASSERT_RC(fe->read_fe_reg == NULL, 0); + WAN_ASSERT(fe->swirq == NULL); + #if 0 DEBUG_EVENT("%s: %s:%d: ---------------START ----------------------\n", @@ -4099,6 +4249,15 @@ static int sdla_ds_te1_polling(sdla_fe_t* fe) sdla_ds_te1_poll_events(fe); } + if (fe->te_param.tx_ais_alarm && fe->te_param.tx_ais_startup_timeout) { + if (SYSTEM_TICKS - fe->te_param.tx_ais_startup_timeout > HZ*10) { + if (!(fe->fe_alarm & WAN_TE_BIT_ALARM_LOS)) { + fe->te_param.tx_ais_startup_timeout=0; + sdla_ds_te1_clear_alarms(fe,WAN_TE_BIT_ALARM_AIS); + } + } + } + wan_clear_bit(TE_TIMER_EVENT_PENDING,(void*)&fe->te_param.critical); sdla_ds_te1_add_timer(fe, POLLING_TE1_TIMER); return 0; @@ -4891,7 +5050,8 @@ sdla_ds_te1_udp_get_stats(sdla_fe_t *fe, char *data,int force) /* TE1 Update T1/E1 perfomance counters */ sdla_ds_te1_pmon(fe, WAN_FE_PMON_UPDATE|WAN_FE_PMON_READ); sdla_ds_te1_rxlevel(fe); - memcpy(stats, &fe->fe_stats, sizeof(sdla_fe_stats_t)); + memcpy(stats, &fe->fe_stats, sizeof(sdla_fe_stats_t)); + if (force){ /* force to read FE alarms */ @@ -5380,7 +5540,9 @@ static int sdla_ds_te1_udp(sdla_fe_t *fe, void* p_udp_cmd, unsigned char* data) wan_femedia_t *fe_media; sdla_fe_debug_t *fe_debug; sdla_fe_timer_event_t event; - + uint8_t pending; + int err; + switch(udp_cmd->wan_cmd_command){ case WAN_GET_MEDIA_TYPE: fe_media = (wan_femedia_t*)data; @@ -5396,30 +5558,30 @@ static int sdla_ds_te1_udp(sdla_fe_t *fe, void* p_udp_cmd, unsigned char* data) case WAN_FE_LB_MODE: /* Activate/Deactivate Line Loopback modes */ sdla_ds_te1_udp_lb(fe, data); - udp_cmd->wan_cmd_data_len = sizeof(sdla_fe_lbmode_t); - udp_cmd->wan_cmd_return_code = WAN_CMD_OK; + udp_cmd->wan_cmd_data_len = sizeof(sdla_fe_lbmode_t); + udp_cmd->wan_cmd_return_code = WAN_CMD_OK; break; case WAN_FE_GET_STAT: sdla_ds_te1_udp_get_stats(fe, data, udp_cmd->wan_cmd_fe_force); - udp_cmd->wan_cmd_return_code = WAN_CMD_OK; - udp_cmd->wan_cmd_data_len = sizeof(sdla_fe_stats_t); + udp_cmd->wan_cmd_return_code = WAN_CMD_OK; + udp_cmd->wan_cmd_data_len = sizeof(sdla_fe_stats_t); break; case WAN_FE_FLUSH_PMON: /* TE1 Flush T1/E1 pmon counters */ sdla_ds_te1_flush_pmon(fe); - udp_cmd->wan_cmd_return_code = WAN_CMD_OK; + udp_cmd->wan_cmd_return_code = WAN_CMD_OK; break; case WAN_FE_GET_CFG: /* Read T1/E1 configuration */ - memcpy(&data[0], - &fe->fe_cfg, - sizeof(sdla_fe_cfg_t)); - udp_cmd->wan_cmd_return_code = WAN_CMD_OK; - udp_cmd->wan_cmd_data_len = sizeof(sdla_fe_cfg_t); - break; + memcpy(&data[0], + &fe->fe_cfg, + sizeof(sdla_fe_cfg_t)); + udp_cmd->wan_cmd_return_code = WAN_CMD_OK; + udp_cmd->wan_cmd_data_len = sizeof(sdla_fe_cfg_t); + break; case WAN_FE_SET_DEBUG_MODE: fe_debug = (sdla_fe_debug_t*)&data[0]; @@ -5430,8 +5592,9 @@ static int sdla_ds_te1_udp(sdla_fe_t *fe, void* p_udp_cmd, unsigned char* data) fe->name); event.type = TE_RBS_READ; event.delay = POLLING_TE1_TIMER; - sdla_ds_te1_add_event(fe, &event); - udp_cmd->wan_cmd_return_code = WAN_CMD_OK; + err=sdla_ds_te1_exec_event(fe, &event, &pending); + udp_cmd->wan_cmd_return_code = err; + }else if (fe_debug->mode == WAN_FE_DEBUG_RBS_PRINT){ /* Enable extra debugging */ sdla_ds_te1_rbs_print(fe, 1); @@ -5465,7 +5628,8 @@ static int sdla_ds_te1_udp(sdla_fe_t *fe, void* p_udp_cmd, unsigned char* data) sdla_ds_te1_rbs_print(fe, 1); udp_cmd->wan_cmd_return_code = WAN_CMD_OK; }else if (fe_debug->mode == WAN_FE_DEBUG_RBS_SET){ - + + if (IS_T1_FEMEDIA(fe)){ if (fe_debug->fe_debug_rbs.channel < 1 || fe_debug->fe_debug_rbs.channel > 24){ @@ -5490,15 +5654,16 @@ static int sdla_ds_te1_udp(sdla_fe_t *fe, void* p_udp_cmd, unsigned char* data) event.delay = POLLING_TE1_TIMER; event.te_event.rbs_channel = fe_debug->fe_debug_rbs.channel; event.te_event.rbs_abcd = fe_debug->fe_debug_rbs.abcd; - sdla_ds_te1_add_event(fe, &event); - udp_cmd->wan_cmd_return_code = WAN_CMD_OK; + err=sdla_ds_te1_exec_event(fe, &event, &pending); + udp_cmd->wan_cmd_return_code = err; + } break; case WAN_FE_DEBUG_RECONFIG: event.type = TE_POLL_CONFIG; event.delay = POLLING_TE1_TIMER; sdla_ds_te1_add_event(fe, &event); - udp_cmd->wan_cmd_return_code = WAN_CMD_OK; + udp_cmd->wan_cmd_return_code = WAN_CMD_OK; break; #if 0 @@ -5529,12 +5694,35 @@ static int sdla_ds_te1_udp(sdla_fe_t *fe, void* p_udp_cmd, unsigned char* data) fe->te_param.reg_dbg_busy = 1; fe->te_param.reg_dbg_ready = 0; } - sdla_ds_te1_add_event(fe, &event); - udp_cmd->wan_cmd_return_code = WAN_CMD_OK; + err=sdla_ds_te1_exec_event(fe, &event, &pending); + udp_cmd->wan_cmd_return_code = err; break; case WAN_FE_DEBUG_ALARM: + + if (fe_debug->mode == WAN_FE_DEBUG_ALARM_AIS_ENABLE) { + DEBUG_EVENT("%s: Alarm Maintenance AIS On\n",fe->name); + sdla_ds_te1_set_alarms(fe,WAN_TE_BIT_ALARM_AIS); + fe->fe_stats.tx_maint_alarms |= WAN_TE_BIT_ALARM_AIS; + /* If user set the AIS the make sure to turn off + the startup timer that will turn off AIS + after timeout */ + fe->te_param.tx_ais_startup_timeout=0; + udp_cmd->wan_cmd_return_code = WAN_CMD_OK; + } else if (fe_debug->mode == WAN_FE_DEBUG_ALARM_AIS_DISABLE) { + DEBUG_EVENT("%s: Alarm Maintenance AIS Off\n",fe->name); + sdla_ds_te1_clear_alarms(fe,WAN_TE_BIT_ALARM_AIS); + fe->fe_stats.tx_maint_alarms &= ~WAN_TE_BIT_ALARM_AIS; + udp_cmd->wan_cmd_return_code = WAN_CMD_OK; + } else { + DEBUG_ERROR("%s: Error Invalid Alarm command 0x%02X\n",fe->name,fe_debug->mode); + udp_cmd->wan_cmd_return_code = WAN_UDP_INVALID_CMD; + } + break; + default: + DEBUG_ERROR("%s: Error Invalid WAN_FE_SET_DEBUG_MODE cmd 0x%02X\n", + fe->name,fe_debug->type); udp_cmd->wan_cmd_return_code = WAN_UDP_INVALID_CMD; break; } diff --git a/patches/kdrivers/src/net/sdla_adsl.c b/patches/kdrivers/src/net/sdla_adsl.c index 7f4e2f1..4f04a22 100644 --- a/patches/kdrivers/src/net/sdla_adsl.c +++ b/patches/kdrivers/src/net/sdla_adsl.c @@ -2225,9 +2225,9 @@ static int process_udp_cmd(netdevice_t* ifp, wan_udp_hdr_t* udp_hdr) } switch(udp_hdr->wan_udphdr_command){ case WAN_GET_PROTOCOL: - udp_hdr->wan_udphdr_adsl_num_frames = WANCONFIG_ADSL; - udp_hdr->wan_udphdr_return_code = WAN_CMD_OK; - udp_hdr->wan_udphdr_data_len = 2; + udp_hdr->wan_udphdr_data[0] = (unsigned char)card->wandev.config_id; + udp_hdr->wan_udphdr_return_code = WAN_CMD_OK; + udp_hdr->wan_udphdr_data_len = 1; break; case WAN_GET_PLATFORM: diff --git a/patches/kdrivers/src/net/sdla_aft_te3.c b/patches/kdrivers/src/net/sdla_aft_te3.c index 1b40a2c..098826f 100644 --- a/patches/kdrivers/src/net/sdla_aft_te3.c +++ b/patches/kdrivers/src/net/sdla_aft_te3.c @@ -1437,12 +1437,12 @@ static void disable_comm (sdla_t *card) /* Unconfiging, only on shutdown */ if (IS_TE3(&card->fe.fe_cfg)) { - if (card->wandev.fe_iface.pre_release){ - card->wandev.fe_iface.pre_release(&card->fe); - } if (card->wandev.fe_iface.unconfig){ card->wandev.fe_iface.unconfig(&card->fe); } + if (card->wandev.fe_iface.post_unconfig){ + card->wandev.fe_iface.post_unconfig(&card->fe); + } } wan_spin_lock_irq(&card->wandev.lock,&flags); @@ -6115,12 +6115,12 @@ static void aft_critical_shutdown (sdla_t *card) /* Unconfiging, only on shutdown */ if (IS_TE3(&card->fe.fe_cfg)) { - if (card->wandev.fe_iface.pre_release){ - card->wandev.fe_iface.pre_release(&card->fe); - } if (card->wandev.fe_iface.unconfig){ card->wandev.fe_iface.unconfig(&card->fe); } + if (card->wandev.fe_iface.post_unconfig){ + card->wandev.fe_iface.post_unconfig(&card->fe); + } } port_set_state(card,WAN_DISCONNECTED); diff --git a/patches/kdrivers/src/net/sdla_asyhdlc.c b/patches/kdrivers/src/net/sdla_asyhdlc.c index da27a41..fc42378 100644 --- a/patches/kdrivers/src/net/sdla_asyhdlc.c +++ b/patches/kdrivers/src/net/sdla_asyhdlc.c @@ -1116,8 +1116,8 @@ static void disable_comm (sdla_t *card) /* TE1 - Unconfiging, only on shutdown */ if (IS_TE1_CARD(card)) { - if (card->wandev.fe_iface.pre_release){ - card->wandev.fe_iface.pre_release(&card->fe); + if (card->wandev.fe_iface.post_unconfig){ + card->wandev.fe_iface.post_unconfig(&card->fe); } if (card->wandev.fe_iface.unconfig){ card->wandev.fe_iface.unconfig(&card->fe); @@ -1578,8 +1578,8 @@ static int chdlc_disable_comm_shutdown (sdla_t *card) /* TE1 - Unconfiging, only on shutdown */ if (IS_TE1_CARD(card)) { - if (card->wandev.fe_iface.pre_release){ - card->wandev.fe_iface.pre_release(&card->fe); + if (card->wandev.fe_iface.post_unconfig){ + card->wandev.fe_iface.post_unconfig(&card->fe); } if (card->wandev.fe_iface.unconfig){ card->wandev.fe_iface.unconfig(&card->fe); diff --git a/patches/kdrivers/src/net/sdla_bitstrm.c b/patches/kdrivers/src/net/sdla_bitstrm.c index 6865cd7..fd4c683 100644 --- a/patches/kdrivers/src/net/sdla_bitstrm.c +++ b/patches/kdrivers/src/net/sdla_bitstrm.c @@ -1730,8 +1730,8 @@ static int if_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd) card->u.b.cfg.max_length_tx_data_block = 682;//divisible by 31 card->u.b.time_slots = NO_ACTIVE_RX_TIME_SLOTS_E1; } - if (card->wandev.fe_iface.pre_release){ - card->wandev.fe_iface.pre_release(&card->fe); + if (card->wandev.fe_iface.post_unconfig){ + card->wandev.fe_iface.post_unconfig(&card->fe); } if (card->wandev.fe_iface.unconfig){ card->wandev.fe_iface.unconfig(&card->fe); @@ -2058,13 +2058,13 @@ static void disable_comm (sdla_t *card) /* TE1 - Unconfiging */ - if (card->wandev.fe_iface.pre_release){ - card->wandev.fe_iface.pre_release(&card->fe); - } if (IS_TE1_CARD(card)) { if (card->wandev.fe_iface.unconfig){ card->wandev.fe_iface.unconfig(&card->fe); } + if (card->wandev.fe_iface.post_unconfig){ + card->wandev.fe_iface.post_unconfig(&card->fe); + } } return; } diff --git a/patches/kdrivers/src/net/sdla_bri.c b/patches/kdrivers/src/net/sdla_bri.c index a399fcf..622e7b9 100644 --- a/patches/kdrivers/src/net/sdla_bri.c +++ b/patches/kdrivers/src/net/sdla_bri.c @@ -97,6 +97,11 @@ static void dump_data(u8 *data, int data_len); static int check_data(u8 *data, int data_len); #endif +typedef enum _wp_bri_critical_bits { + WP_BCB_BRI_CONFIG, + WP_BCB_BRI_POST_INIT +} wp_bri_critical_bits_t; + /******************************************************************************* ** DEFINES AND MACROS *******************************************************************************/ @@ -188,11 +193,16 @@ extern WAN_LIST_HEAD(, wan_tdmv_) wan_tdmv_head; *******************************************************************************/ static int32_t bri_global_config(void* pfe); static int32_t bri_global_unconfig(void* pfe); + static int32_t wp_bri_config(void *pfe); -static int32_t wp_bri_unconfig(void *pfe); static int32_t wp_bri_post_init(void *pfe); + +static int32_t wp_bri_unconfig(void *pfe); +static int32_t wp_bri_post_unconfig(void* pfe); + static int32_t wp_bri_if_config(void *pfe, u32 mod_map, u8); static int32_t wp_bri_if_unconfig(void *pfe, u32 mod_map, u8); + static int32_t wp_bri_disable_irq(sdla_fe_t *fe, u32 mod_no, u8 port_no); static int wp_bri_disable_fe_irq(void *fe); static void bri_enable_interrupts(sdla_fe_t *fe, u32 mod_no, u8 port_no); @@ -203,11 +213,10 @@ static int32_t wp_bri_udp(sdla_fe_t*, void*, u8*); static u32 wp_bri_active_map(sdla_fe_t* fe, u8 line_no); static u8 wp_bri_fe_media(sdla_fe_t *fe); static int32_t wp_bri_set_dtmf(sdla_fe_t*, int32_t, u8); + static int wp_bri_intr_ctrl(sdla_fe_t *fe, int, u_int8_t, u_int8_t, unsigned int); static int wp_bri_event_ctrl(sdla_fe_t*, wan_event_ctrl_t*); -static int wp_bri_pre_release(void* pfe); - static int32_t wp_bri_dchan_tx(sdla_fe_t *fe, void *src_data_buffer, u32 buffer_len); static void *wp_bri_dchan_rx(sdla_fe_t *fe, u8 mod_no, u8 port_no); @@ -1412,13 +1421,13 @@ int32_t wp_bri_iface_init(void *pfe_iface) sdla_fe_iface_t *fe_iface = (sdla_fe_iface_t*)pfe_iface; BRI_FUNC(); - fe_iface->global_config = &bri_global_config; /* not used in remora */ - fe_iface->global_unconfig = &bri_global_unconfig; /* not used in remora */ + fe_iface->global_config = &bri_global_config; /* not used in BRI */ + fe_iface->global_unconfig = &bri_global_unconfig; /* not used in BRI */ fe_iface->config = &wp_bri_config; fe_iface->unconfig = &wp_bri_unconfig; - fe_iface->pre_release = &wp_bri_pre_release; + fe_iface->post_unconfig = &wp_bri_post_unconfig; fe_iface->post_init = &wp_bri_post_init; @@ -1668,14 +1677,15 @@ static int32_t bri_global_unconfig(void* pfe) /* ****************************************************************************** - * wp_bri_pre_release() + * wp_bri_post_unconfig() * - * Description: BRI pre release function (not locked routines) + * Description: Free resources used by 'fe'. This function is NOT locked and + * it must NOT be called more than one time. * Arguments: * Returns: ****************************************************************************** */ -static int wp_bri_pre_release(void* pfe) +static int wp_bri_post_unconfig(void* pfe) { sdla_fe_t *fe = (sdla_fe_t*)pfe; wp_bri_module_t *bri_module; @@ -1683,11 +1693,7 @@ static int wp_bri_pre_release(void* pfe) u8 mod_no, port_no; bri_xhfc_port_t *port_ptr; - DEBUG_EVENT("%s: Running pre-release...\n", fe->name); - - if(fe->fe_status == FE_UNITIALIZED){ - DEBUG_BRI("%s: %s(): Warning: Front End initialization was incomplete.\n", - fe->name, __FUNCTION__); + if (!wan_test_bit(WP_BCB_BRI_POST_INIT, &fe->bri_param.critical)) { return 1; } @@ -1695,6 +1701,8 @@ static int wp_bri_pre_release(void* pfe) return 1; } + DEBUG_EVENT("%s: Running post-unconfig...\n", fe->name); + mod_no = fe_line_no_to_physical_mod_no(fe); port_no = fe_line_no_to_port_no(fe); @@ -1711,6 +1719,8 @@ static int wp_bri_pre_release(void* pfe) }/* for (port_no = 0; port_no < bri_module->num_ports; port_no++) */ + wan_clear_bit(WP_BCB_BRI_POST_INIT, &fe->bri_param.critical); + return 0; } @@ -1739,6 +1749,11 @@ static int32_t wp_bri_config(void *pfe) BRI_FUNC(); + if (wan_test_bit(WP_BCB_BRI_CONFIG, &fe->bri_param.critical)) { + DEBUG_ERROR("%s: %s: Error: Line already configred! Line number %i !\n", + fe->name, FE_MEDIA_DECODE(fe), WAN_FE_LINENO(fe)+1); + return 1; + } fe->fe_status = FE_UNITIALIZED; @@ -1902,6 +1917,9 @@ static int32_t wp_bri_config(void *pfe) /******************************************************/ fe->fe_status = FE_DISCONNECTED; + + wan_set_bit(WP_BCB_BRI_CONFIG, &fe->bri_param.critical); + return 0; } @@ -1929,15 +1947,15 @@ static int32_t wp_bri_unconfig(void *pfe) DEBUG_HFC_INIT("%s(): mod_no: %d, port_no: %d\n", __FUNCTION__, mod_no, port_no); - DEBUG_EVENT("%s: Unconfiguring BRI Front End...\n", fe->name); - - /* Check if port was configured, if no, return. */ - if(fe->fe_status == FE_UNITIALIZED){ - DEBUG_BRI("%s: %s(): Warning: Front End initialization was incomplete.\n", + /* Check if port was configured. If not, return. */ + if (!wan_test_bit(WP_BCB_BRI_CONFIG, &fe->bri_param.critical)) { + DEBUG_BRI("%s: %s(): Warning: Front End initialization was incomplete OR not a first call to UnConfig!\n", fe->name, __FUNCTION__); return 1; } + DEBUG_EVENT("%s: Unconfiguring BRI Front End...\n", fe->name); + bri_module = &bri->mod[mod_no]; port_ptr = &bri_module->port[port_no]; @@ -1998,7 +2016,11 @@ static int32_t wp_bri_unconfig(void *pfe) } #endif /******************************************************************/ + fe->fe_status = FE_UNITIALIZED; + + wan_clear_bit(WP_BCB_BRI_CONFIG, &fe->bri_param.critical); + return 0; } @@ -2015,12 +2037,16 @@ static int32_t wp_bri_post_init(void *pfe) u8 mod_no, port_no; bri_xhfc_port_t *port_ptr; - DEBUG_EVENT("%s: Running post initialization...\n", fe->name); + if (wan_test_bit(WP_BCB_BRI_POST_INIT, &fe->bri_param.critical)) { + return 1; + } if(validate_fe_line_no(fe, __FUNCTION__)){ return 1; } + DEBUG_EVENT("%s: Running post initialization...\n", fe->name); + mod_no = fe_line_no_to_physical_mod_no(fe); port_no = fe_line_no_to_port_no(fe); @@ -2050,6 +2076,9 @@ static int32_t wp_bri_post_init(void *pfe) card->hw_iface.hw_unlock(card->hw,&smp_flags1); } #endif + + wan_set_bit(WP_BCB_BRI_POST_INIT, &fe->bri_param.critical); + return 0; } @@ -2076,7 +2105,7 @@ static void l1_timer_start_t3(void *pport) DEBUG_HFC_S0_STATES("%s(): mod_no: %i, port number: %i\n", __FUNCTION__, mod_no, port_ptr->idx); - if(fe->fe_status == FE_UNITIALIZED){ + if (!wan_test_bit(WP_BCB_BRI_CONFIG, &fe->bri_param.critical)) { /* may get here during unload!! */ return; } @@ -2179,7 +2208,7 @@ static void l1_timer_start_t4(void *pport) DEBUG_HFC_S0_STATES("%s(): mod_no: %i, port number: %i\n", __FUNCTION__, mod_no, port_ptr->idx); - if(fe->fe_status == FE_UNITIALIZED){ + if (!wan_test_bit(WP_BCB_BRI_CONFIG, &fe->bri_param.critical)) { /* may get here during unload!! */ return; } @@ -2328,7 +2357,7 @@ static void l1_timer_start_t1(void *pport) DEBUG_HFC_S0_STATES("%s(): mod_no: %i, port number: %i\n", __FUNCTION__, mod_no, port_ptr->idx); - if(fe->fe_status == FE_UNITIALIZED){ + if (!wan_test_bit(WP_BCB_BRI_CONFIG, &fe->bri_param.critical)) { /* may get here during unload!! */ return; } @@ -3502,7 +3531,7 @@ static int32_t wp_bri_intr(sdla_fe_t *fe) BRI_FUNC(); - if(fe->fe_status == FE_UNITIALIZED){ + if (!wan_test_bit(WP_BCB_BRI_CONFIG, &fe->bri_param.critical)) { return 0; } diff --git a/patches/kdrivers/src/net/sdla_bri_tdmv.c b/patches/kdrivers/src/net/sdla_bri_tdmv.c index 1c1244c..3ad3f2f 100644 --- a/patches/kdrivers/src/net/sdla_bri_tdmv.c +++ b/patches/kdrivers/src/net/sdla_bri_tdmv.c @@ -177,7 +177,7 @@ static int wp_tdmv_rx_dchan(wan_tdmv_t*, int, unsigned char*, unsigned int); static int wp_tdmv_span_buf_rotate(void *pcard, u32, unsigned long, int); -static void wp_tdmv_report_alarms(void* pcard, unsigned long te_alarm); +static void wp_tdmv_report_alarms(void* pcard, uint32_t te_alarm); #ifdef DAHDI_22 static int wp_tdmv_bri_hwec_create(struct dahdi_chan *chan, @@ -1450,7 +1450,7 @@ static int wp_tdmv_rx_dchan(wan_tdmv_t *wan_tdmv, int channo, ** ** DONE */ -static void wp_tdmv_report_alarms(void* pcard, unsigned long te_alarm) +static void wp_tdmv_report_alarms(void* pcard, uint32_t te_alarm) { sdla_t *card = (sdla_t*)pcard; wan_tdmv_t *wan_tdmv = &card->wan_tdmv; diff --git a/patches/kdrivers/src/net/sdla_chdlc.c b/patches/kdrivers/src/net/sdla_chdlc.c index 3d98015..dcb5716 100644 --- a/patches/kdrivers/src/net/sdla_chdlc.c +++ b/patches/kdrivers/src/net/sdla_chdlc.c @@ -1396,8 +1396,8 @@ static void disable_comm (sdla_t *card) /* TE1 - Unconfiging, only on shutdown */ if (IS_TE1_CARD(card)) { - if (card->wandev.fe_iface.pre_release){ - card->wandev.fe_iface.pre_release(&card->fe); + if (card->wandev.fe_iface.post_unconfig){ + card->wandev.fe_iface.post_unconfig(&card->fe); } if (card->wandev.fe_iface.unconfig){ card->wandev.fe_iface.unconfig(&card->fe); @@ -1909,12 +1909,12 @@ static int chdlc_disable_comm_shutdown (sdla_t *card) /* TE1 - Unconfiging, only on shutdown */ if (IS_TE1_CARD(card)) { - if (card->wandev.fe_iface.pre_release){ - card->wandev.fe_iface.pre_release(&card->fe); - } if (card->wandev.fe_iface.unconfig){ card->wandev.fe_iface.unconfig(&card->fe); } + if (card->wandev.fe_iface.post_unconfig){ + card->wandev.fe_iface.post_unconfig(&card->fe); + } } return 0; diff --git a/patches/kdrivers/src/net/sdla_fr.c b/patches/kdrivers/src/net/sdla_fr.c index 818040e..59dc93d 100644 --- a/patches/kdrivers/src/net/sdla_fr.c +++ b/patches/kdrivers/src/net/sdla_fr.c @@ -1439,12 +1439,12 @@ static void disable_comm (sdla_t *card) /* TE1 unconfiging */ if (IS_TE1_CARD(card)) { - if (card->wandev.fe_iface.pre_release){ - card->wandev.fe_iface.pre_release(&card->fe); - } if (card->wandev.fe_iface.unconfig){ card->wandev.fe_iface.unconfig(&card->fe); } + if (card->wandev.fe_iface.post_unconfig){ + card->wandev.fe_iface.post_unconfig(&card->fe); + } } } diff --git a/patches/kdrivers/src/net/sdla_ppp.c b/patches/kdrivers/src/net/sdla_ppp.c index d4e4a2b..9b38371 100644 --- a/patches/kdrivers/src/net/sdla_ppp.c +++ b/patches/kdrivers/src/net/sdla_ppp.c @@ -871,12 +871,12 @@ static void disable_comm (sdla_t *card) /* TE1 unconfiging */ if (IS_TE1_CARD(card)) { - if (card->wandev.fe_iface.pre_release){ - card->wandev.fe_iface.pre_release(&card->fe); - } if (card->wandev.fe_iface.unconfig){ card->wandev.fe_iface.unconfig(&card->fe); } + if (card->wandev.fe_iface.post_unconfig){ + card->wandev.fe_iface.post_unconfig(&card->fe); + } } return; } diff --git a/patches/kdrivers/src/net/sdla_remora.c b/patches/kdrivers/src/net/sdla_remora.c index 6ee8cd8..d40079e 100644 --- a/patches/kdrivers/src/net/sdla_remora.c +++ b/patches/kdrivers/src/net/sdla_remora.c @@ -402,7 +402,7 @@ int wp_init_voicedaa(sdla_fe_t *fe, int mod_no, int fast, int sane); static int wp_remora_config(void *pfe); static int wp_remora_unconfig(void *pfe); static int wp_remora_post_init(void *pfe); -static int wp_remora_pre_release(void* pfe); +static int wp_remora_post_unconfig(void* pfe); static int wp_remora_if_config(void *pfe, u32 mod_map, u8); static int wp_remora_if_unconfig(void *pfe, u32 mod_map, u8); static int wp_remora_disable_irq(void *pfe); @@ -417,10 +417,8 @@ static int wp_remora_intr_ctrl(sdla_fe_t*, int, u_int8_t, u_int8_t, unsigned int static int wp_remora_event_ctrl(sdla_fe_t*, wan_event_ctrl_t*); static int wp_remora_get_link_status(sdla_fe_t *fe, unsigned char *status,int mod_no); -static int wp_remora_add_timer(sdla_fe_t*, unsigned long); - #if 0 -static int wp_remora_add_event(sdla_fe_t*, sdla_fe_timer_event_t*); +static int wp_remora_add_timer(sdla_fe_t*, unsigned long); #endif #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) @@ -473,6 +471,7 @@ wp_proslic_setreg_indirect(sdla_fe_t *fe, int mod_no, unsigned char address, uns DEBUG_REG("%s: Indirect Register %d = %X\n", fe->name, address, data); + WRITE_RM_REG(mod_no, IDA_LO,(unsigned char)(data & 0xFF)); WRITE_RM_REG(mod_no, IDA_HI,(unsigned char)((data & 0xFF00)>>8)); WRITE_RM_REG(mod_no, IAA,address); @@ -528,8 +527,24 @@ static int wp_proslic_init_indirect_regs(sdla_fe_t *fe, int mod_no) DEBUG_CFG("%s: Initializing Indirect Registers...\n", fe->name); for (i=0; iname, mod_no, indirect_regs[i].address,x, indirect_regs[i].initial); + } +#endif if(wp_proslic_setreg_indirect(fe, mod_no, indirect_regs[i].address,indirect_regs[i].initial)) return -1; + +#if 0 + if (mod_no == 0 && indirect_regs[i].address==20) { + int x; + x= wp_proslic_getreg_indirect(fe, mod_no, indirect_regs[i].address); + DEBUG_EVENT("%s: AFTER mod_no:%d indirect_reg address:%d val:%x, writing:%x\n", fe->name, mod_no, indirect_regs[i].address,x, indirect_regs[i].initial); + } +#endif + } DEBUG_CFG("%s: Initializing Indirect Registers...Done!\n", fe->name); @@ -559,7 +574,7 @@ static int wp_proslic_verify_indirect_regs(sdla_fe_t *fe, int mod_no) if ( j != initial && indirect_regs[i].altaddr != 255){ DEBUG_EVENT( - "%s: Module %d: Internal Error: iReg=%s (%X) Value=%X (%X)\n", + "%s: Module %d: Internal Error: iReg=%s (%d) Value=%X (%X)\n", fe->name, mod_no+1, indirect_regs[i].name, indirect_regs[i].address, @@ -599,7 +614,7 @@ static int wp_remora_chain_enable(sdla_fe_t *fe) return 0; } - for(mod_no = 0;mod_no < fe->rm_param.max_fe_channels; mod_no ++){ + for(mod_no = 0;mod_no < fe->rm_param.max_fe_channels; mod_no ++){ if (fe->rm_param.mod[mod_no].type == MOD_TYPE_NONE){ byte = READ_RM_FXS_REG(mod_no, 0, 0); byte &= 0x0F; @@ -622,7 +637,12 @@ static int wp_remora_chain_enable(sdla_fe_t *fe) for(mod_no = 0;mod_no < fe->rm_param.max_fe_channels; mod_no ++){ if (fe->rm_param.mod[mod_no].type == MOD_TYPE_NONE){ - byte = READ_RM_FXO_REG(mod_no,1,2); + if (IS_B800(fe)) { + /* Not sure why we would try to read FXO with chain enable on A200/A400 */ + byte = READ_RM_FXO_REG(mod_no,0,2); + } else { + byte = READ_RM_FXO_REG(mod_no,1,2); + } if (byte == 0x03){ DEBUG_RM("%s: Module %d FXO\n", fe->name, mod_no+1); @@ -636,32 +656,35 @@ static int wp_remora_chain_enable(sdla_fe_t *fe) fe->reset_fe(fe); /* Now enable chain mode for only FXS modules (FXO by default chain) */ - for(mod_no = 0;mod_no < fe->rm_param.max_fe_channels; mod_no ++){ - if (fe->rm_param.mod[mod_no].type == MOD_TYPE_FXS && mod_no % 2 == 0){ - WRITE_RM_FXS_REG(mod_no,0,0,0xC0); - byte = READ_RM_FXS_REG(mod_no, 1, 0); - if ((byte & 0x80) != 0x80){ - DEBUG_RM( - "%s: Module %d: Failed to enable chain (%02X)!\n", - fe->name, mod_no+1, byte); - return -EINVAL; - } - }else if (fe->rm_param.mod[mod_no].type == MOD_TYPE_FXO){ - byte = READ_RM_FXO_REG(mod_no,1,2); - if (byte != 0x03){ - /* Should never happened */ - fe->rm_param.mod[mod_no].type = MOD_TYPE_NONE; + /* B800 Does not use chain mode */ + if (!IS_B800(fe)) { + for(mod_no = 0;mod_no < fe->rm_param.max_fe_channels; mod_no ++){ + if (fe->rm_param.mod[mod_no].type == MOD_TYPE_FXS && mod_no % 2 == 0){ + WRITE_RM_FXS_REG(mod_no,0,0,0xC0); + byte = READ_RM_FXS_REG(mod_no, 1, 0); + if ((byte & 0x80) != 0x80){ + DEBUG_RM( + "%s: Module %d: Failed to enable chain (%02X)!\n", + fe->name, mod_no+1, byte); + return -EINVAL; + } + }else if (fe->rm_param.mod[mod_no].type == MOD_TYPE_FXO){ + byte = READ_RM_FXO_REG(mod_no,1,2); + if (byte != 0x03){ + /* Should never happened */ + fe->rm_param.mod[mod_no].type = MOD_TYPE_NONE; + continue; + } + }else if (fe->rm_param.mod[mod_no].type == MOD_TYPE_TEST){ + /* Test module or nothing */ continue; } - }else if (fe->rm_param.mod[mod_no].type == MOD_TYPE_TEST){ - /* Test module or nothing */ - continue; + DEBUG_RM( + "%s: Module %d %s (chain)\n", + fe->name, mod_no+1, + WP_REMORA_DECODE_TYPE(fe->rm_param.mod[mod_no].type)); + fe->rm_param.mod[mod_no].chain = MOD_CHAIN_ENABLED; } - DEBUG_RM( - "%s: Module %d %s (chain)\n", - fe->name, mod_no+1, - WP_REMORA_DECODE_TYPE(fe->rm_param.mod[mod_no].type)); - fe->rm_param.mod[mod_no].chain = MOD_CHAIN_ENABLED; } return 0; } @@ -975,7 +998,7 @@ int wp_init_proslic(sdla_fe_t *fe, int mod_no, int fast, int sane) if (!fast){ fe->rm_param.mod[mod_no].u.fxs.proslic_power = PROSLIC_POWER_UNKNOWN; } - + /* Step 9 */ if (wp_proslic_init_indirect_regs(fe, mod_no)) { DEBUG_EVENT( @@ -1462,7 +1485,7 @@ int wp_remora_iface_init(void *p_fe, void *pfe_iface) fe_iface->if_config = &wp_remora_if_config; fe_iface->if_unconfig = &wp_remora_if_unconfig; - fe_iface->pre_release = &wp_remora_pre_release; + fe_iface->post_unconfig = &wp_remora_post_unconfig; fe_iface->active_map = &wp_remora_active_map; fe_iface->isr = &wp_remora_intr; @@ -1541,11 +1564,13 @@ static int wp_remora_config(void *pfe) DEBUG_EVENT("%s: Configuring FXS/FXO Front End ...\n", fe->name); - + if (IS_A600(fe) || IS_B601(fe)) { fe->rm_param.max_fe_channels = NUM_A600_ANALOG_PORTS; } else if (IS_A700(fe)) { fe->rm_param.max_fe_channels = NUM_A700_ANALOG_PORTS; + } else if (IS_B800(fe)) { + fe->rm_param.max_fe_channels = NUM_B800_ANALOG_PORTS; } else { fe->rm_param.max_fe_channels = MAX_REMORA_MODULES; } @@ -1726,14 +1751,14 @@ static int wp_remora_unconfig(void *pfe) /* ****************************************************************************** - * sdla_te_pre_release() + * wp_remora_post_unconfig() * * Description: T1/E1 pre release routines (not locked). * Arguments: * Returns: ****************************************************************************** */ -static int wp_remora_pre_release(void* pfe) +static int wp_remora_post_unconfig(void* pfe) { sdla_fe_t *fe = (sdla_fe_t*)pfe; sdla_fe_timer_event_t *fe_event = NULL; @@ -1775,7 +1800,7 @@ static int wp_remora_post_init(void *pfe) sdla_fe_t *fe = (sdla_fe_t*)pfe; DEBUG_EVENT("%s: Running post initialization...\n", fe->name); - return wp_remora_add_timer(fe, WP_RM_POLL_TIMER); + return 0; } /****************************************************************************** @@ -1937,10 +1962,6 @@ static void wp_remora_timer(unsigned long pfe) #endif { sdla_fe_t *fe = (sdla_fe_t*)pfe; - sdla_t *card = (sdla_t*)fe->card; - wan_device_t *wandev = &card->wandev; - wan_smp_flag_t smp_flags; - int empty = 1; DEBUG_TEST("%s: RM timer!\n", fe->name); @@ -1956,11 +1977,10 @@ static void wp_remora_timer(unsigned long pfe) } wan_clear_bit(WP_RM_TIMER_RUNNING,(void*)&fe->rm_param.critical); - /* Enable hardware interrupt for TE1 */ - wan_spin_lock_irq(&fe->lockirq,&smp_flags); - empty = WAN_LIST_EMPTY(&fe->event); - wan_spin_unlock_irq(&fe->lockirq,&smp_flags); + /* NC: Polling timer is not use in remora, enable + this feature if there is a need for it */ +#if 0 if (!empty){ if (wan_test_and_set_bit(WP_RM_TIMER_EVENT_PENDING,(void*)&fe->rm_param.critical)){ DEBUG_EVENT("%s: RM timer event is pending!\n", fe->name); @@ -1974,6 +1994,7 @@ static void wp_remora_timer(unsigned long pfe) }else{ wp_remora_add_timer(fe, WP_RM_POLL_TIMER); } +#endif return; } @@ -1986,6 +2007,8 @@ static void wp_remora_timer(unsigned long pfe) * Returns: ****************************************************************************** */ + +#if 0 static int wp_remora_add_timer(sdla_fe_t* fe, unsigned long delay) { int err; @@ -1998,6 +2021,7 @@ static int wp_remora_add_timer(sdla_fe_t* fe, unsigned long delay) wan_set_bit(WP_RM_TIMER_RUNNING,(void*)&fe->rm_param.critical); return 0; } +#endif #if 0 #undef DEBUG_RM @@ -2396,9 +2420,6 @@ static int wp_remora_event_exec(sdla_fe_t* fe, sdla_fe_timer_event_t *fe_event) ******************************************************************************/ static int wp_remora_polling(sdla_fe_t* fe) { - sdla_t *card = (sdla_t*)fe->card; - sdla_fe_timer_event_t *fe_event; - wan_smp_flag_t smp_flags; int err = 0; WAN_ASSERT_RC(fe->write_fe_reg == NULL,0); @@ -2411,106 +2432,16 @@ static int wp_remora_polling(sdla_fe_t* fe) DEBUG_EVENT("%s: %s:%d: ---------------STOP ----------------------\n", fe->name, __FUNCTION__,__LINE__); #endif - wan_spin_lock_irq(&fe->lockirq,&smp_flags); - if (WAN_LIST_EMPTY(&fe->event)){ - wan_clear_bit(WP_RM_TIMER_EVENT_PENDING,(void*)&fe->rm_param.critical); - wan_spin_unlock_irq(&fe->lockirq,&smp_flags); - DEBUG_EVENT("%s: WARNING: No FE events in a queue!\n", - fe->name); - wp_remora_add_timer(fe, WP_RM_POLL_TIMER); - return 0; - } - fe_event = WAN_LIST_FIRST(&fe->event); - WAN_LIST_REMOVE(fe_event, next); - wan_spin_unlock_irq(&fe->lockirq,&smp_flags); - - wan_spin_lock_irq(&card->wandev.lock,&smp_flags); - - err=wp_remora_event_exec(fe, fe_event); - - wan_spin_unlock_irq(&card->wandev.lock,&smp_flags); wan_clear_bit(WP_RM_TIMER_EVENT_PENDING,(void*)&fe->rm_param.critical); - if (fe_event) wan_free(fe_event); - /* Add fe timer */ - fe_event = WAN_LIST_FIRST(&fe->event); - if (fe_event){ - wp_remora_add_timer(fe, fe_event->delay); - }else{ - wp_remora_add_timer(fe, WP_RM_POLL_TIMER); - } + /* NC: wp_remoare_polling is not use in remora. + If there is a need for it one can implement + logic here */ + return err; } -/* - ****************************************************************************** - * wp_remora_add_event() - * - * Description: Enable software timer interrupt in delay ms. - * Arguments: - * Returns: - ****************************************************************************** - */ -#if 0 -static int -wp_remora_add_event(sdla_fe_t *fe, sdla_fe_timer_event_t *fe_event) -{ - sdla_t *card = (sdla_t*)fe->card; - sdla_fe_timer_event_t *event = NULL; - wan_smp_flag_t smp_flags; - - WAN_ASSERT_RC(card == NULL, -EINVAL); - - DEBUG_RM("%s: Remora Event=0x%X\n", - fe->name,fe_event->type); - - /* Creating event timer */ - event = wan_malloc(sizeof(sdla_fe_timer_event_t)); - if (event == NULL){ - DEBUG_EVENT( - "%s: Failed to allocate memory for timer event!\n", - fe->name); - return -EINVAL; - } - - memcpy(event, fe_event, sizeof(sdla_fe_timer_event_t)); - -#if 0 - DEBUG_EVENT("%s: %s:%d: ---------------START ----------------------\n", - fe->name, __FUNCTION__,__LINE__); - WARN_ON(1); - DEBUG_EVENT("%s: %s:%d: ---------------STOP ----------------------\n", - fe->name, __FUNCTION__,__LINE__); -#endif - wan_spin_lock_irq(&fe->lockirq,&smp_flags); - if (WAN_LIST_EMPTY(&fe->event)){ - WAN_LIST_INSERT_HEAD(&fe->event, event, next); - }else{ -#if defined(__WINDOWS__) - /* only one event allowed at a time */ - DEBUG_RM("%s: returning EBUSY\n", - fe->name); - wan_spin_unlock_irq(&fe->lockirq, &smp_flags); - return EBUSY; -#else - sdla_fe_timer_event_t *tmp; - WAN_LIST_FOREACH(tmp, &fe->event, next){ - if (!WAN_LIST_NEXT(tmp, next)) break; - } - if (tmp == NULL){ - DEBUG_ERROR("%s: Internal Error!!!\n", fe->name); - wan_spin_unlock_irq(&fe->lockirq, &smp_flags); - return -EINVAL; - } - WAN_LIST_INSERT_AFTER(tmp, event, next); -#endif - } - wan_spin_unlock_irq(&fe->lockirq, &smp_flags); - return 0; -} -#endif - /****************************************************************************** * wp_remora_event_verification() * @@ -2679,11 +2610,7 @@ wp_remora_event_ctrl(sdla_fe_t *fe, wan_event_ctrl_t *ectrl) } if (err==0) { -#if 0 - err = wp_remora_add_event(fe, &fe_event); -#else err = wp_remora_event_exec(fe, &fe_event); -#endif } return err; } @@ -3053,11 +2980,7 @@ static int wp_remora_udp(sdla_fe_t *fe, void* p_udp_cmd, unsigned char* data) } event.rm_event.tone = WAN_EVENT_RM_TONE_TYPE_DIAL; event.delay = WP_RM_POLL_TIMER; -#if 0 - wp_remora_add_event(fe, &event); -#else wp_remora_event_exec(fe, &event); -#endif udp_cmd->wan_cmd_return_code = WAN_CMD_OK; break; @@ -3073,11 +2996,7 @@ static int wp_remora_udp(sdla_fe_t *fe, void* p_udp_cmd, unsigned char* data) } event.delay = WP_RM_POLL_TIMER; -#if 0 - wp_remora_add_event(fe, &event); -#else wp_remora_event_exec(fe, &event); -#endif udp_cmd->wan_cmd_return_code = WAN_CMD_OK; break; @@ -3120,11 +3039,7 @@ static int wp_remora_udp(sdla_fe_t *fe, void* p_udp_cmd, unsigned char* data) fe->rm_param.reg_dbg_busy = 1; fe->rm_param.reg_dbg_ready = 0; } -#if 0 - wp_remora_add_event(fe, &event); -#else wp_remora_event_exec(fe, &event); -#endif udp_cmd->wan_cmd_return_code = WAN_CMD_OK; break; @@ -3133,11 +3048,7 @@ static int wp_remora_udp(sdla_fe_t *fe, void* p_udp_cmd, unsigned char* data) WP_RM_POLL_TXSIG_OFFHOOK: WP_RM_POLL_TXSIG_ONHOOK; event.rm_event.mod_no = fe_debug->mod_no; -#if 0 - wp_remora_add_event(fe, &event); -#else wp_remora_event_exec(fe, &event); -#endif udp_cmd->wan_cmd_return_code = WAN_CMD_OK; break; @@ -3175,11 +3086,7 @@ static int wp_init_proslic_recheck_sanity(sdla_fe_t *fe, int mod_no) event.type = WP_RM_POLL_INIT; event.delay = WP_RM_POLL_TIMER; event.rm_event.mod_no = mod_no; -#if 0 - wp_remora_add_event(fe, &event); -#else wp_remora_event_exec(fe, &event); -#endif return 1; /*wp_init_proslic(fe, mod_no, 1, 1);*/ } else { @@ -3387,11 +3294,7 @@ static int wp_remora_check_intr_fxs(sdla_fe_t *fe, int mod_no) event.type = WP_RM_POLL_INIT; event.delay = WP_RM_POLL_TIMER; event.rm_event.mod_no = mod_no; -#if 0 - wp_remora_add_event(fe, &event); -#else wp_remora_event_exec(fe, &event); -#endif #endif return 0; } diff --git a/patches/kdrivers/src/net/sdla_remora_tdmv.c b/patches/kdrivers/src/net/sdla_remora_tdmv.c index 1ee0561..23540fe 100644 --- a/patches/kdrivers/src/net/sdla_remora_tdmv.c +++ b/patches/kdrivers/src/net/sdla_remora_tdmv.c @@ -744,6 +744,9 @@ static int wp_tdmv_remora_software_init(wan_tdmv_t *wan_tdmv) } wr->span.pvt = wr; #ifdef DAHDI_ISSUES +#ifdef DAHDI_23 + wr->span.owner = THIS_MODULE; +#endif wr->span.chans = wr->chans_ptrs; #else wr->span.chans = wr->chans; diff --git a/patches/kdrivers/src/net/sdla_tdmv.c b/patches/kdrivers/src/net/sdla_tdmv.c index 1b26f63..6125224 100644 --- a/patches/kdrivers/src/net/sdla_tdmv.c +++ b/patches/kdrivers/src/net/sdla_tdmv.c @@ -284,7 +284,7 @@ static int wp_tdmv_is_rbsbits(wan_tdmv_t *wan_tdmv); static int wp_tdmv_rbsbits_poll(wan_tdmv_t *wan_tdmv, void *card1); static void wp_tdmv_report_rbsbits(void* pcard, int channel, unsigned char status); -static void wp_tdmv_report_alarms(void* pcard, unsigned long te_alarm); +static void wp_tdmv_report_alarms(void* pcard, uint32_t te_alarm); /* Rx/Tx functions */ static int wp_tdmv_rx_tx(void* pcard, netskb_t* skb); @@ -410,8 +410,6 @@ static int wp_tdmv_create(void* pcard, wan_tdmv_conf_t *tdmv_conf) card->wan_tdmv.max_timeslots = GET_TE_CHANNEL_RANGE(&card->fe); card->wan_tdmv.spanno = tdmv_conf->span_no; - card->wandev.te_report_rbsbits = wp_tdmv_report_rbsbits; - card->wandev.te_report_alarms = wp_tdmv_report_alarms; wp = wan_kmalloc(sizeof(wp_tdmv_softc_t)); if (wp == NULL){ @@ -451,6 +449,10 @@ static int wp_tdmv_create(void* pcard, wan_tdmv_conf_t *tdmv_conf) }else{ WAN_LIST_INSERT_HEAD(&wan_tdmv_head, &card->wan_tdmv, next); } + + /* Bind alarms only when wp has been initialized */ + card->wandev.te_report_rbsbits = wp_tdmv_report_rbsbits; + card->wandev.te_report_alarms = wp_tdmv_report_alarms; return 0; } @@ -791,7 +793,7 @@ static void wp_tdmv_report_rbsbits(void* pcard, int channel, unsigned char statu if (!(wp->chans[i].sig & ZT_SIG_CLEAR) && (wp->chans[i].rxsig != rxs)){ zt_rbsbits(&wp->chans[i], rxs); -#if 1 + DEBUG_TDMV( "[TDMV] %s: %s:%02d(%d) RX RBS: A:%1d B:%1d C:%1d D:%1d\n", wp->devname, @@ -801,7 +803,6 @@ static void wp_tdmv_report_rbsbits(void* pcard, int channel, unsigned char statu (rxs & ZT_BBIT) ? 1 : 0, (rxs & ZT_CBIT) ? 1 : 0, (rxs & ZT_DBIT) ? 1 : 0); -#endif } } @@ -810,14 +811,16 @@ static void wp_tdmv_report_rbsbits(void* pcard, int channel, unsigned char statu ** ** DONE */ -static void wp_tdmv_report_alarms(void* pcard, unsigned long te_alarm) +static void wp_tdmv_report_alarms(void* pcard, uint32_t te_alarm) { sdla_t *card = (sdla_t*)pcard; wan_tdmv_t *wan_tdmv = &card->wan_tdmv; wp_tdmv_softc_t *wp = NULL; - int alarms = 0, prev_alarms; + unsigned int alarms = 0, prev_alarms; int x,j; + + /* The sc pointer can be NULL, on shutdown. In this * case don't generate error, just get out */ wp = wan_tdmv->sc; @@ -1138,6 +1141,9 @@ static int wp_tdmv_software_init(wan_tdmv_t *wan_tdmv) wp->span.close = wp_tdmv_close; wp->span.channels = wp->max_timeslots; #ifdef DAHDI_ISSUES +#ifdef DAHDI_23 + wp->span.owner = THIS_MODULE; +#endif wp->span.chans = wp->chans_ptrs; #else wp->span.chans = wp->chans; @@ -1548,6 +1554,7 @@ static int wp_tdmv_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) wp_tdmv_softc_t *wp = NULL; sdla_t *card = NULL; int err = 0; + wan_smp_flag_t smp_flags; WAN_ASSERT2(span == NULL, -ENODEV); WAN_ASSERT2(span->pvt == NULL, -ENODEV); @@ -1583,9 +1590,14 @@ static int wp_tdmv_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) }else{ card->fe.fe_cfg.cfg.te_cfg.sig_mode = WAN_TE1_SIG_CAS; } + + if (card->wandev.fe_iface.reconfig){ + card->hw_iface.hw_lock(card->hw,&smp_flags); card->wandev.fe_iface.reconfig(&card->fe); + card->hw_iface.hw_unlock(card->hw,&smp_flags); } + } span->txlevel = 0; switch(wp->lbo){ @@ -1634,12 +1646,24 @@ static int wp_tdmv_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) span->rxlevel = 0; /* Do we want to SYNC on receive or not */ wp->sync = lc->sync; + /* */ /* If already running, apply changes immediately */ if (span->flags & ZT_FLAG_RUNNING){ err = wp_tdmv_startup(span); } + if (card->wandev.fe_iface.read_alarm) { + u32 alarm; + card->hw_iface.hw_lock(card->hw,&smp_flags); + alarm=card->wandev.fe_iface.read_alarm(&card->fe,WAN_FE_ALARM_READ|WAN_FE_ALARM_UPDATE); + if (card->wandev.te_report_alarms) { + card->wandev.te_report_alarms(card,alarm); + } + card->hw_iface.hw_unlock(card->hw,&smp_flags); + + } + return err; } @@ -1789,7 +1813,11 @@ static int wp_tdmv_is_rbsbits(wan_tdmv_t *wan_tdmv) /****************************************************************************** ** wp_tdmv_rbsbits_poll() - ** -** DONE +** Note: this code MUST run locked with hw_lock. +** The calling code must take the hw_lock because this function +** accesses the front end. +** +** DONE */ static int wp_tdmv_rbsbits_poll(wan_tdmv_t *wan_tdmv, void *card1) @@ -1941,7 +1969,7 @@ static int wp_tdmv_tx_rbsbits(wp_tdmv_softc_t *wp) while ((rbs_skb=wan_skb_dequeue(&wp->rbs_tx_q))) { rbs_pkt=(wp_tdmv_rbs_t*)wan_skb_data(rbs_skb); - DEBUG_TEST("%s: TX RBS HW Chan=%02i Data=0x%02X\n", + DEBUG_TDMV("%s: TX RBS HW Chan=%02i Data=0x%02X\n", wp->devname, rbs_pkt->chan, rbs_pkt->data); card->wandev.fe_iface.set_rbsbits( @@ -2445,6 +2473,12 @@ static void wp_tdmv_tx_hdlc_hard(struct zt_chan *chan) WAN_ASSERT_VOID(wp->dchan_dev == NULL); size = chan->writen[chan->outwritebuf] - chan->writeidx[chan->outwritebuf]-2; + if (!size) { + /* Do not transmit zero length frame */ + zt_hdlc_getbuf(chan, data, &size); + return; + } + skb = wan_skb_alloc(size+1); if (skb == NULL){ return; diff --git a/patches/kdrivers/src/net/sdla_te1.c b/patches/kdrivers/src/net/sdla_te1.c index 6cc38f0..6c160b4 100644 --- a/patches/kdrivers/src/net/sdla_te1.c +++ b/patches/kdrivers/src/net/sdla_te1.c @@ -2247,7 +2247,7 @@ static int sdla_te_global_unconfig(void* pfe); static int sdla_te_config(void* pfe); static int sdla_te_unconfig(void* pfe); static int sdla_te_post_init(void *pfe); -static int sdla_te_pre_release(void* pfe); +static int sdla_te_post_unconfig(void* pfe); static void ClearTemplate(sdla_fe_t* fe); static unsigned char PrgTransmitTemplate(sdla_fe_t* fe); static void InitLineReceiver(sdla_fe_t* fe, RLPS_EQUALIZER_RAM* rlps_table); @@ -3300,7 +3300,7 @@ int sdla_te_iface_init(void *p_fe, void *pfe_iface) fe_iface->post_init = &sdla_te_post_init; fe_iface->reconfig = &sdla_te_reconfig; fe_iface->unconfig = &sdla_te_unconfig; - fe_iface->pre_release = &sdla_te_pre_release; + fe_iface->post_unconfig = &sdla_te_post_unconfig; fe_iface->isr = &sdla_te_intr; fe_iface->disable_irq = &sdla_te_disable_irq; fe_iface->check_isr = &sdla_te_check_intr; @@ -4533,14 +4533,14 @@ static int sdla_te_post_init(void *pfe) /* ****************************************************************************** - * sdla_te_pre_release() + * sdla_te_post_unconfig() * * Description: T1/E1 pre release routines (not locked). * Arguments: * Returns: ****************************************************************************** */ -static int sdla_te_pre_release(void* pfe) +static int sdla_te_post_unconfig(void* pfe) { sdla_fe_t *fe = (sdla_fe_t*)pfe; sdla_fe_timer_event_t *fe_event = NULL; @@ -4764,14 +4764,9 @@ static int sdla_te_global_unconfig(void* pfe) static int sdla_te_unconfig(void* pfe) { sdla_fe_t *fe = (sdla_fe_t*)pfe; - - /* Verify the FE timer is stopped */ - if (!wan_test_bit(TE_TIMER_KILL,(void*)&fe->te_param.critical)){ - DEBUG_EVENT("%s: %s(): Front-End timer is not stopped!\n", - fe->name, __FUNCTION__); - return -EINVAL; - } + wan_set_bit(TE_TIMER_KILL,(void*)&fe->te_param.critical); + if (!wan_test_bit(TE_CONFIGURED,(void*)&fe->te_param.critical)){ return -EINVAL; } diff --git a/patches/kdrivers/src/net/sdla_te3.c b/patches/kdrivers/src/net/sdla_te3.c index f09724a..9a858e3 100644 --- a/patches/kdrivers/src/net/sdla_te3.c +++ b/patches/kdrivers/src/net/sdla_te3.c @@ -92,7 +92,7 @@ static unsigned int sdla_te3_read_alarms(sdla_fe_t *fe, int); static int sdla_te3_read_pmon(sdla_fe_t *fe, int); static int sdla_te3_flush_pmon(sdla_fe_t *fe); static int sdla_te3_post_init(void* pfe); -static int sdla_te3_pre_release(void* pfe); +static int sdla_te3_post_unconfig(void* pfe); static int sdla_te3_update_alarm_info(sdla_fe_t* fe, struct seq_file* m, int* stop_cnt); static int sdla_te3_update_pmon_info(sdla_fe_t* fe, struct seq_file* m, int* stop_cnt); @@ -1189,7 +1189,7 @@ int sdla_te3_iface_init(void *p_fe_iface) fe_iface->config = &sdla_te3_config; fe_iface->unconfig = &sdla_te3_unconfig; fe_iface->post_init = &sdla_te3_post_init; - fe_iface->pre_release = &sdla_te3_pre_release; + fe_iface->post_unconfig = &sdla_te3_post_unconfig; fe_iface->polling = &sdla_te3_polling; fe_iface->isr = &sdla_te3_isr; fe_iface->process_udp = &sdla_te3_udp; @@ -1220,6 +1220,9 @@ static int sdla_te3_config(void *p_fe) card->hw_iface.getcfg(card->hw, SDLA_ADAPTERSUBTYPE, &adptr_subtype); data = READ_REG(0x02); + + + data=0x00; /* configure Line Interface Unit */ if (card->adptr_subtype == AFT_SUBTYPE_NORMAL){ @@ -1295,7 +1298,6 @@ static int sdla_te3_config(void *p_fe) fe->name,fe_cfg->frame); return -EINVAL; } - data |= BIT_OPMODE_INTERNAL_LOS; data |= (BIT_OPMODE_TIMREFSEL1 | BIT_OPMODE_TIMREFSEL0); WRITE_REG(REG_OPMODE, data); @@ -1436,7 +1438,7 @@ static int sdla_te3_post_init(void* pfe) return 0; } -static int sdla_te3_pre_release(void* pfe) +static int sdla_te3_post_unconfig(void* pfe) { sdla_fe_t *fe = (sdla_fe_t*)pfe; @@ -1454,6 +1456,9 @@ static int sdla_te3_pre_release(void* pfe) static int sdla_te3_unconfig(void *p_fe) { sdla_fe_t *fe = (sdla_fe_t*)p_fe; + + wan_set_bit(TE_TIMER_KILL,(void*)&fe->te3_param.critical); + DEBUG_EVENT("%s: Unconfiguring T3/E3 interface\n", fe->name); return 0; diff --git a/patches/kdrivers/src/net/sdla_usb_remora.c b/patches/kdrivers/src/net/sdla_usb_remora.c index 8c8d57f..eeb0ae1 100644 --- a/patches/kdrivers/src/net/sdla_usb_remora.c +++ b/patches/kdrivers/src/net/sdla_usb_remora.c @@ -390,7 +390,7 @@ int wp_usb_init_voicedaa(sdla_fe_t *fe, int mod_no, int fast, int sane); static int wp_usb_remora_config(void *pfe); static int wp_usb_remora_unconfig(void *pfe); static int wp_usb_remora_post_init(void *pfe); -static int wp_usb_remora_pre_release(void* pfe); +static int wp_usb_remora_post_unconfig(void* pfe); static int wp_usb_remora_if_config(void *pfe, u32 mod_map, u8); static int wp_usb_remora_if_unconfig(void *pfe, u32 mod_map, u8); static int wp_usb_remora_disable_irq(void *pfe); @@ -1366,7 +1366,7 @@ int wp_usb_remora_iface_init(void *p_fe, void *pfe_iface) fe_iface->if_config = &wp_usb_remora_if_config; fe_iface->if_unconfig = &wp_usb_remora_if_unconfig; - fe_iface->pre_release = &wp_usb_remora_pre_release; + fe_iface->post_unconfig = &wp_usb_remora_post_unconfig; fe_iface->active_map = &wp_usb_remora_active_map; fe_iface->isr = &wp_usb_remora_intr; @@ -1590,6 +1590,8 @@ static int wp_usb_remora_unconfig(void *pfe) /* Clear and Kill TE timer poll command */ wan_clear_bit(WP_RM_CONFIGURED,(void*)&fe->rm_param.critical); + wan_set_bit(WP_RM_TIMER_KILL,(void*)&fe->rm_param.critical); + for(mod_no = 0; mod_no < MAX_USB_REMORA_MODULES; mod_no++){ if (!wan_test_bit(mod_no, &fe->rm_param.module_map)) continue; if (fe->rm_param.mod[mod_no].type == MOD_TYPE_FXO){ @@ -1602,14 +1604,14 @@ static int wp_usb_remora_unconfig(void *pfe) /* ****************************************************************************** - * sdla_te_pre_release() + * sdla_te_post_unconfig() * * Description: T1/E1 pre release routines (not locked). * Arguments: * Returns: ****************************************************************************** */ -static int wp_usb_remora_pre_release(void* pfe) +static int wp_usb_remora_post_unconfig(void* pfe) { sdla_fe_t *fe = (sdla_fe_t*)pfe; sdla_fe_timer_event_t *fe_event = NULL; @@ -1617,7 +1619,6 @@ static int wp_usb_remora_pre_release(void* pfe) int empty = 0; /* Kill TE timer poll command */ - wan_set_bit(WP_RM_TIMER_KILL,(void*)&fe->rm_param.critical); if (wan_test_bit(WP_RM_TIMER_RUNNING,(void*)&fe->rm_param.critical)){ wan_del_timer(&fe->timer); diff --git a/patches/kdrivers/src/net/sdla_usb_remora_tdmv.c b/patches/kdrivers/src/net/sdla_usb_remora_tdmv.c index 1e5176f..9e17337 100644 --- a/patches/kdrivers/src/net/sdla_usb_remora_tdmv.c +++ b/patches/kdrivers/src/net/sdla_usb_remora_tdmv.c @@ -65,7 +65,7 @@ #define OHT_TIMER 6000 /* How long after RING to retain OHT */ -#define FXO_LINK_DEBOUNCE 200 +#define FXO_LINK_DEBOUNCE 400 /* 200 */ #define MAX_ALARMS 10 @@ -1122,11 +1122,11 @@ static int wp_usb_tdmv_remora_hook(sdla_fe_t *fe, int mod_no, int off_hook) /****************************************************************************** -** wp_usb_tdmv_remora_init() - +** wp_usb_rm_tdmv_init() - ** ** OK */ -int wp_usb_tdmv_remora_init(wan_tdmv_iface_t *iface) +int wp_usb_rm_tdmv_init(wan_tdmv_iface_t *iface) { WAN_ASSERT(iface == NULL); diff --git a/patches/kdrivers/src/net/sdla_xilinx.c b/patches/kdrivers/src/net/sdla_xilinx.c index c337403..081efc3 100644 --- a/patches/kdrivers/src/net/sdla_xilinx.c +++ b/patches/kdrivers/src/net/sdla_xilinx.c @@ -2413,9 +2413,7 @@ static void disable_comm (sdla_t *card) /* TE1 - Unconfiging, only on shutdown */ if (IS_TE1_CARD(card)) { wan_smp_flag_t smp_flags,smp_flags1; - if (card->wandev.fe_iface.pre_release){ - card->wandev.fe_iface.pre_release(&card->fe); - } + card->hw_iface.hw_lock(card->hw,&smp_flags1); wan_spin_lock_irq(&card->wandev.lock, &smp_flags); if (card->wandev.fe_iface.unconfig){ @@ -8029,9 +8027,6 @@ static void aft_critical_shutdown (sdla_t *card) /* TE1 - Unconfiging, only on shutdown */ if (IS_TE1_CARD(card)) { - if (card->wandev.fe_iface.pre_release){ - card->wandev.fe_iface.pre_release(&card->fe); - } if (card->wandev.fe_iface.unconfig){ card->wandev.fe_iface.unconfig(&card->fe); } diff --git a/patches/kdrivers/src/net/sdladrv.c b/patches/kdrivers/src/net/sdladrv.c index 12aedeb..378130a 100644 --- a/patches/kdrivers/src/net/sdladrv.c +++ b/patches/kdrivers/src/net/sdladrv.c @@ -137,6 +137,9 @@ #include "sdlasfm.h" /* SDLA firmware module definitions */ #include "sdlapci.h" /* SDLA PCI hardware definitions */ #include "sdladrv.h" /* API definitions */ +#if defined(CONFIG_PRODUCT_WANPIPE_USB) +# include "sdladrv_usb.h" +#endif #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) @@ -426,6 +429,11 @@ extern u_int8_t __sdla_a600_read_fe (void* phw, ...); extern u_int8_t sdla_a600_read_fe (void* phw, ...); extern void sdla_a600_reset_fe (void* fe); +extern int sdla_b800_write_fe (void* phw, ...); +extern u_int8_t __sdla_b800_read_fe (void* phw, ...); +extern u_int8_t sdla_b800_read_fe (void* phw, ...); +extern void sdla_b800_reset_fe (void* fe); + extern int sdla_shark_bri_write_fe (void* phw, ...); extern u_int8_t sdla_shark_bri_read_fe (void* phw, ...); @@ -457,24 +465,6 @@ extern u_int8_t sdla_usb_fxo_read(void *phw, ...); extern int sdla_plxctrl_read8(void *phw, short, unsigned char*); extern int sdla_plxctrl_write8(void *phw, short, unsigned char); -/*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_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_rxdata(void *phw, unsigned char*, int); -extern int sdla_usb_txdata(void *phw, unsigned char*, int); -extern int sdla_usb_txdata_ready(void *phw); -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*); - - #if defined(CONFIG_PRODUCT_WANPIPE_AFT_B601) extern int sdla_b601_te1_write_fe(void *phw, ...); extern u_int8_t sdla_b601_te1_read_fe (void *phw, ...); @@ -643,10 +633,6 @@ static unsigned char s507_irqmask[] = sdladrv_callback_t sdladrv_callback; EXPORT_SYMBOL(sdladrv_callback); -extern void sdla_usb_init(void); -extern void sdla_usb_exit(void); -extern int sdla_usb_setup(sdlahw_t*); -extern int sdla_usb_down(sdlahw_t*, int force); #endif #if defined(SDLADRV_HW_IFACE) @@ -947,7 +933,7 @@ sdla_save_hw_probe (sdlahw_t* hw, int port) break; case A200_ADPTR_ANALOG: - case A400_ADPTR_ANALOG: + case A400_ADPTR_ANALOG: /*sprintf(tmp_hw_probe->hw_info,*/ SDLA_PROBE_SPRINT(hwprobe->hw_info, sizeof(hwprobe->hw_info), @@ -964,6 +950,9 @@ sdla_save_hw_probe (sdlahw_t* hw, int port) case AFT_ADPTR_A600: #if defined(CONFIG_PRODUCT_WANPIPE_AFT_B601) case AFT_ADPTR_B601: +#endif +#if defined(CONFIG_PRODUCT_WANPIPE_AFT_B800) + case AFT_ADPTR_B800: #endif SDLA_PROBE_SPRINT(hwprobe->hw_info, sizeof(hwprobe->hw_info), @@ -1527,10 +1516,128 @@ sdla_hwdev_Remora_register(sdlahw_cpu_t* hwcpu, int *line_num) sdla_bus_write_4(hw,0x40,reg); sdla_memory_unmap(hw); - return first_hw; } +#if defined (CONFIG_PRODUCT_WANPIPE_AFT_B800) +static sdlahw_t* +sdla_hwdev_b800_register(sdlahw_cpu_t* hwcpu, int *line_num) +{ + sdlahw_t *hw; + sdlahw_t *first_hw = NULL; + u32 reg, reg1; + int mod_no; + int rm_mod_type[NUM_B800_ANALOG_PORTS+2]; + unsigned char value; + //unsigned char str[150]; + int err; + + //memset(str,0,sizeof(str)); + + WAN_ASSERT_RC(hwcpu == NULL, NULL); + *line_num = 0; + + if ((hw = sdla_hw_register(hwcpu, 0)) == NULL){ + return NULL; + } + + if (sdla_memory_map(hw)){ + sdla_hw_unregister(hw); + return NULL; + } + + /* A200 clear reset */ + sdla_bus_read_4(hw, 0x40,®); + wan_set_bit(1,®); + wan_set_bit(2,®); + sdla_bus_write_4(hw,0x40,reg); + + WP_DELAY(10); + + wan_clear_bit(1,®); + wan_clear_bit(2,®); + sdla_bus_write_4(hw,0x40,reg); + + WP_DELAY(10); + + /* Reset SPI for all modules */ + for(mod_no = 0; mod_no < NUM_B800_ANALOG_PORTS; mod_no++) { + reg1 = 0; + reg1 |= (mod_no/4) << 26; + reg1 |= (mod_no%4) << 24; + wan_set_bit(B800_SPI_REG_RESET_BIT, ®1); + + sdla_bus_write_4(hw,SPI_INTERFACE_REG, reg1); + WP_DELAY(1000); + sdla_bus_write_4(hw,SPI_INTERFACE_REG,0x00000000); + WP_DELAY(1000); + } + + + for(mod_no = 0; mod_no < NUM_B800_ANALOG_PORTS; mod_no ++){ + rm_mod_type[mod_no] = MOD_TYPE_NONE; + value = sdla_b800_read_fe(hw, mod_no, MOD_TYPE_FXS, 0, 0); + if ((value & 0x0F) == 0x05){ + rm_mod_type[mod_no] = MOD_TYPE_FXS; + } + } + + /* Reset SPI for all modules */ + for(mod_no = 0; mod_no < NUM_B800_ANALOG_PORTS; mod_no++) { + reg1 = 0; + reg1 |= (mod_no/4) << 26; + reg1 |= (mod_no%4) << 24; + wan_set_bit(B800_SPI_REG_RESET_BIT, ®1); + + sdla_bus_write_4(hw,SPI_INTERFACE_REG, reg1); + WP_DELAY(1000); + sdla_bus_write_4(hw,SPI_INTERFACE_REG,0x00000000); + WP_DELAY(1000); + } + + for(mod_no = 0; mod_no < NUM_B800_ANALOG_PORTS; mod_no ++){ + if (rm_mod_type[mod_no] != MOD_TYPE_NONE) continue; + + /* Confirm this section of code when we receive B800 with FXO modules */ + value = sdla_b800_read_fe(hw, mod_no, MOD_TYPE_FXO, 0, 2); + if (value == 0x03){ + rm_mod_type[mod_no] = MOD_TYPE_FXO; + } + } + + err = sdla_hwdev_register_analog(hwcpu, &first_hw, rm_mod_type, 0, NUM_B800_ANALOG_PORTS); + if (err) { + DEBUG_EVENT("%s: Failed to register FXO/FXS modules\n", hw->devname); + } + if (first_hw == NULL) { + DEBUG_EVENT("%s: No FXO/FXS modules detected\n", hw->devname); + } + + if (first_hw) { + /* the original 'hw' was freed! */ + hw = first_hw; + } + + sprintf(&hw->hwport[hw->max_port_no-1].hwprobe->hw_info_dump[strlen(hw->hwport[hw->max_port_no-1].hwprobe->hw_info_dump)], "|BUS_IF=%s|BRDG=%s", + AFT_PCITYPE_DECODE(hwcpu->hwcard), AFT_PCIBRIDGE_DECODE(hwcpu->hwcard)); + + /* Reset SPI bus */ + sdla_bus_write_4(hw,SPI_INTERFACE_REG,MOD_SPI_RESET); + WP_DELAY(1000); + sdla_bus_write_4(hw,SPI_INTERFACE_REG,0x00000000); + WP_DELAY(1000); + + WP_DELAY(10); + + wan_set_bit(1,®); + wan_set_bit(2,®); + sdla_bus_write_4(hw,0x40,reg); + + sdla_memory_unmap(hw); + return first_hw; +} +#endif + static sdlahw_t* sdla_hwdev_ISDN_register(sdlahw_cpu_t* hwcpu, int *lines_no) { @@ -2040,6 +2147,7 @@ int sdla_get_hw_info(sdlahw_t* hw) switch(hwcard->adptr_type){ case A200_ADPTR_ANALOG: case A400_ADPTR_ANALOG: + case AFT_ADPTR_B800: /* Enable memory access */ sdla_bus_read_4(hw, SDLA_REG_OFF(hwcard, AFT_CHIP_CFG_REG), ®1); reg = reg1; @@ -2614,7 +2722,28 @@ static int sdla_aft_hw_select (sdlahw_card_t* hwcard, int cpu_no, int irq, void* hwcard->core_rev, hwcard->u_pci.bus_no, hwcard->u_pci.slot_no, irq); break; - +#if defined (CONFIG_PRODUCT_WANPIPE_AFT_B800) + case AFT_ADPTR_B800: + hwcard->cfg_type = WANOPT_AFT_ANALOG; + sdla_adapter_cnt.aft_b800_adapters++; + if ((hwcpu = sdla_hwcpu_register(hwcard, cpu_no, irq, dev)) == NULL){ + return 0; + } + if ((hw = sdla_hwdev_b800_register(hwcpu, &lines_no)) == NULL){ + sdla_hwcpu_unregister(hwcpu); + return 0; + } + number_of_cards ++; + DEBUG_EVENT( + "%s: %s %s FXO/FXS card found (%s rev.%X), cpu(s) 1, bus #%d, slot #%d, irq #%d\n", + wan_drvname, + hwcard->adptr_name, + AFT_PCITYPE_DECODE(hwcard), + AFT_CORE_ID_DECODE(hwcard->core_id), + hwcard->core_rev, + hwcard->u_pci.bus_no, hwcard->u_pci.slot_no, irq); + break; +#endif case AFT_ADPTR_ISDN: hwcard->cfg_type = WANOPT_AFT_ISDN; sdla_adapter_cnt.aft_isdn_adapters++; @@ -3046,6 +3175,12 @@ sdla_pci_probe_aft(sdlahw_t *hw, int bus_no, int slot_no, int irq) hwcard->adptr_type = AFT_ADPTR_A600; hwcard->adptr_subtype = AFT_SUBTYPE_SHARK; break; +#if defined (CONFIG_PRODUCT_WANPIPE_AFT_B800) + case AFT_B800_SUBSYS_VENDOR: + hwcard->adptr_type = AFT_ADPTR_B800; + hwcard->adptr_subtype = AFT_SUBTYPE_SHARK; + break; +#endif #if defined (CONFIG_PRODUCT_WANPIPE_AFT_B601) case AFT_B601_SUBSYS_VENDOR: hwcard->adptr_type = AFT_ADPTR_B601; @@ -3077,7 +3212,10 @@ sdla_pci_probe_aft(sdlahw_t *hw, int bus_no, int slot_no, int irq) case AFT_4SERIAL_RS232_SUBSYS_VENDOR: case AFT_A600_SUBSYS_VENDOR: case AFT_B601_SUBSYS_VENDOR: - case A700_SHARK_SUBSYS_VENDOR: +#if defined (CONFIG_PRODUCT_WANPIPE_AFT_B800) + case AFT_B800_SUBSYS_VENDOR: +#endif + case A700_SHARK_SUBSYS_VENDOR: sdla_pcibridge_detect(hwcard); break; } @@ -3562,12 +3700,6 @@ unsigned int sdla_hw_probe(void) #endif unsigned int cardno=0; - //if (!WAN_LIST_EMPTY(&sdlahw_card_head)){ - // DEBUG_EVENT("ADBG> SDLA_HW_PROBE: Number configured cards %d\n", - // cardno); - // return cardno; - //} - tmp_hw = wan_malloc(sizeof(sdlahw_t)); WAN_ASSERT_RC(tmp_hw == NULL, 0); tmp_hwcpu = wan_malloc(sizeof(sdlahw_cpu_t)); @@ -4081,10 +4213,14 @@ sdla_card_register(u8 hw_type, int bus_no, int slot_no, int ioport, char *bus_id case SDLA_PCI_CARD: new_hwcard->u_pci.bus_no = bus_no; new_hwcard->u_pci.slot_no = slot_no; - break; + break; +#if defined(CONFIG_PRODUCT_WANPIPE_USB) case SDLA_USB_CARD: // new_hwcard->u_usb.devnum = bus_no; + sprintf(new_hwcard->name, "sdla-%s", bus_id); + sprintf(new_hwcard->u_usb.bus_id, "%s", bus_id); break; +#endif } wan_spin_lock_init(&new_hwcard->pcard_lock,"wan_hwcard_lock"); wan_spin_lock_init(&new_hwcard->pcard_ec_lock,"wan_hwcard_ec_lock"); @@ -4109,7 +4245,7 @@ sdla_card_unregister(sdlahw_card_t* hwcard) WAN_ASSERT(hwcard == NULL); if (hwcard->internal_used){ - DEBUG_ERROR("%s: Error: This card is still in used (used=%d)!\n", + DEBUG_ERROR("%s: Error: This card is still in use (used=%d)!\n", __FUNCTION__, hwcard->internal_used); sdla_card_info(hwcard); @@ -4669,6 +4805,14 @@ void* sdla_register(sdlahw_iface_t* hw_iface, wandev_conf_t* conf, char* devname hw_iface->fe_write = sdla_shark_rm_write_fe; hw_iface->reset_fe = sdla_a200_reset_fe; break; +#if defined (CONFIG_PRODUCT_WANPIPE_AFT_B800) + case AFT_ADPTR_B800: + hw_iface->fe_read = sdla_b800_read_fe; + hw_iface->__fe_read = __sdla_b800_read_fe; + hw_iface->fe_write = sdla_b800_write_fe; + hw_iface->reset_fe = sdla_b800_reset_fe; + break; +#endif case A300_ADPTR_U_1TE3: hw_iface->fe_read = sdla_te3_read_fe; hw_iface->fe_write = sdla_te3_write_fe; @@ -4738,7 +4882,10 @@ void* sdla_register(sdlahw_iface_t* hw_iface, wandev_conf_t* conf, char* devname case AFT_ADPTR_4SERIAL_RS232: case AFT_ADPTR_A600: #if defined(CONFIG_PRODUCT_WANPIPE_AFT_B601) - case AFT_ADPTR_B601: + case AFT_ADPTR_B601: +#endif +#if defined(CONFIG_PRODUCT_WANPIPE_AFT_B800) + case AFT_ADPTR_B800: #endif DEBUG_EVENT("%s: Found: %s card, CPU %c, PciBus=%d, PciSlot=%d, Port=%d\n", devname, @@ -4760,11 +4907,11 @@ void* sdla_register(sdlahw_iface_t* hw_iface, wandev_conf_t* conf, char* devname break; #if defined(CONFIG_PRODUCT_WANPIPE_USB) - case WANOPT_USB_ANALOG: - DEBUG_EVENT("%s: Found: %s card (%d)\n", - devname, - SDLA_DECODE_CARDTYPE(hwcard->cfg_type), - hw->used); + case WANOPT_USB_ANALOG: + DEBUG_EVENT("%s: Found: %s card, BusId %s\n", + devname, + SDLA_DECODE_CARDTYPE(hwcard->cfg_type), + hwcard->u_usb.bus_id); hwcard->type = SDLA_USB; hw_iface->fe_read = sdla_usb_fxo_read; hw_iface->fe_write = sdla_usb_fxo_write; @@ -4776,9 +4923,10 @@ void* sdla_register(sdlahw_iface_t* hw_iface, wandev_conf_t* conf, char* devname hw_iface->usb_rxevent = sdla_usb_rxevent; hw_iface->usb_rxtx_data_init = sdla_usb_rxtx_data_init; hw_iface->usb_rxdata_enable = sdla_usb_rxdata_enable; - hw_iface->usb_rxdata = sdla_usb_rxdata; - hw_iface->usb_txdata = sdla_usb_txdata; - hw_iface->usb_txdata_ready = sdla_usb_txdata_ready; + hw_iface->usb_fwupdate_enable = sdla_usb_fwupdate_enable; + hw_iface->usb_txdata_raw = sdla_usb_txdata_raw; + hw_iface->usb_txdata_raw_ready = sdla_usb_txdata_raw_ready; + hw_iface->usb_rxdata_raw = sdla_usb_rxdata_raw; hw_iface->usb_err_stats = sdla_usb_err_stats; hw_iface->usb_flush_err_stats = sdla_usb_flush_err_stats; hw_iface->set_intrhand = sdla_usb_set_intrhand; @@ -5223,7 +5371,10 @@ static int sdla_setup (void* phw, wandev_conf_t* conf) case AFT_ADPTR_4SERIAL_RS232: case AFT_ADPTR_A600: #if defined(CONFIG_PRODUCT_WANPIPE_AFT_B601) - case AFT_ADPTR_B601: + case AFT_ADPTR_B601: +#endif +#if defined(CONFIG_PRODUCT_WANPIPE_AFT_B800) + case AFT_ADPTR_B800: #endif if (hwcpu->used > 1){ if (conf) conf->irq = hwcpu->irq; @@ -5237,9 +5388,6 @@ static int sdla_setup (void* phw, wandev_conf_t* conf) #if defined(CONFIG_PRODUCT_WANPIPE_USB) case SDLA_USB: - if (sdla_usb_setup(hw)){ - return -EINVAL; - } return 0; break; #endif @@ -5921,7 +6069,9 @@ static int sdla_down (void* phw) #if defined(CONFIG_PRODUCT_WANPIPE_AFT_B601) case AFT_ADPTR_B601: #endif - +#if defined(CONFIG_PRODUCT_WANPIPE_AFT_B800) + case AFT_ADPTR_B800: +#endif if (hwcpu->used > 1){ break; } @@ -5934,7 +6084,6 @@ static int sdla_down (void* phw) #if defined(CONFIG_PRODUCT_WANPIPE_USB) case SDLA_USB: - sdla_usb_down(hw, 0); break; #endif @@ -7726,6 +7875,9 @@ static int sdla_memory_map(sdlahw_t* hw) case AFT_ADPTR_A600: #if defined(CONFIG_PRODUCT_WANPIPE_AFT_B601) case AFT_ADPTR_B601: +#endif +#if defined(CONFIG_PRODUCT_WANPIPE_AFT_B800) + case AFT_ADPTR_B800: #endif case AFT_ADPTR_FLEXBRI: hwcpu->memory = AFT4_PCI_MEM_SIZE; @@ -8251,6 +8403,9 @@ adapter_found: case A400_ADPTR_ANALOG: case AFT_ADPTR_56K: case AFT_ADPTR_A600: +#if defined (CONFIG_PRODUCT_WANPIPE_AFT_B800) + case AFT_ADPTR_B800: +#endif conf->comm_port = 0; conf->fe_cfg.line_no = 0; break; @@ -9712,6 +9867,14 @@ static int sdla_hw_lock(void *phw, wan_smp_flag_t *flag) hwcpu = hw->hwcpu; hwcard = hwcpu->hwcard; +#ifdef __LINUX__ + if (in_interrupt()) { + if (WAN_NET_RATELIMIT()) { + WARN_ON(1); + DEBUG_ERROR("%s:%d: Error hw_lock taken in interrupt!\n",__FUNCTION__,__LINE__); + } + } +#endif wan_spin_lock(&hw->hwcpu->lines_info[hw->cfg_type].pcard_lock,flag); return 0; @@ -9746,6 +9909,16 @@ static int sdla_hw_ec_trylock(void *phw, wan_smp_flag_t *flag) WAN_ASSERT(hw->hwcpu->hwcard == NULL); hwcpu = hw->hwcpu; hwcard = hwcpu->hwcard; + +#ifdef __LINUX__ + if (in_interrupt()) { + if (WAN_NET_RATELIMIT()) { + WARN_ON(1); + DEBUG_ERROR("%s:%d: Error hw_lock taken in interrupt!\n",__FUNCTION__,__LINE__); + } + } +#endif + return wan_spin_trylock(&hwcard->pcard_ec_lock,flag); } @@ -9761,6 +9934,16 @@ static int sdla_hw_ec_lock(void *phw, wan_smp_flag_t *flag) WAN_ASSERT(hw->hwcpu->hwcard == NULL); hwcpu = hw->hwcpu; hwcard = hwcpu->hwcard; + +#ifdef __LINUX__ + if (in_interrupt()) { + if (WAN_NET_RATELIMIT()) { + WARN_ON(1); + DEBUG_ERROR("%s:%d: Error hw_lock taken in interrupt!\n",__FUNCTION__,__LINE__); + } + } +#endif + wan_spin_lock(&hwcard->pcard_ec_lock,flag); return 0; } @@ -10571,6 +10754,9 @@ static int sdla_hw_read_cpld(void *phw, u16 off, u8 *data) case A400_ADPTR_ANALOG: case AFT_ADPTR_FLEXBRI: case AFT_ADPTR_ISDN: +#if defined (CONFIG_PRODUCT_WANPIPE_AFT_B800) + case AFT_ADPTR_B800: +#endif off &= ~AFT4_BIT_DEV_ADDR_CLEAR; off |= AFT4_BIT_DEV_ADDR_CPLD; /* Save current original address */ @@ -10733,7 +10919,10 @@ static int sdla_hw_write_cpld(void *phw, u16 off, u8 data) case A200_ADPTR_ANALOG: case A400_ADPTR_ANALOG: case AFT_ADPTR_FLEXBRI: - case AFT_ADPTR_ISDN://???? + case AFT_ADPTR_ISDN: +#if defined (CONFIG_PRODUCT_WANPIPE_AFT_B800) + case AFT_ADPTR_B800: +#endif off &= ~AFT4_BIT_DEV_ADDR_CLEAR; off |= AFT4_BIT_DEV_ADDR_CPLD; /* Save current original address */ @@ -10822,6 +11011,7 @@ static int sdla_get_hwec_index(void *phw) return hw->hwcpu->hwcard->hwec_ind; } + #if defined(CONFIG_PRODUCT_WANPIPE_USB) static int sdla_usb_hw_select (sdlahw_card_t*, void*); @@ -10850,21 +11040,17 @@ static int sdla_usb_hw_select (sdlahw_card_t* hwcard, void* dev) return 0; } number_of_cards += 1; - DEBUG_EVENT("%s: %s USB-FXO module found (rev.%X)!\n", - wan_drvname, + DEBUG_EVENT("%s: %s USB-FXO module found (rev.%X), busid:%s\n", + hwcard->name, hwcard->adptr_name, - hwcard->core_rev); - if (sdladrv_callback.add_device){ - sdladrv_callback.add_device(hw->devname, hw); - }else{ - DEBUG_EVENT("WARNING: Undefined add_defice callback function (just loaded)!\n"); - } + hwcard->core_rev, + hwcard->u_usb.bus_id); break; default: DEBUG_EVENT("%s: Unknown USB adapter %04X (Bus Id #%s)!\n", wan_drvname, hwcard->adptr_type, - WP_USB_BUSID(hwcard)); + hwcard->u_usb.bus_id); break; } return number_of_cards; @@ -10873,22 +11059,43 @@ static int sdla_usb_hw_select (sdlahw_card_t* hwcard, void* dev) int sdla_usb_create(struct usb_interface *intf, int adptr_type) { struct usb_device *udev = interface_to_usbdev(intf); - sdlahw_card_t *hwcard = NULL; + sdlahw_card_t *hwcard = NULL; + int new_usbdev = 0; WAN_ASSERT(udev == NULL); DEBUG_EVENT("sdlausb: Attaching sdlausb on %d (BusId %s)\n", udev->devnum, WAN_DEV_NAME(udev)); - hwcard = sdla_card_register(SDLA_USB_CARD, udev->devnum, 0, 0, WAN_DEV_NAME(udev)); + hwcard = sdla_card_search(SDLA_USB_CARD, udev->devnum, 0, 0, WAN_DEV_NAME(udev)); if (hwcard == NULL){ - return 0; + hwcard = sdla_card_register(SDLA_USB_CARD, udev->devnum, 0, 0, WAN_DEV_NAME(udev)); + if (hwcard == NULL){ + return 0; + } + new_usbdev = 1; + }else{ + DEBUG_EVENT("%s: %s USB-FXO module plugged in (rev.%X), busid:%s\n", + hwcard->name, + hwcard->adptr_name, + hwcard->core_rev, + hwcard->u_usb.bus_id); } hwcard->adptr_type = adptr_type; hwcard->u_usb.usb_dev = udev; - hwcard->u_usb.usb_intf = intf; - if (!sdla_usb_hw_select(hwcard, udev)){ + hwcard->u_usb.usb_intf = intf; + + if (sdla_usb_setup(hwcard, new_usbdev)){ + sdla_card_unregister(hwcard); return -EINVAL; } + if (new_usbdev){ + if (!sdla_usb_hw_select(hwcard, udev)){ + return -EINVAL; + } + if (sdladrv_callback.add_device){ + sdladrv_callback.add_device(); + } + } return 0; } @@ -10896,59 +11103,30 @@ int sdla_usb_remove(struct usb_interface *intf, int force) { struct usb_device *udev = interface_to_usbdev(intf); sdlahw_card_t *hwcard = NULL; - sdlahw_cpu_t *hwcpu = NULL; - sdlahw_t *hw = NULL; WAN_ASSERT(intf == NULL); udev = interface_to_usbdev(intf); WAN_ASSERT(udev == NULL); - DEBUG_EVENT("sdlausb: Detaching device from %d (BusId %s)\n", - udev->devnum, WAN_DEV_NAME(udev)); - hwcard = sdla_card_search(SDLA_USB_CARD, udev->devnum, 0, 0, WAN_DEV_NAME(udev)); + hwcard = sdla_card_search(SDLA_USB_CARD, udev->devnum, 0, 0, WAN_DEV_NAME(udev)); if (hwcard == NULL){ DEBUG_EVENT("sdlausb: Failed to find HW USB module!\n"); return -EINVAL; } - hwcpu = sdla_hwcpu_search(SDLA_USB_CARD, udev->devnum, 0, 0, 0, WAN_DEV_NAME(udev)); - if (hwcpu == NULL){ - DEBUG_EVENT("sdlausb: Failed to find HW USB module!\n"); - return -EINVAL; - } - hw = sdla_hw_search(hwcpu, 0); - if (hw == NULL){ - DEBUG_EVENT("sdlausb: Failed to find HW USB device!\n"); - return -EINVAL; - } - if (force){ - if (sdladrv_callback.delete_device){ - sdladrv_callback.delete_device(hw->devname); - }else{ - DEBUG_EVENT("sdlausb: Sangoma USB devices doesn't support hot-plug functionality!\n"); - sdla_usb_down(hw, force); - return 0; - } - } - - if (sdla_hwdev_common_unregister(hwcpu) == -EBUSY){ - DEBUG_EVENT("sdlausb: Failed to unregister HW USB ports!\n"); - return -EINVAL; - } - if (sdla_hwcpu_unregister(hwcpu) == -EBUSY){ - DEBUG_EVENT("sdlausb: Failed to unregister HW USB module!\n"); - return -EINVAL; - } - if (sdla_card_unregister(hwcard) == -EBUSY){ - DEBUG_EVENT("sdlausb: Failed to unregister HW USB card!\n"); - return -EINVAL; - } - sdla_adapter_cnt.usb_adapters--; - DEBUG_EVENT("sdlausb: USB-FXO module on %d detached (BusId %s)\n", - udev->devnum, WAN_DEV_NAME(udev)); + DEBUG_EVENT("%s: Detaching device from %d (BusId %s)\n", + hwcard->name, + udev->devnum, WAN_DEV_NAME(udev)); + + sdla_usb_down(hwcard, 1); + + hwcard->u_usb.usb_dev = NULL; + hwcard->u_usb.usb_intf = NULL; + return 0; } #endif + void _sdla_copy_hwinfo(hardware_info_t *hwinfo, sdlahw_t *hw, sdlahw_cpu_t *hwcpu) { hwinfo->card_model = hwcpu->hwcard->adptr_type; diff --git a/patches/kdrivers/src/net/sdladrv_fe.c b/patches/kdrivers/src/net/sdladrv_fe.c index 8e8c47a..1f8ff22 100644 --- a/patches/kdrivers/src/net/sdladrv_fe.c +++ b/patches/kdrivers/src/net/sdladrv_fe.c @@ -135,6 +135,17 @@ extern int sdla_hw_fe_test_bit(void *phw, int value); extern int sdla_hw_fe_clear_bit(void *phw, int value); extern int sdla_hw_fe_set_bit(void *phw, int value); + +#define SDLA_HW_T1E1_FE_ACCESS_BLOCK { u32 breg; sdla_bus_read_4(hw, 0x40, &breg); \ + if (breg == (u32)-1) { \ + if (WAN_NET_RATELIMIT()) { \ + DEBUG_ERROR("%s:%d: wanpipe PCI Error: Illegal Register read: 0x40 = 0xFFFFFFFF\n", \ + __FUNCTION__,__LINE__); \ + } \ + } \ +} + + /*************************************************************************** **** G L O B A L D A T A **** ***************************************************************************/ @@ -291,21 +302,23 @@ int sdla_te1_write_fe(void* phw, ...) value = va_arg(args, int); va_end(args); + SDLA_HW_T1E1_FE_ACCESS_BLOCK; + off &= ~BIT_DEV_ADDR_CLEAR; - sdla_bus_write_2(hw, XILINX_MCPU_INTERFACE_ADDR, (u16)off); + sdla_bus_write_2(hw, XILINX_MCPU_INTERFACE_ADDR, (u16)off); + /* AF: Sep 10, 2003 * IMPORTANT * This delays are required to avoid bridge optimization * (combining two writes together) */ - if (!qaccess){ - WP_DELAY(5); - } - sdla_bus_write_1(hw, XILINX_MCPU_INTERFACE, (u8)value); - if (!qaccess){ - WP_DELAY(5); - } - return 0; + SDLA_HW_T1E1_FE_ACCESS_BLOCK; + + sdla_bus_write_1(hw, XILINX_MCPU_INTERFACE, (u8)value); + + SDLA_HW_T1E1_FE_ACCESS_BLOCK; + + return 0; } @@ -326,14 +339,18 @@ u_int8_t sdla_te1_read_fe (void* phw, ...) off = va_arg(args, int); va_end(args); - off &= ~BIT_DEV_ADDR_CLEAR; - sdla_bus_write_2(hw, XILINX_MCPU_INTERFACE_ADDR, (u16)off); - sdla_bus_read_1(hw,XILINX_MCPU_INTERFACE, &tmp); + SDLA_HW_T1E1_FE_ACCESS_BLOCK; + + off &= ~BIT_DEV_ADDR_CLEAR; + sdla_bus_write_2(hw, XILINX_MCPU_INTERFACE_ADDR, (u16)off); - if (!qaccess){ - WP_DELAY(5); - } - return tmp; + SDLA_HW_T1E1_FE_ACCESS_BLOCK; + + sdla_bus_read_1(hw,XILINX_MCPU_INTERFACE, &tmp); + + SDLA_HW_T1E1_FE_ACCESS_BLOCK; + + return tmp; } /*************************************************************************** @@ -372,30 +389,31 @@ static int __sdla_shark_te1_write_fe (void *phw, ...) } } + + SDLA_HW_T1E1_FE_ACCESS_BLOCK; + sdla_bus_read_2(hw, AFT_MCPU_INTERFACE_ADDR, (u16*)&org_off); - sdla_bus_write_2(hw,AFT_MCPU_INTERFACE_ADDR, (u16)off); + SDLA_HW_T1E1_FE_ACCESS_BLOCK; + sdla_bus_write_2(hw,AFT_MCPU_INTERFACE_ADDR, (u16)off); + /* AF: Sep 10, 2003 * IMPORTANT * This delays are required to avoid bridge optimization * (combining two writes together) */ - if (!qaccess){ - WP_DELAY(5); - } + SDLA_HW_T1E1_FE_ACCESS_BLOCK; sdla_bus_write_1(hw, AFT_MCPU_INTERFACE, (u8)value); - if (!qaccess){ - WP_DELAY(5); - } - + + SDLA_HW_T1E1_FE_ACCESS_BLOCK; + sdla_bus_write_2(hw, AFT_MCPU_INTERFACE_ADDR, (u16)org_off); - if (!qaccess){ - WP_DELAY(5); - } - return 0; + SDLA_HW_T1E1_FE_ACCESS_BLOCK; + + return 0; } int sdla_shark_te1_write_fe (void *phw, ...) @@ -423,7 +441,7 @@ int sdla_shark_te1_write_fe (void *phw, ...) hw->devname, line_no, off, value); __sdla_shark_te1_write_fe(hw, qaccess, line_no, off, value); sdla_hw_fe_clear_bit(hw,0); - return 0; + return 0; } /*============================================================================ @@ -461,21 +479,26 @@ u_int8_t __sdla_shark_te1_read_fe (void *phw, ...) } } + + SDLA_HW_T1E1_FE_ACCESS_BLOCK; + sdla_bus_read_2(hw, AFT_MCPU_INTERFACE_ADDR, (u16*)&org_off); + SDLA_HW_T1E1_FE_ACCESS_BLOCK; + sdla_bus_write_2(hw, AFT_MCPU_INTERFACE_ADDR, (u16)off); + + SDLA_HW_T1E1_FE_ACCESS_BLOCK; sdla_bus_read_1(hw,AFT_MCPU_INTERFACE, (u8*)&tmp); - if (!qaccess){ - WP_DELAY(5); - } + + SDLA_HW_T1E1_FE_ACCESS_BLOCK; sdla_bus_write_2(hw, AFT_MCPU_INTERFACE_ADDR, (u16)org_off); + + SDLA_HW_T1E1_FE_ACCESS_BLOCK; - if (!qaccess){ - WP_DELAY(5); - } - return (u8)tmp; + return (u8)tmp; } u_int8_t sdla_shark_te1_read_fe (void *phw, ...) @@ -528,15 +551,17 @@ static int __sdla_shark_56k_write_fe (void *phw, ...) va_end(args); off &= ~AFT8_BIT_DEV_ADDR_CLEAR; + + SDLA_HW_T1E1_FE_ACCESS_BLOCK; sdla_bus_write_2(hw,0x46, (u16)off); + + SDLA_HW_T1E1_FE_ACCESS_BLOCK; sdla_bus_write_2(hw,0x44, (u16)value); + + SDLA_HW_T1E1_FE_ACCESS_BLOCK; - if (!qaccess){ - WP_DELAY(5); - } - return 0; } @@ -586,14 +611,16 @@ u_int8_t __sdla_shark_56k_read_fe (void *phw, ...) va_end(args); off &= ~AFT8_BIT_DEV_ADDR_CLEAR; + + SDLA_HW_T1E1_FE_ACCESS_BLOCK; sdla_bus_write_2(hw, AFT56K_MCPU_INTERFACE_ADDR, (u16)off); + + SDLA_HW_T1E1_FE_ACCESS_BLOCK; sdla_bus_read_4(hw, AFT56K_MCPU_INTERFACE, &tmp); - - if (!qaccess){ - WP_DELAY(5); - } + + SDLA_HW_T1E1_FE_ACCESS_BLOCK; return (u_int8_t)tmp; } @@ -736,7 +763,6 @@ int sdla_a600_write_fe(void *phw, ...) u_int8_t __sdla_a600_read_fe (void *phw, ...) { - sdlahw_t *hw = (sdlahw_t*)phw; va_list args; int mod_no, type, chain, reg; @@ -1215,6 +1241,44 @@ void sdla_a600_reset_fe (void *fe) WP_DELAY(1000); } +void sdla_b800_reset_module(sdla_t *card, int mod_no) +{ + u32 reg; + u8 remora_no, module_no; + + remora_no = mod_no/4; + module_no = mod_no%4; + + reg = 0x00; + reg |= (module_no & 0x3) << 24; + reg |= (remora_no & 0x3) << 26; + reg |= 1<< B800_SPI_REG_RESET_BIT; + + card->hw_iface.bus_write_4(card->hw, SPI_INTERFACE_REG, reg); + + WP_DELAY(1000); + card->hw_iface.bus_write_4(card->hw, SPI_INTERFACE_REG, 0x00000000); + WP_DELAY(1000); +} + +void sdla_b800_reset_fe (void *fe) +{ + int i; + sdla_t *card; + + WAN_ASSERT1(fe == NULL); + card = (sdla_t*)((sdla_fe_t*)fe)->card; + + WAN_ASSERT1(card == NULL); + + /* reset all modules together for now until we have the ability/need + reset 1 module at a time from driver core */ + for (i=0;ihwcpu == NULL); + WAN_ASSERT(hw->hwcpu->hwcard == NULL); + + va_start(args, phw); + mod_no = va_arg(args, int); + type = va_arg(args, int); + chain = va_arg(args, int); + reg = va_arg(args, int); + value = va_arg(args, int); + va_end(args); + + if (chain) DEBUG_ERROR ("%s :%d Error: chain mode not supported on A600 (%s:%d)\n", + hw->devname, mod_no, __FUNCTION__,__LINE__); + + remora_no = mod_no/4; + module_no = mod_no%4; + + data |= (module_no & 0x3) << 24; + data |= (remora_no & 0x3) << 26; + data &= 0xFF000000; + + if (type == MOD_TYPE_FXO) { + /* Clear data bits */ + data |= (value & 0xFF); + data |= (reg & 0xFF) << 8; + } else if (type == MOD_TYPE_FXS) { + wan_set_bit(B800_SPI_REG_CHAN_TYPE_FXS_BIT, &data); + /* Clear data bits */ + data |= (value & 0xFF); + data |= (reg & 0x7F) << 8; + } else { + DEBUG_EVENT("%s: Module %d: Unsupported module type %d!\n", + hw->devname, mod_no, type); + return -EINVAL; + } + + sdla_bus_write_4(hw, SPI_INTERFACE_REG, data); + + WP_DELAY(10); + + wan_set_bit(B800_SPI_REG_START_BIT, &data); + sdla_bus_write_4(hw, SPI_INTERFACE_REG, data); + + for (i=0;i<10;i++) { + WP_DELAY(10); + sdla_bus_read_4(hw, SPI_INTERFACE_REG,&data); + if (!(wan_test_bit(B800_SPI_REG_SPI_BUSY_BIT, &data))) { + goto spi_write_done; + } + } + + if (wan_test_bit(B800_SPI_REG_SPI_BUSY_BIT, &data)) { + DEBUG_ERROR("%s: ERROR:SPI Iface not ready\n", hw->devname); + return -EINVAL; + } + +spi_write_done: + return 0; +} + + +int sdla_b800_write_fe(void* phw, ...) +{ + sdlahw_t *hw = (sdlahw_t*)phw; + va_list args; + int mod_no, type, chain, reg, value; +#if defined(WAN_DEBUG_FE) + char *fname; + int fline; +#endif + + WAN_ASSERT(hw->magic != SDLADRV_MAGIC); + va_start(args, phw); + mod_no = va_arg(args, int); + type = va_arg(args, int); + chain = va_arg(args, int); + reg = va_arg(args, int); + value = va_arg(args, int); +#if defined(WAN_DEBUG_FE) + fname = va_arg(args, char*); + fline = va_arg(args, int); +#endif + va_end(args); + + if (sdla_hw_fe_test_and_set_bit(hw,0)){ +#if defined(WAN_DEBUG_FE) + DEBUG_ERROR("%s: %s:%d: Critical Error: Re-entry in FE (%s:%d)!\n", + hw->devname, __FUNCTION__,__LINE__, fname, fline); +#else + DEBUG_ERROR("%s: %s:%d: Critical Error: Re-entry in FE!\n", + hw->devname, __FUNCTION__,__LINE__); +#endif + return -EINVAL; + } + + DEBUG_REG("%s: Remora Direct Register %d = %02X\n", + hw->devname, reg, value); + + __sdla_b800_write_fe(hw, mod_no, type, chain, reg, value); + + sdla_hw_fe_clear_bit(hw,0); + return 0; +} + static int __sdla_shark_rm_write_fe (void* phw, ...) { sdlahw_t *hw = (sdlahw_t*)phw; @@ -1431,6 +1612,119 @@ int sdla_shark_rm_write_fe (void* phw, ...) return 0; } +u_int8_t __sdla_b800_read_fe (void* phw, ...) +{ + sdlahw_t *hw = (sdlahw_t*)phw; + va_list args; + int mod_no, type, chain, reg; + u8 module_no, remora_no; + u32 data = 0; + int i; + + WAN_ASSERT(hw == NULL); + WAN_ASSERT(hw->hwcpu == NULL); + WAN_ASSERT(hw->hwcpu->hwcard == NULL); + + va_start(args, phw); + mod_no = va_arg(args, int); + type = va_arg(args, int); + chain = va_arg(args, int); + reg = va_arg(args, int); + va_end(args); + + remora_no = mod_no/4; + module_no = mod_no%4; + + if (chain) { + DEBUG_ERROR ("%s :%d Error: chain mode not supported on B800 (%s:%d)\n", hw->devname, mod_no, __FUNCTION__,__LINE__); + WARN_ON(1); + } + + wan_set_bit(B800_SPI_REG_READ_ENABLE_BIT, &data); + + data |= (module_no & 0x3) << 24; + data |= (remora_no & 0x3) << 26; + data &= 0xFF000000; + + if (type == MOD_TYPE_FXO) { + data |= (reg & 0xFF) << 8; + data &= 0xFFFFFF00; + } else if (type == MOD_TYPE_FXS) { + wan_set_bit(B800_SPI_REG_CHAN_TYPE_FXS_BIT, &data); + data |= (reg & 0x7F) << 8; + data &= 0xFFFFFF00; + } else { + DEBUG_EVENT("%s: Module %d: Unsupported module type %d!\n", + hw->devname, mod_no, type); + return 0xFF; + } + + sdla_bus_write_4(hw, SPI_INTERFACE_REG, data); + WP_DELAY(10); + + wan_set_bit(B800_SPI_REG_START_BIT, &data); + sdla_bus_write_4(hw, SPI_INTERFACE_REG, data); + + + for (i=0;i<10;i++) { + WP_DELAY(10); + sdla_bus_read_4(hw, SPI_INTERFACE_REG,&data); + + if (!(wan_test_bit(B800_SPI_REG_SPI_BUSY_BIT, &data))) { + goto spi_read_done; + } + } + +spi_read_done: + if (wan_test_bit(B800_SPI_REG_SPI_BUSY_BIT, &data)) { + DEBUG_ERROR("%s: ERROR:SPI Iface not ready\n", hw->devname); + data = 0xFF; + } + + return (u8)(data & 0xFF); +} + +u_int8_t sdla_b800_read_fe (void* phw, ...) +{ + sdlahw_t *hw = (sdlahw_t*)phw; + va_list args; + int mod_no, type, chain, reg; + unsigned char data = 0; +#if defined(WAN_DEBUG_FE) + char *fname; + int fline; +#endif + + WAN_ASSERT(hw->magic != SDLADRV_MAGIC); + va_start(args, phw); + mod_no = va_arg(args, int); + type = va_arg(args, int); + chain = va_arg(args, int); + reg = va_arg(args, int); +#if defined(WAN_DEBUG_FE) + fname = va_arg(args, char*); + fline = va_arg(args, int); +#endif + va_end(args); + + if (sdla_hw_fe_test_and_set_bit(hw,0)){ +#if defined(WAN_DEBUG_FE) + DEBUG_ERROR("%s: %s:%d: Critical Error: Re-entry in FE (%s:%d)!\n", + hw->devname, __FUNCTION__,__LINE__,fname,fline); +#else + DEBUG_ERROR("%s: %s:%d: Critical Error: Re-entry in FE!\n", + hw->devname, __FUNCTION__,__LINE__); +#endif + return 0x00; + } + data = __sdla_b800_read_fe (hw, mod_no, type, chain, reg); + //DEBUG_REG("%s: Remora Read Reg %X = %02X\n", + // hw->devname, reg, data); + + sdla_hw_fe_clear_bit(hw,0); + return data; +} + u_int8_t __sdla_shark_rm_read_fe (void* phw, ...) { sdlahw_t *hw = (sdlahw_t*)phw; @@ -2116,10 +2410,17 @@ static int __sdla_b601_te1_write_fe(void *phw, ...) data_hi |= 0x4000; } + SDLA_HW_T1E1_FE_ACCESS_BLOCK; + data_hi |= (off & 0x7FF); sdla_bus_write_2(hw, A600_MAXIM_INTERFACE_REG_ADD_HI, data_hi); - data_lo = (value & 0xFF); + + SDLA_HW_T1E1_FE_ACCESS_BLOCK; + + data_lo = (value & 0xFF); sdla_bus_write_2(hw, A600_MAXIM_INTERFACE_REG_ADD_LO, data_lo); + + SDLA_HW_T1E1_FE_ACCESS_BLOCK; return 0; } @@ -2185,10 +2486,17 @@ u_int8_t __sdla_b601_te1_read_fe (void *phw, ...) data_hi |= 0x4000; } - data_hi |= (off & 0x7FF); + SDLA_HW_T1E1_FE_ACCESS_BLOCK; + + data_hi |= (off & 0x7FF); sdla_bus_write_2(hw, A600_MAXIM_INTERFACE_REG_ADD_HI, data_hi); - data_read = 0x00; + + SDLA_HW_T1E1_FE_ACCESS_BLOCK; + + data_read = 0x00; sdla_bus_read_4(hw, A600_MAXIM_INTERFACE_REG_ADD_LO, &data_read); + + SDLA_HW_T1E1_FE_ACCESS_BLOCK; return (data_read & 0xFF); } diff --git a/patches/kdrivers/src/net/sdladrv_usb.c b/patches/kdrivers/src/net/sdladrv_usb.c index 32cbf36..fe6b518 100644 --- a/patches/kdrivers/src/net/sdladrv_usb.c +++ b/patches/kdrivers/src/net/sdladrv_usb.c @@ -31,18 +31,13 @@ # include # include # include -# include -# include -# include -# include -# include /* Socket Driver common area */ -# include -# include -# include -# include +# include "wanpipe.h" +# include "sdlapci.h" +# include "sdladrv_usb.h" #endif #if defined(CONFIG_PRODUCT_WANPIPE_USB) + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) # include #else @@ -55,8 +50,11 @@ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,19) #define USB2420 #endif + #define LINUX26 +#define SDLA_USBFXO_BL_DELAY (10) // ms + #define WP_USB_RXTX_DATA_LEN 8 #define WP_USB_RXTX_DATA_COUNT 2 // Original 2 #define WP_USB_MAX_RW_COUNT 100 @@ -66,57 +64,13 @@ #define SDLA_USBFXO_VID 0x10C4 #define SDLA_USBFXO_PID 0x8461 -#define SDLA_USBFXO_READ_DELAY 100 +#define SDLA_USBFXO_SYNC_DELAY 10 +#define SDLA_USBFXO_SYNC_RX_RETRIES 100 +#define SDLA_USBFXO_SYNC_TX_RETRIES 400 +#define SDLA_USBFXO_READ_DELAY 10 +#define SDLA_USBFXO_READ_RETRIES 100 #define SDLA_USBFXO_WRITE_DELAY 10 -/* Internal USB-FXO CPU registers */ -#define SDLA_USB_CPU_REG_DEVICEID 0x00 - -#define SDLA_USB_CPU_REG_HARDWAREVER 0x01 - -#define SDLA_USB_CPU_REG_FIRMWAREVER 0x02 - -#define SDLA_USB_CPU_REG_CONRTOL 0x03 -#define SDLA_USB_CPU_BIT_CONRTOL_TS1_EVENT_EN 0x02 -#define SDLA_USB_CPU_BIT_CONRTOL_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 WP_USB_BAUD_RATE 500000 #define WP_USB_IDLE_PATTERN 0x7E @@ -147,13 +101,14 @@ unsigned char idlebuf[]= 0x57, 0xCF, 0xCF, 0x8E }; -#define WP_USB_STATUS_READY 1 -#define WP_USB_STATUS_TX_READY 2 -#define WP_USB_STATUS_RX_EVENT1_READY 3 -#define WP_USB_STATUS_RX_EVENT2_READY 4 -#define WP_USB_STATUS_RX_DATA_READY 5 -#define WP_USB_STATUS_BH 6 -#define WP_USB_STATUS_TX_CMD 7 +#define WP_USB_STATUS_ATTACHED 1 +#define WP_USB_STATUS_READY 2 +#define WP_USB_STATUS_TX_READY 3 +#define WP_USB_STATUS_RX_EVENT1_READY 4 +#define WP_USB_STATUS_RX_EVENT2_READY 5 +#define WP_USB_STATUS_RX_DATA_READY 6 +#define WP_USB_STATUS_BH 7 +#define WP_USB_STATUS_TX_CMD 8 #define WP_USB_CMD_TYPE_MASK 0x1C #define WP_USB_CMD_TYPE_SHIFT 2 @@ -192,6 +147,35 @@ unsigned char idlebuf[]= *((buf)+2) |= ((ctrl) & 0x0C) << 4; \ *((buf)+3) |= ((ctrl) & 0x03) << 6; #endif + +#define WP_USB_GUARD1_CHECK(hwcard) if(hwcard){ \ + if (hwcard->u_usb.guard1[0]){\ + DEBUG_EVENT("%s: Memory problem guard1 %d (%s:%d)!\n",\ + hwcard->name, 0, __FUNCTION__,__LINE__);\ + hwcard->u_usb.guard1[0]=0x00;\ + }\ + } + +#define WP_USB_GUARD1(hwcard) if(hwcard){ \ + int i=0;\ + for(i=0;i<1000;i++){\ + if (hwcard->u_usb.guard1[i]){\ + DEBUG_EVENT("%s: Memory problem guard1 %d (%s:%d)!\n",\ + hwcard->name, i, __FUNCTION__,__LINE__);\ + }\ + }\ + } + +#define WP_USB_GUARD2(hwcard) if (hwcard){ \ + int i=0;\ + for(i=0;i<1000;i++){\ + if (hwcard->u_usb.guard2[i]){\ + DEBUG_EVENT("%s: Memory problem guard2 %d (%s:%d)!\n",\ + hwcard->name, i, __FUNCTION__,__LINE__);\ + }\ + }\ + } + /*************************************************************************** **** S T R U C T U R E S T Y P E D E F S **** ***************************************************************************/ @@ -218,7 +202,7 @@ static void sdla_usb_disconnect(struct usb_interface*); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) static int sdla_usb_suspend (struct usb_interface*, pm_message_t); #else -static int sdla_usb_suspend (struct usb_interface*, u32 msg); +static int sdla_usb_suspend (struct usb_interface*, u32); #endif static int sdla_usb_resume (struct usb_interface*); #if 0 @@ -232,26 +216,26 @@ int sdla_usb_cpu_read(void *phw, unsigned char off, unsigned char *data); int sdla_usb_cpu_write(void *phw, unsigned char off, unsigned char data); int sdla_usb_write_poll(void *phw, unsigned char off, unsigned char data); int sdla_usb_read_poll(void *phw, unsigned char off, unsigned char *data); +int sdla_usb_hwec_enable(void *phw, int mod_no, int enable); int sdla_usb_rxevent_enable(void *phw, int mod_no, int enable); int sdla_usb_rxevent(void *phw, int mod_no, u8 *regs, int); int sdla_usb_rxtx_data_init(void *phw, int, unsigned char **, unsigned char **); int sdla_usb_rxdata_enable(void *phw, int enable); -int sdla_usb_rxdata(void *phw, unsigned char*, int); -int sdla_usb_txdata(void *phw, unsigned char*, int); -int sdla_usb_txdata_ready(void *phw); int sdla_usb_set_intrhand(void* phw, wan_pci_ifunc_t *isr_func, void* arg, int notused); int sdla_usb_restore_intrhand(void* phw, int notused); int sdla_usb_err_stats(void*,void*,int); -//int sdla_usb_rxdata_ready(void *phw, int mod_no); -//netskb_t* sdla_usb_rxdata(void *phw, int mod_no); -//int sdla_usb_txdata(void *phw, netskb_t*, in t mod_no); #if defined(__LINUX__) static void sdla_usb_bh (unsigned long); #else static void sdla_usb_bh (void*,int); #endif + +static int sdla_usb_rxdata_get(sdlahw_card_t*, unsigned char*, int); +static int sdla_usb_txdata_prepare(sdlahw_card_t*, char*, int); static int wp_usb_start_transfer(struct wan_urb*); +static int sdla_usb_rxurb_reset(sdlahw_card_t *hwcard); +static int sdla_usb_txurb_reset(sdlahw_card_t *hwcard); /*************************************************************************** **** G L O B A L V A R I A B L E **** @@ -370,8 +354,8 @@ static int sdla_usb_probe(struct usb_interface *intf, const struct usb_device_id SDLA_USB_NAME, desc->name, desc->adptr_type, udev->devnum); if (sdla_usb_create(intf, desc->adptr_type)){ - DEBUG_ERROR("ERROR: %s: Failed to creae hwcard structures\n", - SDLA_USB_NAME); + DEBUG_ERROR("ERROR: %s: Failed to probe new device on %d!\n", + SDLA_USB_NAME, udev->devnum); return -ENODEV; } return 0; @@ -386,7 +370,6 @@ static void sdla_usb_disconnect(struct usb_interface *intf) DEBUG_EVENT("%s: Disconnect USB from %d ...\n", SDLA_USB_NAME, dev->devnum); if ((hwcard = usb_get_intfdata(intf)) != NULL){ - DEBUG_EVENT("WARNING: Force to remove usb device!\n"); wan_clear_bit(WP_USB_STATUS_READY, &hwcard->u_usb.status); force = 1; } @@ -395,23 +378,17 @@ static void sdla_usb_disconnect(struct usb_interface *intf) return; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) static int sdla_usb_suspend (struct usb_interface *intf, pm_message_t message) -{ - struct usb_device *dev = interface_to_usbdev(intf); - DEBUG_EVENT("%s: Suspend USB device on %d (not implemented)!\n", - SDLA_USB_NAME, dev->devnum); - return 0; -} #else -static int sdla_usb_suspend (struct usb_interface *intf, u32 msg) +static int sdla_usb_suspend (struct usb_interface *intf, u32 message) +#endif { struct usb_device *dev = interface_to_usbdev(intf); DEBUG_EVENT("%s: Suspend USB device on %d (not implemented)!\n", SDLA_USB_NAME, dev->devnum); return 0; } -#endif static int sdla_usb_resume (struct usb_interface *intf) { @@ -440,15 +417,15 @@ static void sdla_usb_postreset (struct usb_interface *intf) /*************************************************************************** ***************************************************************************/ -static void wait_just_a_bit(int foo, int fast) +static void wait_just_a_bit(int ms, int fast) { #if defined(__FreeBSD__) || defined(__OpenBSD__) WP_SCHEDULE(foo, "A-USB"); #else - wan_ticks_t start_ticks; - start_ticks = SYSTEM_TICKS + foo; - while(SYSTEM_TICKS < start_ticks){ + wan_ticks_t start_ticks = SYSTEM_TICKS; + int delay_ticks = (HZ*ms)/1000; + while((SYSTEM_TICKS-start_ticks) < delay_ticks){ WP_DELAY(1); # if defined(__LINUX__) if (!fast) WP_SCHEDULE(foo, "A-USB"); @@ -457,144 +434,81 @@ static void wait_just_a_bit(int foo, int fast) #endif } -static u_int8_t __sdla_usb_fxo_read(void *phw, int mod_no, unsigned char off) +static u_int8_t __sdla_usb_fxo_read(sdlahw_card_t *hwcard, int mod_no, unsigned char off) { - sdlahw_t *hw = (sdlahw_t*)phw; - sdlahw_card_t *hwcard = NULL; + sdlahw_usb_t *hwusb = NULL; netskb_t *skb; + int retry = 0; u8 data = 0xFF, *cmd_data; wan_smp_flag_t flags; - WAN_ASSERT_RC(hw == NULL, 0xFF); - SDLA_MAGIC(hw); - WAN_ASSERT_RC(hw->hwcpu == NULL, 0xFF); - WAN_ASSERT_RC(hw->hwcpu->hwcard == NULL, 0xFF); - hwcard = hw->hwcpu->hwcard; - - wan_spin_lock(&hwcard->u_usb.cmd_lock,&flags); + data = 0xFF; + hwusb = &hwcard->u_usb; + wan_spin_lock(&hwusb->cmd_lock, &flags); DEBUG_TX("%s: Tx Read FXO register (%02X:%d)!\n", - hw->devname, + hwcard->name, WP_USB_CMD_TYPE_ENCODE(WP_USB_CMD_TYPE_READ_FXO) | mod_no, (unsigned char)off); - if (wan_test_and_set_bit(WP_USB_STATUS_TX_CMD, &hwcard->u_usb.status)){ + if (wan_test_and_set_bit(WP_USB_STATUS_TX_CMD, &hwusb->status)){ DEBUG_USB("%s: WARNING: USB FXO Read Command Overrun (Read command in process)!\n", - hw->devname); - hwcard->u_usb.stats.cmd_overrun++; + hwcard->name); + hwusb->stats.cmd_overrun++; goto fxo_read_done; } - if (!wan_skb_queue_len(&hwcard->u_usb.tx_cmd_free_list)){ + if (!wan_skb_queue_len(&hwusb->tx_cmd_free_list)){ DEBUG_USB("%s: WARNING: USB FXO Read Command Overrun (%d commands in process)!\n", - hw->devname, wan_skb_queue_len(&hwcard->u_usb.tx_cmd_list)); - hwcard->u_usb.stats.cmd_overrun++; + hwcard->name, wan_skb_queue_len(&hwusb->tx_cmd_list)); + hwusb->stats.cmd_overrun++; goto fxo_read_done; } - skb = wan_skb_dequeue(&hwcard->u_usb.tx_cmd_free_list); + skb = wan_skb_dequeue(&hwusb->tx_cmd_free_list); cmd_data = wan_skb_put(skb, 2); cmd_data[0] = WP_USB_CMD_TYPE_ENCODE(WP_USB_CMD_TYPE_READ_FXO) | mod_no; cmd_data[1] = off; - wan_skb_queue_tail(&hwcard->u_usb.tx_cmd_list, skb); + wan_skb_queue_tail(&hwusb->tx_cmd_list, skb); - wait_just_a_bit(SDLA_USBFXO_READ_DELAY, gl_usb_rw_fast); //WP_DELAY(10000); - - if (!wan_skb_queue_len(&hwcard->u_usb.rx_cmd_list)){ + do { + wait_just_a_bit(SDLA_USBFXO_READ_DELAY, 1); //WP_DELAY(10000); + if (++retry > SDLA_USBFXO_READ_RETRIES) break; + } while(!wan_skb_queue_len(&hwusb->rx_cmd_list)); + if (!wan_skb_queue_len(&hwusb->rx_cmd_list)){ DEBUG_USB("%s: WARNING: Timeout on Read USB-FXO Reg!\n", - hw->devname); - hwcard->u_usb.stats.cmd_timeout++; + hwcard->name); + hwusb->stats.cmd_timeout++; goto fxo_read_done; - } - skb = wan_skb_dequeue(&hwcard->u_usb.rx_cmd_list); + } + + skb = wan_skb_dequeue(&hwusb->rx_cmd_list); cmd_data = wan_skb_data(skb); if (cmd_data[1] != off){ DEBUG_USB("%s: USB FXO Read response is out of order (%02X:%02X)!\n", - hw->devname, cmd_data[1], off); - hwcard->u_usb.stats.cmd_invalid++; + hwcard->name, cmd_data[1], off); + hwusb->stats.cmd_invalid++; goto fxo_read_done; } data = (unsigned char)cmd_data[2]; wan_skb_init(skb, 0); - wan_skb_queue_tail(&hwcard->u_usb.rx_cmd_free_list, skb); + wan_skb_queue_tail(&hwusb->rx_cmd_free_list, skb); fxo_read_done: - wan_clear_bit(WP_USB_STATUS_TX_CMD, &hwcard->u_usb.status); - wan_spin_unlock(&hwcard->u_usb.cmd_lock,&flags); + wan_clear_bit(WP_USB_STATUS_TX_CMD, &hwusb->status); + wan_spin_unlock(&hwusb->cmd_lock, &flags); return data; } u_int8_t sdla_usb_fxo_read(void *phw, ...) -{ - sdlahw_t* hw = (sdlahw_t*)phw; - va_list args; - int mod_no, off, data; - - WAN_ASSERT(hw == NULL); - SDLA_MAGIC(hw); - if (sdla_hw_fe_test_and_set_bit(hw,0)){ - if (WAN_NET_RATELIMIT()){ - DEBUG_EVENT( - "%s: %s:%d: Critical Error: Re-entry in FE!\n", - hw->devname, - __FUNCTION__,__LINE__); - } - return -EINVAL; - } - va_start(args, phw); - mod_no = va_arg(args, int); - off = va_arg(args, int); - data = va_arg(args, int); - va_end(args); - - data = __sdla_usb_fxo_read(hw, mod_no, (unsigned char)off); - sdla_hw_fe_clear_bit(hw,0); - return data; -} - -static int __sdla_usb_fxo_write(void *phw, int mod_no, unsigned char off, unsigned char data) { sdlahw_t *hw = (sdlahw_t*)phw; sdlahw_card_t *hwcard = NULL; - netskb_t *skb; - u8 *cmd_data; - wan_smp_flag_t flags; + va_list args; + int mod_no, off, data; WAN_ASSERT(hw == NULL); SDLA_MAGIC(hw); WAN_ASSERT(hw->hwcpu == NULL); WAN_ASSERT(hw->hwcpu->hwcard == NULL); hwcard = hw->hwcpu->hwcard; - wan_spin_lock(&hwcard->u_usb.cmd_lock,&flags); - DEBUG_TX("%s: Tx Write FXO register (%02X: %d <- 0x%02X)!\n", - hw->devname, - WP_USB_CMD_TYPE_ENCODE(WP_USB_CMD_TYPE_WRITE_FXO) | mod_no, - (unsigned char)off, (unsigned char)data); - if (!wan_skb_queue_len(&hwcard->u_usb.tx_cmd_free_list)){ - DEBUG_USB("%s: WARNING: USB FXO Write Command Overrun (%d commands in process)!\n", - hw->devname, wan_skb_queue_len(&hwcard->u_usb.tx_cmd_list)); - hwcard->u_usb.stats.cmd_overrun++; - wan_spin_unlock(&hwcard->u_usb.cmd_lock,&flags); - return 0; - } - skb = wan_skb_dequeue(&hwcard->u_usb.tx_cmd_free_list); - cmd_data = wan_skb_put(skb, 3); - cmd_data[0] = WP_USB_CMD_TYPE_ENCODE(WP_USB_CMD_TYPE_WRITE_FXO) | mod_no; - cmd_data[1] = off; - cmd_data[2] = data; - wan_skb_queue_tail(&hwcard->u_usb.tx_cmd_list, skb); - - /* update mirror registers */ - hwcard->u_usb.regs[mod_no][off] = data; - - wan_spin_unlock(&hwcard->u_usb.cmd_lock,&flags); - return 0; -} -int sdla_usb_fxo_write(void *phw, ...) -{ - sdlahw_t* hw = (sdlahw_t*)phw; - va_list args; - int mod_no, off, err, data; - - WAN_ASSERT(hw == NULL); - SDLA_MAGIC(hw); if (sdla_hw_fe_test_and_set_bit(hw,0)){ if (WAN_NET_RATELIMIT()){ DEBUG_EVENT( @@ -610,8 +524,153 @@ int sdla_usb_fxo_write(void *phw, ...) data = va_arg(args, int); va_end(args); - err = __sdla_usb_fxo_write(hw, mod_no, (unsigned char)off, (unsigned char)data); + data = __sdla_usb_fxo_read(hwcard, mod_no, (unsigned char)off); sdla_hw_fe_clear_bit(hw,0); + return data; +} + +static int __sdla_usb_fxo_write(sdlahw_card_t *hwcard, int mod_no, unsigned char off, unsigned char data) +{ + sdlahw_usb_t *hwusb; + netskb_t *skb; + u8 *cmd_data; + wan_smp_flag_t flags; + + hwusb = &hwcard->u_usb; + wan_spin_lock(&hwusb->cmd_lock, &flags); + DEBUG_TX("%s: Tx Write FXO register (%02X: %d <- 0x%02X)!\n", + hwcard->name, + WP_USB_CMD_TYPE_ENCODE(WP_USB_CMD_TYPE_WRITE_FXO) | mod_no, + (unsigned char)off, (unsigned char)data); + if (!wan_skb_queue_len(&hwusb->tx_cmd_free_list)){ + DEBUG_USB("%s: WARNING: USB FXO Write Command Overrun (%d commands in process)!\n", + hwcard->name, wan_skb_queue_len(&hwusb->tx_cmd_list)); + hwusb->stats.cmd_overrun++; + wan_spin_unlock(&hwusb->cmd_lock, &flags); + return 0; + } + skb = wan_skb_dequeue(&hwusb->tx_cmd_free_list); + cmd_data = wan_skb_put(skb, 3); + cmd_data[0] = WP_USB_CMD_TYPE_ENCODE(WP_USB_CMD_TYPE_WRITE_FXO) | mod_no; + cmd_data[1] = off; + cmd_data[2] = data; + wan_skb_queue_tail(&hwusb->tx_cmd_list, skb); + + /* update mirror registers */ + hwusb->regs[mod_no][off] = data; + + wan_spin_unlock(&hwusb->cmd_lock, &flags); + return 0; +} +int sdla_usb_fxo_write(void *phw, ...) +{ + sdlahw_t *hw = (sdlahw_t*)phw; + sdlahw_card_t *hwcard = NULL; + va_list args; + int mod_no, off, err, data; + + WAN_ASSERT(hw == NULL); + SDLA_MAGIC(hw); + WAN_ASSERT(hw->hwcpu == NULL); + WAN_ASSERT(hw->hwcpu->hwcard == NULL); + hwcard = hw->hwcpu->hwcard; + if (sdla_hw_fe_test_and_set_bit(hw,0)){ + if (WAN_NET_RATELIMIT()){ + DEBUG_EVENT( + "%s: %s:%d: Critical Error: Re-entry in FE!\n", + hw->devname, + __FUNCTION__,__LINE__); + } + return -EINVAL; + } + va_start(args, phw); + mod_no = va_arg(args, int); + off = va_arg(args, int); + data = va_arg(args, int); + va_end(args); + + err = __sdla_usb_fxo_write(hwcard, mod_no, (unsigned char)off, (unsigned char)data); + sdla_hw_fe_clear_bit(hw,0); + return err; +} + +static int __sdla_usb_cpu_read(sdlahw_card_t *hwcard, unsigned char off, unsigned char *data) +{ + sdlahw_usb_t *hwusb; + netskb_t *skb; + int err = 0, retry = 0; + u8 *cmd_data; + wan_smp_flag_t flags; + + WAN_ASSERT(hwcard == NULL); + hwusb = &hwcard->u_usb; + *data = 0xFF; + if (!wan_test_bit(WP_USB_STATUS_READY, &hwusb->status)){ + DEBUG_USB("%s: WARNING: RX USB core is not ready (%ld)!\n", + hwcard->name, + (unsigned long)SYSTEM_TICKS); + hwusb->stats.core_notready_cnt++; + return -ENODEV; + } + wan_spin_lock(&hwusb->cmd_lock, &flags); + DEBUG_TX("%s: Tx Read CPU register (0x%02X:ticks=%ld)!\n", + hwcard->name,(unsigned char)off,SYSTEM_TICKS); + if (wan_test_and_set_bit(WP_USB_STATUS_TX_CMD, &hwusb->status)){ + DEBUG_USB("%s: WARNING: USB CPU Read Command Overrun (Read command in process)!\n", + hwcard->name); + hwusb->stats.cmd_overrun++; + err = -EBUSY; + goto cpu_read_done; + } + + if (!wan_skb_queue_len(&hwusb->tx_cmd_free_list)){ + DEBUG_USB("%s: WARNING: USB CPU Read Command Overrun (%d commands in process)!\n", + hwcard->name, wan_skb_queue_len(&hwusb->tx_cmd_list)); + hwusb->stats.cmd_overrun++; + err = -EBUSY; + goto cpu_read_done; + } + skb = wan_skb_dequeue(&hwusb->tx_cmd_free_list); + cmd_data = wan_skb_put(skb, 2); + cmd_data[0] = WP_USB_CMD_TYPE_ENCODE(WP_USB_CMD_TYPE_READ_CPU); + cmd_data[1] = off; + wan_skb_queue_tail(&hwusb->tx_cmd_list, skb); + hwusb->tx_cmd_start = SYSTEM_TICKS; + + //WP_DELAY(20000); + do { + wait_just_a_bit(SDLA_USBFXO_READ_DELAY, 1); //WP_DELAY(10000); + if (++retry > SDLA_USBFXO_READ_RETRIES) break; + } while(!wan_skb_queue_len(&hwusb->rx_cmd_list)); + if (!wan_skb_queue_len(&hwusb->rx_cmd_list)){ + DEBUG_USB("%s: WARNING: Timeout on Read USB-CPU Reg (%d:%02X:%ld:%ld:%ld)!\n", + hwcard->name, retry,off, + (unsigned long)(SYSTEM_TICKS-hwusb->tx_cmd_start), + (unsigned long)hwusb->tx_cmd_start, + (unsigned long)SYSTEM_TICKS); + hwusb->stats.cmd_timeout++; + err = -EINVAL; + goto cpu_read_done; + } + skb = wan_skb_dequeue(&hwusb->rx_cmd_list); + cmd_data = wan_skb_data(skb); + if (cmd_data[1] != off){ + DEBUG_USB("%s: USB Read response is out of order (%02X:%02X)!\n", + hwcard->name, cmd_data[1], off); + hwusb->stats.cmd_invalid++; + wan_skb_init(skb, 0); + wan_skb_queue_tail(&hwusb->rx_cmd_free_list, skb); + err = -EINVAL; + goto cpu_read_done; + } + *data = (unsigned char)cmd_data[2]; + + wan_skb_init(skb, 0); + wan_skb_queue_tail(&hwusb->rx_cmd_free_list, skb); + +cpu_read_done: + wan_clear_bit(WP_USB_STATUS_TX_CMD, &hwusb->status); + wan_spin_unlock(&hwusb->cmd_lock, &flags); return err; } @@ -619,9 +678,7 @@ int sdla_usb_cpu_read(void *phw, unsigned char off, unsigned char *data) { sdlahw_t *hw = (sdlahw_t*)phw; sdlahw_card_t *hwcard = NULL; - netskb_t *skb; - u8 *cmd_data; - wan_smp_flag_t flags; +// wan_smp_flag_t flags; WAN_ASSERT(hw == NULL); SDLA_MAGIC(hw); @@ -629,58 +686,37 @@ int sdla_usb_cpu_read(void *phw, unsigned char off, unsigned char *data) WAN_ASSERT(hw->hwcpu->hwcard == NULL); hwcard = hw->hwcpu->hwcard; - *data = 0xFF; - if (!wan_test_bit(WP_USB_STATUS_READY, &hwcard->u_usb.status)){ + return __sdla_usb_cpu_read(hwcard, off, data); +} - } - wan_spin_lock(&hwcard->u_usb.cmd_lock,&flags); - DEBUG_TX("%s: Tx Read CPU register (0x%02X:ticks=%ld)!\n", - hw->devname,(unsigned char)off,SYSTEM_TICKS); - if (wan_test_and_set_bit(WP_USB_STATUS_TX_CMD, &hwcard->u_usb.status)){ - DEBUG_USB("%s: WARNING: USB CPU Read Command Overrun (Read command in process)!\n", - hw->devname); - hwcard->u_usb.stats.cmd_overrun++; - goto cpu_read_done; - } - - if (!wan_skb_queue_len(&hwcard->u_usb.tx_cmd_free_list)){ - DEBUG_USB("%s: WARNING: USB CPU Read Command Overrun (%d commands in process)!\n", - hw->devname, wan_skb_queue_len(&hwcard->u_usb.tx_cmd_list)); - hwcard->u_usb.stats.cmd_overrun++; - goto cpu_read_done; +static int __sdla_usb_cpu_write(sdlahw_card_t *hwcard, unsigned char off, unsigned char data) +{ + sdlahw_usb_t *hwusb; + netskb_t *skb; + u8 *cmd_data; + wan_smp_flag_t flags; + + WAN_ASSERT(hwcard == NULL); + hwusb = &hwcard->u_usb; + wan_spin_lock(&hwusb->cmd_lock, &flags); + + DEBUG_TX("%s: Tx Write CPU register (0x%02X <- 0x%02X)!\n", + hw->devname, (unsigned char)off, (unsigned char)data); + if (!wan_skb_queue_len(&hwusb->tx_cmd_free_list)){ + DEBUG_USB("%s: WARNING: USB CPU Write Command Overrun (%d commands in process)!\n", + hwcard->name, wan_skb_queue_len(&hwusb->tx_cmd_list)); + hwusb->stats.cmd_overrun++; + wan_spin_unlock(&hwusb->cmd_lock, &flags); + return -EINVAL; } - skb = wan_skb_dequeue(&hwcard->u_usb.tx_cmd_free_list); - cmd_data = wan_skb_put(skb, 2); - cmd_data[0] = WP_USB_CMD_TYPE_ENCODE(WP_USB_CMD_TYPE_READ_CPU); - cmd_data[1] = off; - wan_skb_queue_tail(&hwcard->u_usb.tx_cmd_list, skb); + skb = wan_skb_dequeue(&hwusb->tx_cmd_free_list); + cmd_data = wan_skb_put(skb, 3); + cmd_data[0] = WP_USB_CMD_TYPE_ENCODE(WP_USB_CMD_TYPE_WRITE_CPU); + cmd_data[1] = off; + cmd_data[2] = data; + wan_skb_queue_tail(&hwusb->tx_cmd_list, skb); - //WP_DELAY(20000); - wait_just_a_bit(SDLA_USBFXO_READ_DELAY, gl_usb_rw_fast); //WP_DELAY(10000); - - if (!wan_skb_queue_len(&hwcard->u_usb.rx_cmd_list)){ - DEBUG_USB("WARNING: %s: Timeout on Read USB-CPU Reg!\n", - hw->devname); - hwcard->u_usb.stats.cmd_timeout++; - goto cpu_read_done; - } - skb = wan_skb_dequeue(&hwcard->u_usb.rx_cmd_list); - cmd_data = wan_skb_data(skb); - if (cmd_data[1] != off){ - DEBUG_USB("%s: USB Read response is out of order (%02X:%02X)!\n", - hw->devname, cmd_data[1], off); - hwcard->u_usb.stats.cmd_invalid++; - wan_skb_init(skb, 0); - wan_skb_queue_tail(&hwcard->u_usb.rx_cmd_free_list, skb); - goto cpu_read_done; - } - *data = (unsigned char)cmd_data[2]; - wan_skb_init(skb, 0); - wan_skb_queue_tail(&hwcard->u_usb.rx_cmd_free_list, skb); - -cpu_read_done: - wan_clear_bit(WP_USB_STATUS_TX_CMD, &hwcard->u_usb.status); - wan_spin_unlock(&hwcard->u_usb.cmd_lock,&flags); + wan_spin_unlock(&hwusb->cmd_lock, &flags); return 0; } @@ -688,35 +724,14 @@ int sdla_usb_cpu_write(void *phw, unsigned char off, unsigned char data) { sdlahw_t *hw = (sdlahw_t*)phw; sdlahw_card_t *hwcard = NULL; - netskb_t *skb; - u8 *cmd_data; - wan_smp_flag_t flags; WAN_ASSERT(hw == NULL); SDLA_MAGIC(hw); WAN_ASSERT(hw->hwcpu == NULL); WAN_ASSERT(hw->hwcpu->hwcard == NULL); hwcard = hw->hwcpu->hwcard; - wan_spin_lock(&hwcard->u_usb.cmd_lock,&flags); - DEBUG_TX("%s: Tx Write CPU register (0x%02X <- 0x%02X)!\n", - hw->devname, (unsigned char)off, (unsigned char)data); - if (!wan_skb_queue_len(&hwcard->u_usb.tx_cmd_free_list)){ - DEBUG_USB("%s: WARNING: USB CPU Write Command Overrun (%d commands in process)!\n", - hw->devname, wan_skb_queue_len(&hwcard->u_usb.tx_cmd_list)); - hwcard->u_usb.stats.cmd_overrun++; - wan_spin_unlock(&hwcard->u_usb.cmd_lock,&flags); - return 0; - } - skb = wan_skb_dequeue(&hwcard->u_usb.tx_cmd_free_list); - cmd_data = wan_skb_put(skb, 3); - cmd_data[0] = WP_USB_CMD_TYPE_ENCODE(WP_USB_CMD_TYPE_WRITE_CPU); - cmd_data[1] = off; - cmd_data[2] = data; - wan_skb_queue_tail(&hwcard->u_usb.tx_cmd_list, skb); - - wan_spin_unlock(&hwcard->u_usb.cmd_lock,&flags); - return 0; + return __sdla_usb_cpu_write(hwcard, off, data); } int sdla_usb_write_poll(void *phw, unsigned char off, unsigned char data) @@ -726,6 +741,7 @@ int sdla_usb_write_poll(void *phw, unsigned char off, unsigned char data) int sdla_usb_read_poll(void *phw, unsigned char off, unsigned char *data) { + sdlahw_usb_t *hwusb = NULL; sdlahw_t *hw = (sdlahw_t*)phw; sdlahw_card_t *hwcard = NULL; netskb_t *skb; @@ -736,53 +752,77 @@ int sdla_usb_read_poll(void *phw, unsigned char off, unsigned char *data) WAN_ASSERT(hw->hwcpu == NULL); WAN_ASSERT(hw->hwcpu->hwcard == NULL); hwcard = hw->hwcpu->hwcard; - if (!wan_skb_queue_len(&hwcard->u_usb.rx_cmd_list)){ + hwusb = &hwcard->u_usb; + if (!wan_skb_queue_len(&hwusb->rx_cmd_list)){ DEBUG_EVENT("WARNING: %s: Timeout on Read USB Reg!\n", hw->devname); return -EBUSY; } - skb = wan_skb_dequeue(&hwcard->u_usb.rx_cmd_list); + skb = wan_skb_dequeue(&hwusb->rx_cmd_list); cmd_data = wan_skb_data(skb); *data = (unsigned char)cmd_data[2]; wan_skb_init(skb, 0); - wan_skb_queue_tail(&hwcard->u_usb.rx_cmd_free_list, skb); + wan_skb_queue_tail(&hwusb->rx_cmd_free_list, skb); return 0; } int sdla_usb_rxevent_enable(void *phw, int mod_no, int enable) { + sdlahw_usb_t *hwusb = NULL; sdlahw_t *hw = (sdlahw_t*)phw; sdlahw_card_t *hwcard = NULL; int event_bit; - u8 mask, data; + u8 mask; WAN_ASSERT(hw == NULL); SDLA_MAGIC(hw); WAN_ASSERT(hw->hwcpu == NULL); WAN_ASSERT(hw->hwcpu->hwcard == NULL); hwcard = hw->hwcpu->hwcard; - - if (sdla_usb_cpu_read(hw, SDLA_USB_CPU_REG_CONRTOL, &data)){ - return -EBUSY; - } - if (mod_no) mask = SDLA_USB_CPU_BIT_CONRTOL_TS1_EVENT_EN; - else mask = SDLA_USB_CPU_BIT_CONRTOL_TS0_EVENT_EN; - if (enable) data |= mask; - else data &= ~mask; - sdla_usb_cpu_write(hw, SDLA_USB_CPU_REG_CONRTOL, data); + hwusb = &hwcard->u_usb; + if (mod_no) mask = SDLA_USB_CPU_BIT_CTRL_TS1_EVENT_EN; + else mask = SDLA_USB_CPU_BIT_CTRL_TS0_EVENT_EN; + if (enable) hwusb->reg_cpu_ctrl |= mask; + else hwusb->reg_cpu_ctrl &= ~mask; + sdla_usb_cpu_write(hw, SDLA_USB_CPU_REG_CTRL, hwusb->reg_cpu_ctrl); event_bit = (mod_no) ? WP_USB_STATUS_RX_EVENT2_READY : WP_USB_STATUS_RX_EVENT1_READY; - wan_set_bit(event_bit, &hwcard->u_usb.status); + wan_set_bit(event_bit, &hwusb->status); DEBUG_USB("%s: Module %d: %s RX Events (%02X:%ld)!\n", hw->devname, mod_no+1, - (enable) ? "Enable" : "Disable", data, + (enable) ? "Enable" : "Disable", hwusb->reg_cpu_ctrl, (unsigned long)SYSTEM_TICKS); return 0; } +int sdla_usb_hwec_enable(void *phw, int mod_no, int enable) +{ + sdlahw_usb_t *hwusb = NULL; + sdlahw_t *hw = (sdlahw_t*)phw; + sdlahw_card_t *hwcard = NULL; + u8 mask; + + WAN_ASSERT(hw == NULL); + SDLA_MAGIC(hw); + WAN_ASSERT(hw->hwcpu == NULL); + WAN_ASSERT(hw->hwcpu->hwcard == NULL); + hwcard = hw->hwcpu->hwcard; + hwusb = &hwcard->u_usb; + if (mod_no) mask = SDLA_USB_CPU_BIT_CTRL_TS1_HWEC_EN; + else mask = SDLA_USB_CPU_BIT_CTRL_TS0_HWEC_EN; + if (enable) hwusb->reg_cpu_ctrl |= mask; + else hwusb->reg_cpu_ctrl &= ~mask; + sdla_usb_cpu_write(hw, SDLA_USB_CPU_REG_CTRL, hwusb->reg_cpu_ctrl); + + DEBUG_USB("%s: Module %d: %s hw echo canceller!\n", + hw->devname, mod_no+1, + (enable) ? "Enable" : "Disable"); + return 0; +} int sdla_usb_rxevent(void *phw, int mod_no, u8 *regs, int force) { sdlahw_t *hw = (sdlahw_t*)phw; + sdlahw_usb_t *hwusb = NULL; sdlahw_card_t *hwcard = NULL; int event_bit; @@ -791,25 +831,25 @@ int sdla_usb_rxevent(void *phw, int mod_no, u8 *regs, int force) WAN_ASSERT(hw->hwcpu == NULL); WAN_ASSERT(hw->hwcpu->hwcard == NULL); hwcard = hw->hwcpu->hwcard; - + hwusb = &hwcard->u_usb; event_bit = (mod_no) ? WP_USB_STATUS_RX_EVENT2_READY : WP_USB_STATUS_RX_EVENT1_READY; - if(!wan_test_bit(event_bit, &hwcard->u_usb.status)){ + if(!wan_test_bit(event_bit, &hwusb->status)){ return -EINVAL; } if (force){ - hwcard->u_usb.regs[mod_no][5] = __sdla_usb_fxo_read(hw, mod_no, 5); - hwcard->u_usb.regs[mod_no][29] = __sdla_usb_fxo_read(hw, mod_no, 29); - hwcard->u_usb.regs[mod_no][34] = __sdla_usb_fxo_read(hw, mod_no, 34); - hwcard->u_usb.regs[mod_no][4] = __sdla_usb_fxo_read(hw, mod_no, 4); + hwusb->regs[mod_no][5] = __sdla_usb_fxo_read(hwcard, mod_no, 5); + hwusb->regs[mod_no][29] = __sdla_usb_fxo_read(hwcard, mod_no, 29); + hwusb->regs[mod_no][34] = __sdla_usb_fxo_read(hwcard, mod_no, 34); + hwusb->regs[mod_no][4] = __sdla_usb_fxo_read(hwcard, mod_no, 4); DEBUG_USB("%s: Module %d: RX Event Init (%02X:%02X:%02X:%02X)...\n", hw->devname, mod_no+1, - hwcard->u_usb.regs[mod_no][5], hwcard->u_usb.regs[mod_no][29], - hwcard->u_usb.regs[mod_no][34], hwcard->u_usb.regs[mod_no][4]); + hwusb->regs[mod_no][5], hwusb->regs[mod_no][29], + hwusb->regs[mod_no][34], hwusb->regs[mod_no][4]); } - regs[0] = hwcard->u_usb.regs[mod_no][5]; - regs[1] = hwcard->u_usb.regs[mod_no][29]; - regs[2] = hwcard->u_usb.regs[mod_no][34]; - regs[3] = hwcard->u_usb.regs[mod_no][4]; + regs[0] = hwusb->regs[mod_no][5]; + regs[1] = hwusb->regs[mod_no][29]; + regs[2] = hwusb->regs[mod_no][34]; + regs[3] = hwusb->regs[mod_no][4]; return 0; } @@ -848,96 +888,70 @@ int sdla_usb_rxdata_enable(void *phw, int enable) return 0; } -int sdla_usb_rxdata(void *phw, unsigned char *data, int len) +int sdla_usb_fwupdate_enable(void *phw) { + sdlahw_usb_t *hwusb = NULL; sdlahw_t *hw = (sdlahw_t*)phw; sdlahw_card_t *hwcard = NULL; - int rx_len, rx_ind; - - WAN_ASSERT_RC(hw == NULL, 0); - SDLA_MAGIC_RC(hw, 0); - WAN_ASSERT_RC(hw->hwcpu == NULL, 0); - WAN_ASSERT_RC(hw->hwcpu->hwcard == NULL, 0); + unsigned char data[1]; + + WAN_ASSERT(hw == NULL); + SDLA_MAGIC(hw); + WAN_ASSERT(hw->hwcpu == NULL); + WAN_ASSERT(hw->hwcpu->hwcard == NULL); hwcard = hw->hwcpu->hwcard; + hwusb = &hwcard->u_usb; - rx_ind = hwcard->u_usb.next_rx_ind; - if (rx_ind > hwcard->u_usb.next_read_ind){ - rx_len = rx_ind - hwcard->u_usb.next_read_ind; - }else if (rx_ind < hwcard->u_usb.next_read_ind){ - rx_len = MAX_READ_BUF_LEN - hwcard->u_usb.next_read_ind + rx_ind; - }else{ - DEBUG_USB("%s: No data available!\n", - hw->devname); - return 0; - } - if (rx_len < len){ - DEBUG_USB("%s: No enought data received (%d:%d)\n", - hw->devname, rx_len, len); - return 0; - } + /* Send Firmware update command */ + data[0] = SDLA_USB_CPU_BITS_FWUPDATE_MAGIC; + sdla_usb_cpu_write(phw, SDLA_USB_CPU_REG_FWUPDATE_MAGIC, SDLA_USB_CPU_BITS_FWUPDATE_MAGIC); + data[0] = SDLA_USB_CPU_BIT_CTRL_FWUPDATE; + sdla_usb_cpu_write(phw, SDLA_USB_CPU_REG_CTRL, SDLA_USB_CPU_BIT_CTRL_FWUPDATE); + wait_just_a_bit(SDLA_USBFXO_WRITE_DELAY, 0); + DEBUG_EVENT("%s: Enabling Firmware Update mode...\n", + hwcard->name); + hwusb->opmode = SDLA_USB_OPMODE_API; - memcpy(data, &hwcard->u_usb.readbuf[hwcard->u_usb.next_read_ind], len); - hwcard->u_usb.next_read_ind += len; - return len; + /* Initialize rx urb */ + sdla_usb_rxurb_reset(hwcard); + sdla_usb_txurb_reset(hwcard); + + return 0; } -int sdla_usb_txdata(void *phw, unsigned char *data, int len) +int sdla_usb_txdata_raw(void *phw, unsigned char *data, int max_len) { sdlahw_t *hw = (sdlahw_t*)phw; sdlahw_card_t *hwcard = NULL; - int urb_write_ind; - - WAN_ASSERT_RC(hw == NULL, 0); - SDLA_MAGIC_RC(hw, 0); - WAN_ASSERT_RC(hw->hwcpu == NULL, 0); - WAN_ASSERT_RC(hw->hwcpu->hwcard == NULL, 0); + int err = 0; + + WAN_ASSERT(hw == NULL); + SDLA_MAGIC(hw); + WAN_ASSERT(hw->hwcpu == NULL); + WAN_ASSERT(hw->hwcpu->hwcard == NULL); hwcard = hw->hwcpu->hwcard; - if (len > MAX_USB_TX_LEN){ - len = MAX_USB_TX_LEN; + if (max_len > MAX_USB_TX_LEN){ + max_len = MAX_USB_TX_LEN; } - memcpy(&hwcard->u_usb.writebuf[hwcard->u_usb.next_tx_ind], data, len); - - /* Mark this urb as busy */ - urb_write_ind = (hwcard->u_usb.urb_write_ind + 1) % MAX_WRITE_URB_COUNT; - hwcard->u_usb.datawrite[urb_write_ind].urb.transfer_buffer = &hwcard->u_usb.writebuf[hwcard->u_usb.next_tx_ind]; - hwcard->u_usb.datawrite[urb_write_ind].urb.transfer_buffer_length = len; - hwcard->u_usb.next_tx_ind += len; - hwcard->u_usb.next_tx_ind = hwcard->u_usb.next_tx_ind % MAX_WRITE_BUF_LEN; - wan_clear_bit(WP_USB_STATUS_TX_READY, &hwcard->u_usb.status); - if (wp_usb_start_transfer(&hwcard->u_usb.datawrite[urb_write_ind])){ - DEBUG_TX("%s: Failed to execute write cycle (%d:%d)\n", - hw->devname, - hwcard->u_usb.next_tx_ind, hwcard->u_usb.next_write_ind); - hwcard->u_usb.stats.tx_notready_cnt++; - return 0; - }else{ - hwcard->u_usb.urb_write_ind = urb_write_ind; - } - - return len; + err = sdla_usb_txdata_prepare(hwcard, data, max_len); + return (!err) ? max_len : 0; } -int sdla_usb_txdata_ready(void *phw) +int sdla_usb_txdata_raw_ready(void *phw) { - sdlahw_t *hw = (sdlahw_t*)phw; - sdlahw_card_t *hwcard = NULL; - int urb_write_ind; - - WAN_ASSERT_RC(hw == NULL, -EBUSY); - SDLA_MAGIC_RC(hw, -EBUSY); - WAN_ASSERT_RC(hw->hwcpu == NULL, -EBUSY); - WAN_ASSERT_RC(hw->hwcpu->hwcard == NULL, -EBUSY); - hwcard = hw->hwcpu->hwcard; + sdlahw_t *hw = (sdlahw_t*)phw; + sdlahw_usb_t *hwusb = NULL; + sdlahw_card_t *hwcard = NULL; - urb_write_ind = (hwcard->u_usb.urb_write_ind + 1) % MAX_WRITE_URB_COUNT; - if (!wan_test_bit(1, &hwcard->u_usb.datawrite[urb_write_ind].ready)){ - DEBUG_TX("%s:%d: Tx Data is busy!\n", - hw->devname, hwcard->u_usb.datawrite[urb_write_ind].id, - (unsigned long)SYSTEM_TICKS); - return -EBUSY; - } - if (!wan_test_bit(WP_USB_STATUS_TX_READY, &hwcard->u_usb.status)){ + WAN_ASSERT(hw == NULL); + SDLA_MAGIC(hw); + WAN_ASSERT(hw->hwcpu == NULL); + WAN_ASSERT(hw->hwcpu->hwcard == NULL); + hwcard = hw->hwcpu->hwcard; + hwusb = &hwcard->u_usb; + + if (!wan_test_bit(WP_USB_STATUS_TX_READY, &hwusb->status)){ DEBUG_TX("%s:%d: Tx Data is busy (%ld)!\n", hw->devname, hwcard->u_usb.datawrite[urb_write_ind].id, (unsigned long)SYSTEM_TICKS); @@ -946,6 +960,26 @@ int sdla_usb_txdata_ready(void *phw) return 0; } +int sdla_usb_rxdata_raw(void *phw, unsigned char *data, int max_len) +{ + sdlahw_t *hw = (sdlahw_t*)phw; + sdlahw_card_t *hwcard = NULL; + int rxlen = 0; + + WAN_ASSERT(hw == NULL); + SDLA_MAGIC(hw); + WAN_ASSERT(hw->hwcpu == NULL); + WAN_ASSERT(hw->hwcpu->hwcard == NULL); + hwcard = hw->hwcpu->hwcard; + + if (max_len > MAX_USB_RX_LEN){ + max_len = MAX_USB_RX_LEN; + } + rxlen = sdla_usb_rxdata_get(hwcard, data, max_len); + return rxlen; +} + + int sdla_usb_set_intrhand(void* phw, wan_pci_ifunc_t *isr_func, void* arg, int notused) { sdlahw_t *hw = (sdlahw_t*)phw; @@ -981,6 +1015,7 @@ int sdla_usb_restore_intrhand(void* phw, int notused) int sdla_usb_err_stats(void *phw,void *buf,int len) { sdlahw_t *hw = (sdlahw_t*)phw; + sdlahw_usb_t *hwusb = NULL; sdlahw_card_t *hwcard = NULL; sdla_usb_comm_err_stats_t *stats; @@ -989,16 +1024,16 @@ int sdla_usb_err_stats(void *phw,void *buf,int len) WAN_ASSERT(hw->hwcpu == NULL); WAN_ASSERT(hw->hwcpu->hwcard == NULL); hwcard = hw->hwcpu->hwcard; - + hwusb = &hwcard->u_usb; if (len != sizeof(sdla_usb_comm_err_stats_t)){ DEBUG_EVENT("%s: Invalid stats structure (%d:%d)!\n", - hw->devname, len, sizeof(sdla_usb_comm_err_stats_t)); + hw->devname, len, (int)sizeof(sdla_usb_comm_err_stats_t)); return -EINVAL; } - stats = &hwcard->u_usb.stats; - sdla_usb_cpu_read(hw, SDLA_USB_CPU_REG_FIFO_STATUS, &stats->fifo_status); - sdla_usb_cpu_read(hw, SDLA_USB_CPU_REG_UART_STATUS, &stats->uart_status); - sdla_usb_cpu_read(hw, SDLA_USB_CPU_REG_HOSTIF_STATUS, &stats->hostif_status); + stats = &hwusb->stats; + sdla_usb_cpu_read(hw, SDLA_USB_CPU_REG_FIFO_STATUS, &stats->dev_fifo_status); + sdla_usb_cpu_read(hw, SDLA_USB_CPU_REG_UART_STATUS, &stats->dev_uart_status); + sdla_usb_cpu_read(hw, SDLA_USB_CPU_REG_HOSTIF_STATUS, &stats->dev_hostif_status); memcpy(buf, stats,sizeof(sdla_usb_comm_err_stats_t)); return 0; @@ -1021,40 +1056,38 @@ int sdla_usb_flush_err_stats(void *phw) static unsigned int bhcount=0, rxcount=0, txcount=0; -static int sdla_usb_decode_rxcmd(sdlahw_t *hw, u8 *rx_cmd, int rx_cmd_len) +static int sdla_usb_rxcmd_decode(sdlahw_card_t *hwcard, u8 *rx_cmd, int rx_cmd_len) { - sdlahw_card_t *hwcard; + sdlahw_usb_t *hwusb = NULL; netskb_t *skb; u_int8_t *cmd; u_int8_t reg_no; int mod_no; - WAN_ASSERT(hw == NULL); - WAN_ASSERT(hw->hwcpu == NULL); - WAN_ASSERT(hw->hwcpu->hwcard == NULL); - hwcard = hw->hwcpu->hwcard; + WAN_ASSERT(hwcard == NULL); + hwusb = &hwcard->u_usb; switch(WP_USB_CMD_TYPE_DECODE(rx_cmd[0])){ case WP_USB_CMD_TYPE_WRITE_CPU: DEBUG_RX("%s: Rx Write CPU register (%02X:%02X)!\n", - hw->devname, + hwcard->name, (unsigned char)rx_cmd[1], (unsigned char)rx_cmd[2]); break; case WP_USB_CMD_TYPE_READ_CPU: DEBUG_RX("%s: Rx Read CPU register (%02X:%02X)!\n", - hw->devname, + hwcard->name, (unsigned char)rx_cmd[1], (unsigned char)rx_cmd[2]); break; case WP_USB_CMD_TYPE_WRITE_FXO: DEBUG_RX("%s: Rx Write FXO register (%02X:%02X)!\n", - hw->devname, + hwcard->name, (unsigned char)rx_cmd[1], (unsigned char)rx_cmd[2]); break; case WP_USB_CMD_TYPE_READ_FXO: DEBUG_RX("%s: Rx Read FXO register (%d:%02X)!\n", - hw->devname, + hwcard->name, (unsigned char)rx_cmd[1], (unsigned char)rx_cmd[2]); break; @@ -1062,81 +1095,87 @@ static int sdla_usb_decode_rxcmd(sdlahw_t *hw, u8 *rx_cmd, int rx_cmd_len) mod_no = rx_cmd[0] & 0x01; reg_no = rx_cmd[1]; DEBUG_RX("%s: Module %d: Rx Event Info (Reg:%d = %02X:%ld)!\n", - hw->devname, mod_no+1, + hwcard->name, mod_no+1, reg_no, rx_cmd[2], (unsigned long)SYSTEM_TICKS); - hwcard->u_usb.regs[mod_no][reg_no] = rx_cmd[2]; + hwusb->regs[mod_no][reg_no] = rx_cmd[2]; return 0; default: DEBUG_USB("%s: Unknown command %X : %02X!\n", - hw->devname, + hwcard->name, WP_USB_CMD_TYPE_DECODE(rx_cmd[0]), rx_cmd[0]); - hwcard->u_usb.stats.rx_cmd_unknown++; + hwusb->stats.rx_cmd_unknown++; return -EINVAL; } - skb = wan_skb_dequeue(&hwcard->u_usb.rx_cmd_free_list); + skb = wan_skb_dequeue(&hwusb->rx_cmd_free_list); cmd = wan_skb_put(skb, rx_cmd_len); memcpy(cmd, &rx_cmd[0], rx_cmd_len); - wan_skb_queue_tail(&hwcard->u_usb.rx_cmd_list, skb); + wan_skb_queue_tail(&hwusb->rx_cmd_list, skb); return 0; } -static int sdla_usb_rx_bh (sdlahw_t *hw) +static int +sdla_usb_rxdata_get(sdlahw_card_t *hwcard, unsigned char *rxdata, int max_len) { - sdlahw_card_t *hwcard = NULL; - int rx_len, rx_ind = 0; - int off, x = 0, mod_no=0, ind=0, high=0, shift=0; + sdlahw_usb_t *hwusb = NULL; + int rx_len, next_rx_ind = 0, next_read_ind; + + WAN_ASSERT(hwcard == NULL); + hwusb = &hwcard->u_usb; + + next_rx_ind = hwusb->next_rx_ind; + next_read_ind = hwusb->next_read_ind; + if (next_rx_ind > next_read_ind){ + rx_len = next_rx_ind - next_read_ind; + }else if (next_rx_ind < next_read_ind){ + rx_len = MAX_READ_BUF_LEN - next_read_ind + next_rx_ind; + }else{ + return 0; + } + if (rxdata == NULL){ + /* ignore previously received data */ + hwusb->next_read_ind = (next_read_ind + rx_len) % MAX_READ_BUF_LEN; + return rx_len; + } + if (rx_len > max_len) rx_len = max_len; + if (rx_len > MAX_USB_RX_LEN) rx_len = MAX_USB_RX_LEN; + + if (next_read_ind + rx_len < MAX_READ_BUF_LEN){ + memcpy(rxdata, &hwusb->readbuf[next_read_ind], rx_len); + }else{ + int len = MAX_READ_BUF_LEN - next_read_ind; + memcpy(rxdata, &hwusb->readbuf[next_read_ind], len); + memcpy(&rxdata[len], &hwusb->readbuf[0], rx_len-len); + } + hwusb->next_read_ind = (next_read_ind + rx_len) % MAX_READ_BUF_LEN; + return rx_len; +} + +static int sdla_usb_rxdata_decode (sdlahw_card_t *hwcard, unsigned char *rxdata, int len) +{ + sdlahw_usb_t *hwusb = NULL; + int x = 0, mod_no=0, ind=0, high=0, shift=0; unsigned char data, cmd, start_bit, start_fr_bit; u_int8_t *rx_data[2]; u_int8_t rx_cmd[10]; - int rx_cmd_len= 0; + int rx_cmd_len= 0; - WAN_ASSERT(hw == NULL); - WAN_ASSERT(hw->hwcpu == NULL); - WAN_ASSERT(hw->hwcpu->hwcard == NULL); - hwcard = hw->hwcpu->hwcard; - rx_ind = hwcard->u_usb.next_rx_ind; - if (rx_ind > hwcard->u_usb.next_read_ind){ - rx_len = rx_ind - hwcard->u_usb.next_read_ind; - }else if (rx_ind < hwcard->u_usb.next_read_ind){ - rx_len = MAX_READ_BUF_LEN - hwcard->u_usb.next_read_ind + rx_ind; - }else{ - DEBUG_USB("%s: INTERNAL ERROR:%d: No data available!\n", - hw->devname, (u32)SYSTEM_TICKS); - hwcard->u_usb.stats.rx_underrun_cnt++; - return -EINVAL; - } - if (rx_len < MAX_USB_RX_LEN){ - DEBUG_USB("%s: ERROR: Not enough data (%d:%d:%d:%d)!\n", - hw->devname, rx_len, - hwcard->u_usb.next_read_ind, - hwcard->u_usb.next_rx_ind, - MAX_READ_BUF_LEN); - hwcard->u_usb.stats.rx_underrun_cnt++; - return 0; - } - if (rx_len > MAX_USB_RX_LEN) rx_len = MAX_USB_RX_LEN; + WAN_ASSERT(hwcard == NULL); + hwusb = &hwcard->u_usb; - DEBUG_RX("[RX-BH]%s:%d: RX:%d (%d:%d)\n", - __FUNCTION__,__LINE__,rx_len, - hwcard->u_usb.next_read_ind, - hwcard->u_usb.next_rx_ind); + rx_data[0] = hwusb->readchunk[0]; + rx_data[1] = hwusb->readchunk[1]; - off = hwcard->u_usb.next_read_ind; - x = 0; - - rx_data[0] = hwcard->u_usb.readchunk[0]; - rx_data[1] = hwcard->u_usb.readchunk[1]; - //memset(&hwcard->u_usb.readchunk[0][0], 0, WP_USB_MAX_CHUNKSIZE); - //memset(&hwcard->u_usb.readchunk[1][0], 0, WP_USB_MAX_CHUNKSIZE); + //memset(&hwusb->readchunk[0][0], 0, WP_USB_MAX_CHUNKSIZE); + //memset(&hwusb->readchunk[1][0], 0, WP_USB_MAX_CHUNKSIZE); memset(&rx_cmd[0],0, 10); + x = 0; + while(x < MAX_USB_RX_LEN){ - while(rx_len){ - - DEBUG_RX(" RX: %02X\n", (unsigned char)hwcard->u_usb.readbuf[off]); - data = hwcard->u_usb.readbuf[off] & 0x0F; - start_bit = hwcard->u_usb.readbuf[off] & 0x10; - start_fr_bit = hwcard->u_usb.readbuf[off] & 0x20; + DEBUG_RX(" RX: %02X\n", (unsigned char)rxdata[x]); + data = rxdata[x] & 0x0F; + start_bit = rxdata[x] & 0x10; + start_fr_bit = rxdata[x] & 0x20; ind = x / 4; mod_no = x % 2; @@ -1146,13 +1185,11 @@ static int sdla_usb_rx_bh (sdlahw_t *hw) if (!start_fr_bit){ DEBUG_USB( "%s: ERROR:%d: Start Frame bit missing (%d:%d:%02X:%ld)\n", - hw->devname, - bhcount,off,ind, - (unsigned char)hwcard->u_usb.readbuf[off], + hwcard->name, + bhcount,x,ind, + (unsigned char)rxdata[x], (unsigned long)SYSTEM_TICKS); - hwcard->u_usb.stats.rx_start_fr_err_cnt++; - /* Skip the current packet */ - off = (off + rx_len) % MAX_READ_BUF_LEN; + hwusb->stats.rx_start_fr_err_cnt++; break; } } @@ -1160,19 +1197,17 @@ static int sdla_usb_rx_bh (sdlahw_t *hw) if (!start_bit){ DEBUG_USB( "%s: ERROR:%d: Start bit missing (%d:%02X:%ld)\n", - hw->devname, - bhcount,off, - (unsigned char)hwcard->u_usb.readbuf[off], + hwcard->name, + bhcount,x, + (unsigned char)rxdata[x], (unsigned long)SYSTEM_TICKS); - hwcard->u_usb.stats.rx_start_err_cnt++; - /* Skip the current packet */ - off = (off + rx_len) % MAX_READ_BUF_LEN; + hwusb->stats.rx_start_err_cnt++; break; } } DEBUG_RX("x:%d mod:%d ind:%d high:%d data:%02X\n", x, mod_no, ind, high, - (unsigned char)hwcard->u_usb.readbuf[off]); + (unsigned char)rxdata[x]); if (high){ rx_data[mod_no][ind] |= (data << 4); //sc->readchunk[mod_no][ind] |= (data << 4); }else{ @@ -1180,34 +1215,34 @@ static int sdla_usb_rx_bh (sdlahw_t *hw) } /* decode control command (2 bits) */ - cmd = hwcard->u_usb.readbuf[off] & 0xC0; + cmd = rxdata[x] & 0xC0; ind = x / 4; shift = (x % 4) * 2; cmd = cmd >> shift; if (ind && shift == 0){ - if (rx_cmd[rx_cmd_len] == hwcard->u_usb.ctrl_idle_pattern){ + if (rx_cmd[rx_cmd_len] == hwusb->ctrl_idle_pattern){ DEBUG_RX("RX_CMD: x:%d ind:%d shift:%d len:%d ctrl_idle_pattern\n", x, ind, shift, rx_cmd_len); rx_cmd[rx_cmd_len] = 0x00; if (rx_cmd_len){ - if (!wan_skb_queue_len(&hwcard->u_usb.rx_cmd_free_list)){ + if (!wan_skb_queue_len(&hwusb->rx_cmd_free_list)){ DEBUG_USB("%s: INTERNAL ERROR:%d: Received too many commands!\n", - hw->devname, (u32)SYSTEM_TICKS); - hwcard->u_usb.stats.rx_cmd_drop_cnt++; + hwcard->name, (u32)SYSTEM_TICKS); + hwusb->stats.rx_cmd_drop_cnt++; rx_cmd_len = 0; } if (rx_cmd_len >= 3){ - sdla_usb_decode_rxcmd(hw, rx_cmd, rx_cmd_len); + sdla_usb_rxcmd_decode(hwcard, rx_cmd, rx_cmd_len); }else{ - hwcard->u_usb.stats.rx_cmd_reset_cnt++; + hwusb->stats.rx_cmd_reset_cnt++; if (rx_cmd_len == 1){ DEBUG_USB("%s: Reset RX Cmd (%d:%02X:%02X)!\n", - hw->devname, rx_cmd_len, + hwcard->name, rx_cmd_len, WP_USB_CMD_TYPE_DECODE(rx_cmd[0]), rx_cmd[0]); }else{ DEBUG_USB("%s: Reset RX Cmd (%d:%02X:%02X:%02X)!\n", - hw->devname, rx_cmd_len, + hwcard->name, rx_cmd_len, WP_USB_CMD_TYPE_DECODE(rx_cmd[0]), rx_cmd[0],rx_cmd[1]); } } @@ -1224,37 +1259,107 @@ static int sdla_usb_rx_bh (sdlahw_t *hw) DEBUG_RX("RX_CMD: x:%d ind:%d shift:%d cmd:%02X:%02X\n", x, ind, shift, (unsigned char)cmd, (unsigned char)rx_cmd[rx_cmd_len]); - off = (off + 1) % MAX_READ_BUF_LEN; - rx_len --; x++; } - hwcard->u_usb.next_read_ind = off; - - if (wan_test_bit(WP_USB_STATUS_RX_DATA_READY, &hwcard->u_usb.status) && hwcard->u_usb.isr_func){ - hwcard->u_usb.isr_func(hwcard->u_usb.isr_arg); - } return 0; } -static int sdla_usb_tx_bh (sdlahw_t *hw) -{ - sdlahw_card_t *hwcard = NULL; - int next_write_ind; +static int +sdla_usb_txdata_prepare(sdlahw_card_t *hwcard, char *writebuf, int len) +{ + sdlahw_usb_t *hwusb = NULL; + int next_write_ind, urb_write_ind; + int err; + + WAN_ASSERT(hwcard == NULL); + WAN_ASSERT(len > MAX_USB_TX_LEN); + hwusb = &hwcard->u_usb; + + next_write_ind = hwusb->next_write_ind; + memcpy(&hwusb->writebuf[next_write_ind], writebuf, len); + + next_write_ind = (next_write_ind + len) % MAX_WRITE_BUF_LEN; + if (next_write_ind == hwusb->next_tx_ind){ + DEBUG_USB("ERROR:%d: TX BH is too fast (%d:%ld)\n", + bhcount, + next_write_ind, + (unsigned long)SYSTEM_TICKS); + hwusb->stats.tx_overrun_cnt++; + }else{ + hwusb->next_write_ind = next_write_ind; + } + + urb_write_ind = (hwusb->urb_write_ind + 1) % MAX_WRITE_URB_COUNT; +#if 1 + if (!wan_test_bit(SDLA_URB_STATUS_READY, &hwusb->datawrite[urb_write_ind].ready)){ + /* Use previous urb for now and increment errors */ + DEBUG_TX("%s: [BH:%d:%d:%d]: TX is not ready (%ld)!\n", + hwcard->name, + bhcount,rxcount,txcount, + (unsigned long)SYSTEM_TICKS); + hwusb->stats.tx_overrun_cnt++; + return -EINVAL; + } + /* Update tx urb */ + hwusb->datawrite[urb_write_ind].urb.transfer_buffer = &hwusb->writebuf[hwusb->next_tx_ind]; + hwusb->datawrite[urb_write_ind].urb.transfer_buffer_length = len; + hwusb->next_tx_ind += len; + hwusb->next_tx_ind = hwusb->next_tx_ind % MAX_WRITE_BUF_LEN; + wan_clear_bit(WP_USB_STATUS_TX_READY, &hwusb->status); //sc->tx_ready = 0; + if ((err = wp_usb_start_transfer(&hwusb->datawrite[urb_write_ind]))){ + if (err != -ENOENT){ + DEBUG_EVENT("%s: Failed to program transmitter (%ld)!\n", + hwcard->name, + (unsigned long)SYSTEM_TICKS); + } + hwusb->stats.tx_notready_cnt++; + return -EINVAL; + } + hwusb->urb_write_ind = urb_write_ind; + +#else + if (wan_test_bit(1, &hwusb->datawrite[urb_write_ind].ready)){ + /* Update tx urb */ + hwusb->datawrite[urb_write_ind].urb.transfer_buffer = &hwusb->writebuf[hwusb->next_tx_ind]; + hwusb->next_tx_ind += len; + hwusb->next_tx_ind = hwusb->next_tx_ind % MAX_WRITE_BUF_LEN; + }else{ + /* Use previous urb for now and increment errors */ + DEBUG_USB("%s: [BH:%d:%d:%d]: TX is not ready (%ld)!\n", + hwcard->name, + bhcount,rxcount,txcount, + (unsigned long)SYSTEM_TICKS); + hwusb->stats.tx_overrun_cnt++; + } + wan_clear_bit(WP_USB_STATUS_TX_READY, &hwusb->status); //sc->tx_ready = 0; + if ((err = wp_usb_start_transfer(&hwusb->datawrite[urb_write_ind]))){ + if (err != -ENOENT){ + DEBUG_EVENT("%s: Failed to program transmitter (%ld)!\n", + hwcard->name, + (unsigned long)SYSTEM_TICKS); + } + hwusb->stats.tx_notready_cnt++; + return -EINVAL; + } + hwusb->urb_write_ind = urb_write_ind; +#endif + return 0; +} + +static int +sdla_usb_txdata_encode (sdlahw_card_t *hwcard, unsigned char *writebuf, int len) +{ + sdlahw_usb_t *hwusb = NULL; int off, x = 0, ind, mod_no, tx_idle = 0; unsigned char data, start_bit; unsigned char *txdata[2]; - WAN_ASSERT(hw == NULL); - WAN_ASSERT(hw->hwcpu == NULL); - WAN_ASSERT(hw->hwcpu->hwcard == NULL); - hwcard = hw->hwcpu->hwcard; - DEBUG_TX("%s:%d: TX:%d (%d:%d)\n", - __FUNCTION__,__LINE__,MAX_USB_TX_LEN, - hwcard->u_usb.next_tx_ind, hwcard->u_usb.next_write_ind); - txdata[0] = hwcard->u_usb.writechunk[0]; - txdata[1] = hwcard->u_usb.writechunk[1]; - next_write_ind = hwcard->u_usb.next_write_ind; - memcpy(&hwcard->u_usb.writebuf[next_write_ind], &hwcard->u_usb.idlebuf[0], MAX_USB_TX_LEN); + WAN_ASSERT(hwcard == NULL); + hwusb = &hwcard->u_usb; + + txdata[0] = hwusb->writechunk[0]; + txdata[1] = hwusb->writechunk[1]; + memcpy(writebuf, &hwusb->idlebuf[0], MAX_USB_TX_LEN); for (x = 0; x < WP_USB_RXTX_CHUNKSIZE; x++) { for (mod_no = 0; mod_no < 2; mod_no++) { start_bit = 0x00; @@ -1265,96 +1370,102 @@ static int sdla_usb_tx_bh (sdlahw_t *hw) } ind = x * 4 + mod_no; - WP_USB_CTRL_ENCODE(&hwcard->u_usb.writebuf[next_write_ind], ind); + WP_USB_CTRL_ENCODE(writebuf, ind); /* write loq nibble */ - WP_USB_DATA_ENCODE(&hwcard->u_usb.writebuf[next_write_ind+ind], data); + WP_USB_DATA_ENCODE(&writebuf[ind], data); DEBUG_TX("TX: x:%d mod:%d ind:%d:%d data:%02X:%02X:%02X\n", x, mod_no, ind, ind+2, (unsigned char)data, - (unsigned char)hwcard->u_usb.writebuf[next_write_ind+ind], - (unsigned char)hwcard->u_usb.writebuf[next_write_ind+ind+2]); + (unsigned char)writebuf[ind], + (unsigned char)writebuf[ind+2]); } } - if (wan_skb_queue_len(&hwcard->u_usb.tx_cmd_list)){ + if (wan_skb_queue_len(&hwusb->tx_cmd_list)){ u8 *cmd; int cmd_len; netskb_t *skb; - skb = wan_skb_dequeue(&hwcard->u_usb.tx_cmd_list); + skb = wan_skb_dequeue(&hwusb->tx_cmd_list); cmd = wan_skb_data(skb); cmd_len = wan_skb_len(skb); off = 0; off++; for (x=0; x < cmd_len; x++,off++) { - WP_USB_CMD_ENCODE(&hwcard->u_usb.writebuf[next_write_ind+off*4], cmd[x]); + WP_USB_CMD_ENCODE(&writebuf[off*4], cmd[x]); DEBUG_TX("TX_CMD: off:%d byte:%02X %02X:%02X:%02X:%02X\n", off, cmd[x], - (unsigned char)hwcard->u_usb.writebuf[next_write_ind+off*4], - (unsigned char)hwcard->u_usb.writebuf[next_write_ind+off*4+1], - (unsigned char)hwcard->u_usb.writebuf[next_write_ind+off*4+2], - (unsigned char)hwcard->u_usb.writebuf[next_write_ind+off*4+3]); + (unsigned char)writebuf[off*4], + (unsigned char)writebuf[off*4+1], + (unsigned char)writebuf[off*4+2], + (unsigned char)writebuf[off*4+3]); } wan_skb_init(skb, 0); - wan_skb_queue_tail(&hwcard->u_usb.tx_cmd_free_list, skb); + wan_skb_queue_tail(&hwusb->tx_cmd_free_list, skb); } - - next_write_ind = (next_write_ind + MAX_USB_TX_LEN) % MAX_WRITE_BUF_LEN; - if (next_write_ind == hwcard->u_usb.next_tx_ind){ - DEBUG_USB("ERROR:%d: TX BH is too fast (%d:%ld)\n", - bhcount, - next_write_ind, - (unsigned long)SYSTEM_TICKS); - hwcard->u_usb.stats.tx_overrun_cnt++; - }else{ - hwcard->u_usb.next_write_ind = next_write_ind; - } - -#if 1 -{ - int urb_write_ind = (hwcard->u_usb.urb_write_ind + 1) % MAX_WRITE_URB_COUNT; - if (wan_test_bit(1, &hwcard->u_usb.datawrite[urb_write_ind].ready)){ - /* Update tx urb */ - hwcard->u_usb.datawrite[urb_write_ind].urb.transfer_buffer = &hwcard->u_usb.writebuf[hwcard->u_usb.next_tx_ind]; - hwcard->u_usb.next_tx_ind += MAX_USB_TX_LEN; - hwcard->u_usb.next_tx_ind = hwcard->u_usb.next_tx_ind % MAX_WRITE_BUF_LEN; - }else{ - /* Use previous urb for now and increment errors */ - DEBUG_USB("%s: [BH:%d:%d:%d]: TX is not ready (%ld)!\n", - hw->devname, bhcount,rxcount,txcount,(unsigned long)SYSTEM_TICKS); - hwcard->u_usb.stats.tx_overrun_cnt++; - } - wan_clear_bit(WP_USB_STATUS_TX_READY, &hwcard->u_usb.status); //sc->tx_ready = 0; - if (wp_usb_start_transfer(&hwcard->u_usb.datawrite[urb_write_ind])){ - DEBUG_EVENT("%s: Failed to program transmitter\n", hw->devname); - hwcard->u_usb.stats.tx_notready_cnt++; - }else{ - hwcard->u_usb.urb_write_ind = urb_write_ind; - } + return 0; } -#else - if (!wan_test_bit(WP_USB_STATUS_TX_READY, &hwcard->u_usb.status)){ - DEBUG_USB("%s: [BH:%d:%d:%d]: TX is not ready (%ld)!\n", - hw->devname, bhcount,rxcount,txcount,(unsigned long)SYSTEM_TICKS); - hwcard->u_usb.stats.tx_overrun_cnt++; +static int +sdla_usb_bh_rx (sdlahw_card_t *hwcard) +{ + sdlahw_usb_t *hwusb = NULL; + int rx_len; + u_int8_t readbuf[MAX_USB_RX_LEN]; + + WAN_ASSERT(hwcard == NULL); + hwusb = &hwcard->u_usb; + + DEBUG_USB("[BH-RX] %s:%d: RX:%d (%d:%d)\n", + __FUNCTION__,__LINE__,rx_len, + hwusb->next_read_ind, hwusb->next_rx_ind); + + rx_len = sdla_usb_rxdata_get(hwcard, &readbuf[0], MAX_USB_RX_LEN); + if (!rx_len){ + DEBUG_USB("%s: INTERNAL ERROR:%d: No data available!\n", + hwcard->name, (u32)SYSTEM_TICKS); + hwusb->stats.rx_underrun_cnt++; return -EINVAL; } - hwcard->u_usb.datawrite[0].urb.transfer_buffer = &hwcard->u_usb.writebuf[hwcard->u_usb.next_tx_ind]; - hwcard->u_usb.next_tx_ind += MAX_USB_TX_LEN; - hwcard->u_usb.next_tx_ind = hwcard->u_usb.next_tx_ind % MAX_WRITE_BUF_LEN; - wan_clear_bit(WP_USB_STATUS_TX_READY, &hwcard->u_usb.status); //sc->tx_ready = 0; - if (wp_usb_start_transfer(&hwcard->u_usb.datawrite[0])){ - DEBUG_USB("%s: [BH:%d]: Write cycle failed (%d:%d)\n", - hw->devname, bhcount, - hwcard->u_usb.next_tx_ind, hwcard->u_usb.next_write_ind); - hwcard->u_usb.stats.tx_notready_cnt++; + if (rx_len < MAX_USB_RX_LEN){ + DEBUG_USB("%s: ERROR: Not enough data (%d:%d:%d:%d)!\n", + hwcard->name, rx_len, + hwusb->next_read_ind, + hwusb->next_rx_ind, + MAX_READ_BUF_LEN); + hwusb->stats.rx_underrun_cnt++; + return 0; + } + + sdla_usb_rxdata_decode(hwcard, readbuf, MAX_USB_RX_LEN); + if (wan_test_bit(WP_USB_STATUS_RX_DATA_READY, &hwusb->status) && hwusb->isr_func){ + hwusb->isr_func(hwusb->isr_arg); + } + return 0; +} + + +static int sdla_usb_bh_tx (sdlahw_card_t *hwcard) +{ + sdlahw_usb_t *hwusb = NULL; + unsigned char writebuf[MAX_USB_TX_LEN]; + + WAN_ASSERT(hwcard == NULL); + hwusb = &hwcard->u_usb; + + if (hwusb->opmode == SDLA_USB_OPMODE_VOICE){ + DEBUG_USB("[BH-TX] %s:%d: TX:%d (%d:%d)\n", + __FUNCTION__,__LINE__,MAX_USB_TX_LEN, + hwusb->next_tx_ind, hwusb->next_write_ind); + + sdla_usb_txdata_encode(hwcard, writebuf, MAX_USB_TX_LEN); + + if (sdla_usb_txdata_prepare(hwcard, writebuf, MAX_USB_TX_LEN)){ + return -EINVAL; + } } -#endif - DEBUG_USB("%s: [BH:%d:%d:%d]: Tx is programmed!\n", - hw->devname, bhcount, rxcount, txcount); return 0; } @@ -1364,44 +1475,136 @@ static void sdla_usb_bh (unsigned long data) static void sdla_usb_bh (void *data, int pending) #endif { - sdlahw_t *hw = (sdlahw_t*)data; - sdlahw_card_t *hwcard = NULL; - wan_smp_flag_t flags; + sdlahw_card_t *hwcard = (sdlahw_card_t*)data; + sdlahw_usb_t *hwusb = NULL; +// wan_smp_flag_t flags; - WAN_ASSERT_VOID(hw == NULL); - WAN_ASSERT_VOID(hw->hwcpu == NULL); - WAN_ASSERT_VOID(hw->hwcpu->hwcard == NULL); - hwcard = hw->hwcpu->hwcard; - + WAN_ASSERT_VOID(hwcard == NULL); + hwusb = &hwcard->u_usb; DEBUG_TEST("%s:%d: ------------ BEGIN --------------: %ld\n", __FUNCTION__,__LINE__,(unsigned long)SYSTEM_TICKS); - wan_spin_lock_irq(&hwcard->u_usb.lock,&flags); - if (!wan_test_bit(WP_USB_STATUS_READY, &hwcard->u_usb.status)){ - goto usb_bh_done; + if (!wan_test_bit(WP_USB_STATUS_READY, &hwusb->status)){ + goto usb_bh_exit; } - if (wan_test_and_set_bit(WP_USB_STATUS_BH, &hwcard->u_usb.status)){ + //wan_spin_lock_irq(&hwusb->lock,&flags); + if (wan_test_and_set_bit(WP_USB_STATUS_BH, &hwusb->status)){ DEBUG_EVENT("%s: [BH:%ld]: Re-entry in USB BH!\n", - hw->devname, (unsigned long)SYSTEM_TICKS); + hwcard->name, (unsigned long)SYSTEM_TICKS); goto usb_bh_done; } bhcount++; /* receive path */ - sdla_usb_rx_bh(hw); + sdla_usb_bh_rx(hwcard); /* transmit path */ - sdla_usb_tx_bh(hw); + sdla_usb_bh_tx(hwcard); - wan_clear_bit(WP_USB_STATUS_BH, &hwcard->u_usb.status); + wan_clear_bit(WP_USB_STATUS_BH, &hwusb->status); usb_bh_done: - wan_spin_unlock_irq(&hwcard->u_usb.lock,&flags); - WAN_TASKLET_END((&hwcard->u_usb.bh_task)); + //wan_spin_unlock_irq(&hwusb->lock,&flags); + +usb_bh_exit: + WAN_TASKLET_END((&hwusb->bh_task)); DEBUG_TEST("%s: ------------ END -----------------: %ld\n", __FUNCTION__,(unsigned long)SYSTEM_TICKS); return; } +int sdlausb_syncverify(sdlahw_card_t *hwcard, int len) +{ + sdlahw_usb_t *hwusb = NULL; + unsigned char data; + + WAN_ASSERT(hwcard == NULL); + hwusb = &hwcard->u_usb; + if (!hwusb->rx_sync){ + + DEBUG_USB("%s: Searching for sync from %d...\n", + hwcard->name, hwusb->next_read_ind); + do { + if ((hwusb->readbuf[hwusb->next_read_ind] & 0x30) != 0x30){ + hwusb->next_read_ind = (hwusb->next_read_ind+1) % MAX_READ_BUF_LEN; + len--; + continue; + } + /* Found first sync condition */ + DEBUG_USB("%s: Got first sync condition at %d:%d!\n", + hwcard->name, + hwusb->next_read_ind, + hwusb->next_rx_ind); + if (len < 4) break; + data = WP_USB_CTRL_DECODE(&hwusb->readbuf[hwusb->next_read_ind]); + if (data == 0x7E){ + /* Found second sync condition */ + DEBUG_EVENT("%s: USB device is connected!\n", + hwcard->name); + DEBUG_USB("%s: Got in sync at %d:%d!\n", + hwcard->name, + hwusb->next_read_ind, + hwusb->next_rx_ind); + hwusb->rx_sync = 1; + break; + } + hwusb->next_read_ind = (hwusb->next_read_ind+4) % MAX_READ_BUF_LEN; + len -= 4; + }while(len); + //if (sc->next_read_ind >= MAX_READ_BUF_LEN){ + // sc->next_read_ind = sc->next_read_ind % MAX_READ_BUF_LEN; + //} + }else{ + if ((hwusb->readbuf[hwusb->next_read_ind] & 0x30) != 0x30){ + DEBUG_EVENT("%s: USB device is disconnected!\n", + hwcard->name); + DEBUG_USB("%s: WARNING: Got out of sync 1 at %d:%d (%02X)!\n", + hwcard->name, + hwusb->next_read_ind, hwusb->next_rx_ind, + (unsigned char)hwusb->readbuf[hwusb->next_read_ind]); + hwusb->stats.rx_sync_err_cnt++; + + hwusb->rx_sync = 0; + //sc->next_read_ind++; + hwusb->next_read_ind = (hwusb->next_read_ind+1) % MAX_READ_BUF_LEN; + return 0; + } + data = WP_USB_CTRL_DECODE(&hwusb->readbuf[hwusb->next_read_ind]); + if (data != 0x7E){ + DEBUG_EVENT("%s: USB device is disconnected!\n", + hwcard->name); + DEBUG_USB("%s: WARNING: Got out of sync 2 at %d:%d!\n", + hwcard->name, + hwusb->next_read_ind, + hwusb->next_rx_ind); + hwusb->stats.rx_sync_err_cnt++; + hwusb->rx_sync = 0; + //sc->next_read_ind++; + hwusb->next_read_ind = (hwusb->next_read_ind+1) % MAX_READ_BUF_LEN; + return 0; + } + + if (hwcard->core_rev >= 0x20){ + + if ((hwusb->readbuf[hwusb->next_read_ind+1] & 0x20) == 0x20){ + if (hwcard->core_rev != 0xFF && !hwusb->tx_sync){ + DEBUG_USB("%s: USB device is in sync!\n", + hwcard->name); + } + hwusb->tx_sync = 1; + }else{ + if (hwcard->core_rev != 0xFF && hwusb->tx_sync){ + DEBUG_USB("%s: USB device is out of sync (%02X)!\n", + hwcard->name, + (unsigned char)hwusb->readbuf[hwusb->next_read_ind+1]); + hwusb->stats.dev_sync_err_cnt++; + } + hwusb->tx_sync = 0; + } + } + } + return 1; +} + #if defined(LINUX26) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) void sdlausb_read_complete(struct urb *q, struct pt_regs *regs) #else @@ -1409,77 +1612,82 @@ void sdlausb_read_complete(struct urb *q) #endif { struct wan_urb *wurb = (struct wan_urb*)q->context; - sdlahw_t *hw = (sdlahw_t*)wurb->pvt; - sdlahw_card_t *hwcard = NULL; + sdlahw_card_t *hwcard = (sdlahw_card_t*)wurb->pvt; + sdlahw_usb_t *hwusb = NULL; int next_rx_ind = 0, next_rx_off = 0; - int len = 0; // actual_length = MAX_USB_RX_LEN; - wan_smp_flag_t flags; + int err, len = 0; // actual_length = MAX_USB_RX_LEN; +// wan_smp_flag_t flags; - WAN_ASSERT_VOID(hw == NULL); - WAN_ASSERT_VOID(hw->hwcpu == NULL); - WAN_ASSERT_VOID(hw->hwcpu->hwcard == NULL); - hwcard = hw->hwcpu->hwcard; - wan_spin_lock_irq(&hwcard->u_usb.lock,&flags); + WAN_ASSERT_VOID(hwcard == NULL); + hwusb = &hwcard->u_usb; + if (q->status){ + if (!(q->status == -ENOENT ||q->status == -ECONNRESET || q->status == -ESHUTDOWN)){ + DEBUG_EVENT("%s: ERROR: RX transaction failed (%d)!\n", + hwcard->name, q->status); + } + return; + } + //wan_spin_lock_irq(&hwusb->lock,&flags); rxcount++; - if (!wan_test_bit(WP_USB_STATUS_READY, &hwcard->u_usb.status)){ + if (!wan_test_bit(WP_USB_STATUS_READY, &hwusb->status)){ DEBUG_RX("%s: WARNING: RX USB core is not ready (%d:%ld)!\n", - hw->devname, rxcount, + hwcard->name, rxcount, (unsigned long)SYSTEM_TICKS); - hwcard->u_usb.stats.core_notready_cnt++; - wan_spin_unlock_irq(&hwcard->u_usb.lock,&flags); + hwusb->stats.core_notready_cnt++; + // wan_spin_unlock_irq(&hwusb->lock,&flags); return; } #if 0 if (q->actual_length < MAX_USB_RX_LEN){ - DEBUG_EVENT("%s: [RX:%d]: WARNING: Invalid Rx length (%d:%d)\n", - hw->devname, rxcount, - q->actual_length,MAX_USB_RX_LEN); - actual_length = q->actual_length; + DEBUG_EVENT("%s: [RX:%d]: WARNING: Invalid Rx length (%d:%d:%d)\n", + hwcard->name, rxcount, + q->actual_length,q->transfer_buffer_length, MAX_USB_RX_LEN); } #endif + DEBUG_RX("%s:%d: [RX:%d]: RX:%d:%02X %d:%02X %d:%02X (%ld)\n", - hw->devname, wurb->id, rxcount, + hwcard->name, wurb->id, rxcount, q->actual_length, ((unsigned char*)q->transfer_buffer)[0], - hwcard->u_usb.next_read_ind, (unsigned char)hwcard->u_usb.readbuf[hwcard->u_usb.next_read_ind], - hwcard->u_usb.next_rx_ind, (unsigned char)hwcard->u_usb.readbuf[hwcard->u_usb.next_rx_ind], + hwusb->next_read_ind, (unsigned char)hwusb->readbuf[hwusb->next_read_ind], + hwusb->next_rx_ind, (unsigned char)hwusb->readbuf[hwusb->next_rx_ind], (unsigned long)SYSTEM_TICKS); if (!q->actual_length) goto read_complete_done; - next_rx_ind = hwcard->u_usb.next_rx_ind + q->actual_length; - next_rx_off = hwcard->u_usb.next_rx_ind + q->actual_length * hwcard->u_usb.urbcount_read; + next_rx_ind = hwusb->next_rx_ind + q->actual_length; + next_rx_off = hwusb->next_rx_ind + q->actual_length * hwusb->urbcount_read; - if (hwcard->u_usb.next_rx_ind < hwcard->u_usb.next_read_ind){ + if (hwusb->next_rx_ind < hwusb->next_read_ind){ - if (next_rx_off > hwcard->u_usb.next_read_ind){ + if (next_rx_off > hwusb->next_read_ind){ DEBUG_USB("%s: ERROR:%ld:%d: RX BH is too slow %d:%d:%d (Reset:1)\n", - hw->devname, + hwcard->name, (unsigned long)SYSTEM_TICKS, rxcount, - hwcard->u_usb.next_read_ind,hwcard->u_usb.next_rx_ind, - q->actual_length*hwcard->u_usb.urbcount_read); - hwcard->u_usb.stats.rx_overrun_cnt++; - WAN_TASKLET_SCHEDULE((&hwcard->u_usb.bh_task)); + hwusb->next_read_ind,hwusb->next_rx_ind, + q->actual_length*hwusb->urbcount_read); + hwusb->stats.rx_overrun_cnt++; + WAN_TASKLET_SCHEDULE((&hwusb->bh_task)); goto read_complete_done; } next_rx_ind = next_rx_ind % MAX_READ_BUF_LEN; next_rx_off = next_rx_off % MAX_READ_BUF_LEN; - }else if (hwcard->u_usb.next_rx_ind > hwcard->u_usb.next_read_ind){ + }else if (hwusb->next_rx_ind > hwusb->next_read_ind){ if (next_rx_ind > MAX_READ_BUF_LEN){ - memcpy( &hwcard->u_usb.readbuf[0], - &hwcard->u_usb.readbuf[MAX_READ_BUF_LEN], + memcpy( &hwusb->readbuf[0], + &hwusb->readbuf[MAX_READ_BUF_LEN], next_rx_ind - MAX_READ_BUF_LEN); next_rx_off = next_rx_off % MAX_READ_BUF_LEN; - if (next_rx_off > hwcard->u_usb.next_read_ind){ + if (next_rx_off > hwusb->next_read_ind){ DEBUG_USB("%s: ERROR:%ld:%d: RX BH is too slow %d:%d:%d (Reset:2)\n", - hw->devname, + hwcard->name, (unsigned long)SYSTEM_TICKS, rxcount, - hwcard->u_usb.next_read_ind,hwcard->u_usb.next_rx_ind, - q->actual_length*hwcard->u_usb.urbcount_read); - hwcard->u_usb.stats.rx_overrun_cnt++; - WAN_TASKLET_SCHEDULE((&hwcard->u_usb.bh_task)); + hwusb->next_read_ind,hwusb->next_rx_ind, + q->actual_length*hwusb->urbcount_read); + hwusb->stats.rx_overrun_cnt++; + WAN_TASKLET_SCHEDULE((&hwusb->bh_task)); goto read_complete_done; } next_rx_ind = next_rx_ind % MAX_READ_BUF_LEN; @@ -1491,89 +1699,26 @@ void sdlausb_read_complete(struct urb *q) next_rx_ind = next_rx_ind % MAX_READ_BUF_LEN; next_rx_off = next_rx_off % MAX_READ_BUF_LEN; } - hwcard->u_usb.next_rx_ind = next_rx_ind; + + hwusb->next_rx_ind = next_rx_ind; wurb->next_off = next_rx_off; /* analyze data */ - if (hwcard->u_usb.next_rx_ind >= hwcard->u_usb.next_read_ind){ - len = hwcard->u_usb.next_rx_ind - hwcard->u_usb.next_read_ind; + if (hwusb->next_rx_ind >= hwusb->next_read_ind){ + len = hwusb->next_rx_ind - hwusb->next_read_ind; }else{ - len = MAX_READ_BUF_LEN - hwcard->u_usb.next_read_ind + hwcard->u_usb.next_rx_ind; + len = MAX_READ_BUF_LEN - hwusb->next_read_ind + hwusb->next_rx_ind; } - if (hwcard->u_usb.opmode == SDLA_USB_OPMODE_VOICE){ + if (hwusb->opmode == SDLA_USB_OPMODE_VOICE){ DEBUG_RX("[RX-] %s: RX:%d %d:%d\n", - hw->devname, len, hwcard->u_usb.next_read_ind, hwcard->u_usb.next_rx_ind); + hwcard->name, len, hwusb->next_read_ind, hwusb->next_rx_ind); if (len > 4){ - unsigned char data; - if (!hwcard->u_usb.rx_sync){ - - DEBUG_USB("%s: Searching for sync from %d...\n", - hw->devname, hwcard->u_usb.next_read_ind); - do { - if ((hwcard->u_usb.readbuf[hwcard->u_usb.next_read_ind] & 0x30) != 0x30){ - hwcard->u_usb.next_read_ind = (hwcard->u_usb.next_read_ind+1) % MAX_READ_BUF_LEN; - len--; - continue; - } - /* Found first sync condition */ - DEBUG_USB("%s: Got first sync condition at %d:%d!\n", - hw->devname, - hwcard->u_usb.next_read_ind, - hwcard->u_usb.next_rx_ind); - if (len < 4) break; - data = WP_USB_CTRL_DECODE(&hwcard->u_usb.readbuf[hwcard->u_usb.next_read_ind]); - if (data == 0x7E){ - /* Found second sync condition */ - DEBUG_EVENT("%s: USB device is connected!\n", - hw->devname); - DEBUG_USB("%s: Got in sync at %d:%d!\n", - hw->devname, - hwcard->u_usb.next_read_ind, - hwcard->u_usb.next_rx_ind); - hwcard->u_usb.rx_sync = 1; - break; - } - hwcard->u_usb.next_read_ind = (hwcard->u_usb.next_read_ind+4) % MAX_READ_BUF_LEN; - len -= 4; - }while(len); - //if (sc->next_read_ind >= MAX_READ_BUF_LEN){ - // sc->next_read_ind = sc->next_read_ind % MAX_READ_BUF_LEN; - //} - }else{ - if ((hwcard->u_usb.readbuf[hwcard->u_usb.next_read_ind] & 0x30) != 0x30){ - DEBUG_EVENT("%s: USB device is disconnected!\n", - hw->devname); - DEBUG_USB("%s: WARNING: Got out of sync 1 at %d:%d (%02X)!\n", - hw->devname, - hwcard->u_usb.next_read_ind, hwcard->u_usb.next_rx_ind, - (unsigned char)hwcard->u_usb.readbuf[hwcard->u_usb.next_read_ind]); - hwcard->u_usb.stats.rx_sync_err_cnt++; - - hwcard->u_usb.rx_sync = 0; - //sc->next_read_ind++; - hwcard->u_usb.next_read_ind = (hwcard->u_usb.next_read_ind+1) % MAX_READ_BUF_LEN; - goto read_complete_done; - } - data = WP_USB_CTRL_DECODE(&hwcard->u_usb.readbuf[hwcard->u_usb.next_read_ind]); - if (data != 0x7E){ - DEBUG_EVENT("%s: USB device is disconnected!\n", - hw->devname); - DEBUG_USB("%s: WARNING: Got out of sync 2 at %d:%d!\n", - hw->devname, - hwcard->u_usb.next_read_ind, - hwcard->u_usb.next_rx_ind); - hwcard->u_usb.stats.rx_sync_err_cnt++; - hwcard->u_usb.rx_sync = 0; - //sc->next_read_ind++; - hwcard->u_usb.next_read_ind = (hwcard->u_usb.next_read_ind+1) % MAX_READ_BUF_LEN; - goto read_complete_done; - } - } + sdlausb_syncverify(hwcard, len); } - if (len >= MAX_USB_RX_LEN){ - WAN_TASKLET_SCHEDULE((&hwcard->u_usb.bh_task)); + if (hwusb->rx_sync && len >= MAX_USB_RX_LEN){ + WAN_TASKLET_SCHEDULE((&hwusb->bh_task)); } } @@ -1582,16 +1727,19 @@ read_complete_done: SDLA_USB_NAME, q->dev, q->transfer_buffer); //q->dev = sc->dev; - q->transfer_buffer = &hwcard->u_usb.readbuf[wurb->next_off]; - if (wp_usb_start_transfer(wurb)){ - DEBUG_EVENT("%s: Failed to program receiver\n", - hw->devname); + q->transfer_buffer = &hwusb->readbuf[wurb->next_off]; + if ((err = wp_usb_start_transfer(wurb))){ + if (err != -ENOENT){ + DEBUG_EVENT("%s: Failed to program receiver (%ld)!\n", + hwcard->name, + (unsigned long)SYSTEM_TICKS); + } } DEBUG_RX("%s: [RX:%d:%d]: %s: %d:%d:%d!\n", hw->devname,wurb->id,rxcount, - hwcard->u_usb.next_read_ind, hwcard->u_usb.next_rx_ind, next_rx_off); - wan_spin_unlock_irq(&hwcard->u_usb.lock,&flags); + hwusb->next_read_ind, hwusb->next_rx_ind, next_rx_off); + //wan_spin_unlock_irq(&hwusb->lock,&flags); return; } @@ -1603,27 +1751,32 @@ void sdlausb_write_complete(struct urb *q) #endif { struct wan_urb *wurb = (struct wan_urb*)q->context; - sdlahw_t *hw = (sdlahw_t*)wurb->pvt; - sdlahw_card_t *hwcard = NULL; + sdlahw_card_t *hwcard = (sdlahw_card_t*)wurb->pvt; + sdlahw_usb_t *hwusb = NULL; int actual_length = MAX_USB_TX_LEN; - wan_smp_flag_t flags; +// wan_smp_flag_t flags; - WAN_ASSERT_VOID(hw == NULL); - WAN_ASSERT_VOID(hw->hwcpu == NULL); - WAN_ASSERT_VOID(hw->hwcpu->hwcard == NULL); - hwcard = hw->hwcpu->hwcard; + WAN_ASSERT_VOID(hwcard == NULL); + hwusb = &hwcard->u_usb; txcount++; - wan_spin_lock_irq(&hwcard->u_usb.lock,&flags); - if (!wan_test_bit(WP_USB_STATUS_READY, &hwcard->u_usb.status)){ + if (q->status){ + if (!(q->status == -ENOENT ||q->status == -ECONNRESET || q->status == -ESHUTDOWN)){ + DEBUG_EVENT("%s: ERROR: RX transaction failed (%d)!\n", + hwcard->name, q->status); + } + return; + } + //wan_spin_lock_irq(&hwusb->lock,&flags); + if (!wan_test_bit(WP_USB_STATUS_READY, &hwusb->status)){ DEBUG_USB("%s: WARNING: TX USB core is not ready (%d:%ld)!\n", - hw->devname, txcount, + hwcard->name, txcount, (unsigned long)SYSTEM_TICKS); - hwcard->u_usb.stats.core_notready_cnt++; - wan_spin_unlock_irq(&hwcard->u_usb.lock,&flags); + hwusb->stats.core_notready_cnt++; + // wan_spin_unlock_irq(&hwusb->lock,&flags); return; } - if (hwcard->u_usb.opmode == SDLA_USB_OPMODE_VOICE){ + if (hwusb->opmode == SDLA_USB_OPMODE_VOICE){ if (q->actual_length < MAX_USB_TX_LEN){ DEBUG_TEST("[TX]: WARNING: Invalid Tx length (%d:%d)\n", q->actual_length,MAX_USB_TX_LEN); @@ -1632,13 +1785,13 @@ void sdlausb_write_complete(struct urb *q) } /* Mark this urb as ready */ - wan_set_bit(1, &wurb->ready); - wan_set_bit(WP_USB_STATUS_TX_READY, &hwcard->u_usb.status); //sc->tx_ready = 1; + wan_set_bit(SDLA_URB_STATUS_READY, &wurb->ready); + wan_set_bit(WP_USB_STATUS_TX_READY, &hwusb->status); //sc->tx_ready = 1; DEBUG_TX("%s:%d: [TX:%d:%d] %d:%d (%d:%d)\n", - hw->devname, wurb->id, txcount, txcount, + hwcard->name, wurb->id, txcount, txcount, MAX_USB_TX_LEN,q->transfer_buffer_length, - hwcard->u_usb.next_tx_ind, hwcard->u_usb.next_write_ind); - wan_spin_unlock_irq(&hwcard->u_usb.lock,&flags); + hwusb->next_tx_ind, hwusb->next_write_ind); + //wan_spin_unlock_irq(&hwusb->lock,&flags); return; } @@ -1655,88 +1808,145 @@ void sdlausb_write_complete(struct urb *q) #define usb_endpoint_is_bulk_out(epd) \ (usb_endpoint_xfer_bulk((epd)) && usb_endpoint_dir_out(epd)) -static int sdla_prepare_transfer_urbs(sdlahw_t * hw, struct usb_interface *intf) +static int +sdla_prepare_transfer_urbs(sdlahw_card_t *hwcard, struct usb_interface *intf) { - sdlahw_card_t *hwcard = NULL; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; - struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS]; - struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS]; - int num_bulk_in = 0, num_bulk_out = 0; + sdlahw_usb_t *hwusb = NULL; int x, i = 0; - WAN_ASSERT(hw == NULL); - WAN_ASSERT(hw->hwcpu == NULL); - WAN_ASSERT(hw->hwcpu->hwcard == NULL); - hwcard = hw->hwcpu->hwcard; - - DEBUG_USB("%s: Preparing Transfer URBs...\n", hw->devname); + WAN_ASSERT(hwcard == NULL); + hwusb = &hwcard->u_usb; + DEBUG_USB("%s: Preparing Transfer URBs...\n", hwcard->name); /* descriptor matches, let's find the endpoints needed */ /* check out the endpoints */ iface_desc = intf->cur_altsetting; + +#if 1 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; if (usb_endpoint_is_bulk_in(endpoint)) { /* we found a bulk in endpoint */ - DEBUG_USB("%s: Found bulk in on endpoint %d\n", hw->devname, i); + DEBUG_USB("%s: Found bulk in on endpoint %d\n", + hwcard->name, i); + + for (x = 0; x < hwusb->urbcount_read; x++) { + usb_init_urb(&hwusb->dataread[x].urb); + usb_fill_bulk_urb ( + &hwusb->dataread[x].urb, + hwusb->usb_dev, + usb_rcvbulkpipe (hwusb->usb_dev, + endpoint->bEndpointAddress), + &hwusb->readbuf[MAX_USB_RX_LEN*x], + endpoint->wMaxPacketSize, + sdlausb_read_complete, + &hwusb->dataread[x]); //p + hwusb->dataread[x].next_off = MAX_USB_RX_LEN*x; + DEBUG_USB("%s: %d: Bulk In ENAddress:%X Len:%d (%d:%p)\n", + hwcard->name, x, + endpoint->bEndpointAddress, + endpoint->wMaxPacketSize, + hwusb->dataread[x].next_off, + &hwusb->readbuf[MAX_USB_RX_LEN*x]); + } + } + + if (usb_endpoint_is_bulk_out(endpoint)) { + /* we found a bulk out endpoint */ + DEBUG_USB("%s: Found bulk out on endpoint %d\n", + hwcard->name, i); + for (x = 0; x < hwusb->urbcount_write; x++) { + usb_init_urb(&hwusb->datawrite[x].urb); + usb_fill_bulk_urb ( + &hwusb->datawrite[x].urb, + hwusb->usb_dev, + usb_sndbulkpipe (hwusb->usb_dev, + endpoint->bEndpointAddress), + &hwusb->writebuf[MAX_USB_TX_LEN*x], + MAX_USB_TX_LEN, + sdlausb_write_complete, + &hwusb->datawrite[x]); //p + hwusb->datawrite[x].next_off = MAX_USB_TX_LEN*x; + DEBUG_USB("%s: %d: Bulk Out ENAddress:%X Len:%d (%d:%p)\n", + hwcard->name, x, + endpoint->bEndpointAddress, + MAX_USB_TX_LEN, + hwusb->datawrite[x].next_off, + &hwusb->writebuf[MAX_USB_TX_LEN*x]); + } + } + } + +#else + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + + if (usb_endpoint_is_bulk_in(endpoint)) { + /* we found a bulk in endpoint */ + DEBUG_USB("%s: Found bulk in on endpoint %d\n", + hwcard->name, i); bulk_in_endpoint[num_bulk_in] = endpoint; ++num_bulk_in; } if (usb_endpoint_is_bulk_out(endpoint)) { /* we found a bulk out endpoint */ - DEBUG_USB("%s: Found bulk out on endpoint %d\n", hw->devname, i); + DEBUG_USB("%s: Found bulk out on endpoint %d\n", + hwcard->name, i); bulk_out_endpoint[num_bulk_out] = endpoint; ++num_bulk_out; } } - for (x = 0; x < hwcard->u_usb.urbcount_read; x++) { + for (x = 0; x < hwusb->urbcount_read; x++) { /* set up the endpoint information */ for (i = 0; i < num_bulk_in; ++i) { endpoint = bulk_in_endpoint[i]; - usb_init_urb(&hwcard->u_usb.dataread[x].urb); + usb_init_urb(&hwusb->dataread[x].urb); usb_fill_bulk_urb ( - &hwcard->u_usb.dataread[x].urb, - hwcard->u_usb.usb_dev, - usb_rcvbulkpipe (hwcard->u_usb.usb_dev, + &hwusb->dataread[x].urb, + hwusb->usb_dev, + usb_rcvbulkpipe (hwusb->usb_dev, endpoint->bEndpointAddress), - &hwcard->u_usb.readbuf[MAX_USB_RX_LEN*x], - 64, //MAX_USB_RX_LEN, + &hwusb->readbuf[MAX_USB_RX_LEN*x], + endpoint->wMaxPacketSize, sdlausb_read_complete, - &hwcard->u_usb.dataread[x]); //p - hwcard->u_usb.dataread[x].next_off = MAX_USB_RX_LEN*x; - DEBUG_USB("%s: %d: Bulk Int ENAddress:%X Len:%d (%d:%p)\n", - hw->devname, x, - endpoint->bEndpointAddress,MAX_USB_RX_LEN, - hwcard->u_usb.dataread[x].next_off, - &hwcard->u_usb.readbuf[MAX_USB_RX_LEN*x]); + &hwusb->dataread[x]); //p + hwusb->dataread[x].next_off = MAX_USB_RX_LEN*x; + DEBUG_USB("%s: %d: Bulk In ENAddress:%X Len:%d (%d:%p)\n", + hwcard->name, x, + endpoint->bEndpointAddress, + endpoint->wMaxPacketSize, + hwusb->dataread[x].next_off, + &hwusb->readbuf[MAX_USB_RX_LEN*x]); } } - for (x = 0; x < hwcard->u_usb.urbcount_write; x++) { + for (x = 0; x < hwusb->urbcount_write; x++) { for (i = 0; i < num_bulk_out; ++i) { endpoint = bulk_out_endpoint[i]; - usb_init_urb(&hwcard->u_usb.datawrite[x].urb); + usb_init_urb(&hwusb->datawrite[x].urb); usb_fill_bulk_urb ( - &hwcard->u_usb.datawrite[x].urb, - hwcard->u_usb.usb_dev, - usb_sndbulkpipe (hwcard->u_usb.usb_dev, + &hwusb->datawrite[x].urb, + hwusb->usb_dev, + usb_sndbulkpipe (hwusb->usb_dev, endpoint->bEndpointAddress), - &hwcard->u_usb.writebuf[MAX_USB_TX_LEN*x], + &hwusb->writebuf[MAX_USB_TX_LEN*x], MAX_USB_TX_LEN, sdlausb_write_complete, - &hwcard->u_usb.datawrite[x]); //p - hwcard->u_usb.datawrite[x].next_off = MAX_USB_TX_LEN*x; + &hwusb->datawrite[x]); //p + hwusb->datawrite[x].next_off = MAX_USB_TX_LEN*x; DEBUG_USB("%s: %d: Bulk Out ENAddress:%X Len:%d (%d:%p)\n", - hw->devname, x, - endpoint->bEndpointAddress,MAX_USB_TX_LEN, - hwcard->u_usb.datawrite[x].next_off, - &hwcard->u_usb.writebuf[MAX_USB_TX_LEN*x]); + hwcard->name, x, + endpoint->bEndpointAddress, + MAX_USB_TX_LEN, + hwusb->datawrite[x].next_off, + &hwusb->writebuf[MAX_USB_TX_LEN*x]); } } - +#endif return 0; } @@ -1750,11 +1960,11 @@ static int wp_usb_start_transfer(struct wan_urb *wurb) ret = usb_submit_urb(q); #endif if (ret){ - return -EINVAL; + DEBUG_USB("%s: usb_submit %p returns %d (%s)\n", + __FUNCTION__, wurb, ret, + wan_test_bit(SDLA_URB_STATUS_READY, &wurb->ready)?"Ready":"Busy"); + return ret; } - wan_clear_bit(1, &wurb->ready); - /* Start checking for interrupts */ - //sdlausb_check_interrupt(p); return 0; } @@ -1799,17 +2009,12 @@ static int wp_usb_start_transfer(struct wan_urb *wurb) static int -sdla_usb_set_config(sdlahw_t *hw, u8 request, unsigned int *data, int size) +sdla_usb_set_config(sdlahw_card_t *hwcard, u8 request, unsigned int *data, int size) { - sdlahw_card_t *hwcard; __le32 *buf; int result, i, length; - WAN_ASSERT(hw == NULL); - SDLA_MAGIC(hw); - WAN_ASSERT(hw->hwcpu == NULL); - WAN_ASSERT(hw->hwcpu->hwcard == NULL); - hwcard = hw->hwcpu->hwcard; + WAN_ASSERT(hwcard == NULL); WAN_ASSERT(hwcard->u_usb.usb_dev == NULL); /* Number of integers required to contain the array */ @@ -1863,17 +2068,12 @@ sdla_usb_set_config(sdlahw_t *hw, u8 request, unsigned int *data, int size) * enough to hold 'size' bytes (with 4 bytes to each integer) */ static int -sdla_usb_get_config(sdlahw_t *hw, u8 request, unsigned int *data, int size) +sdla_usb_get_config(sdlahw_card_t *hwcard, u8 request, unsigned int *data, int size) { - sdlahw_card_t *hwcard = NULL; __le32 *buf; int result, i, length; - WAN_ASSERT(hw == NULL); - SDLA_MAGIC(hw); - WAN_ASSERT(hw->hwcpu == NULL); - WAN_ASSERT(hw->hwcpu->hwcard == NULL); - hwcard = hw->hwcpu->hwcard; + WAN_ASSERT(hwcard == NULL); WAN_ASSERT(hwcard->u_usb.usb_dev == NULL); /* Number of integers required to contain the array */ @@ -1916,243 +2116,345 @@ sdla_usb_get_config(sdlahw_t *hw, u8 request, unsigned int *data, int size) * without requiring an integer pointer */ static inline int -sdla_usb_set_config_single(sdlahw_t *hw, u8 request, unsigned int data) +sdla_usb_set_config_single(sdlahw_card_t *hwcard, u8 request, unsigned int data) { - return sdla_usb_set_config(hw, request, &data, 2); + return sdla_usb_set_config(hwcard, request, &data, 2); } - -int sdla_usb_setup(sdlahw_t *hw) +static int sdla_usb_search_rxsync(sdlahw_card_t *hwcard) { - sdlahw_card_t *hwcard; + int retry = 0; + + wait_just_a_bit(5*HZ, 0); + do{ + if (retry++ > SDLA_USBFXO_SYNC_RX_RETRIES) return -EINVAL; + wait_just_a_bit(SDLA_USBFXO_SYNC_DELAY, 0); + } while(!hwcard->u_usb.rx_sync); + return 0; +} + +static int sdla_usb_search_txsync(sdlahw_card_t *hwcard) +{ + int retry = 0; + do{ + if (retry++ > SDLA_USBFXO_SYNC_TX_RETRIES) return -EINVAL; + wait_just_a_bit(SDLA_USBFXO_SYNC_DELAY, 0); + } while(!hwcard->u_usb.tx_sync); + return 0; +} + + +static int sdla_usb_rxurb_reset(sdlahw_card_t *hwcard) +{ + sdlahw_usb_t *hwusb = NULL; + int x=0; + + WAN_ASSERT(hwcard == NULL); + hwusb = &hwcard->u_usb; + + for (x = 0; x < hwusb->urbcount_read; x++){ + usb_unlink_urb(&hwusb->dataread[x].urb); + usb_kill_urb(&hwusb->dataread[x].urb); + } + hwusb->next_rx_ind = 0; + hwusb->next_read_ind = 0; + for (x = 0; x < hwusb->urbcount_read; x++){ + hwusb->dataread[x].urb.transfer_buffer = &hwusb->readbuf[hwusb->next_rx_ind]; + if (wp_usb_start_transfer(&hwusb->dataread[x])) { + DEBUG_EVENT("%s: Failed to start RX:%d transfer!\n", + hwcard->name, x); + return -EINVAL; + } + } + return 0; +} + +static int sdla_usb_txurb_reset(sdlahw_card_t *hwcard) +{ + sdlahw_usb_t *hwusb = NULL; + int x=0; + + WAN_ASSERT(hwcard == NULL); + hwusb = &hwcard->u_usb; + + for (x = 0; x < hwusb->urbcount_write; x++){ + usb_unlink_urb(&hwusb->datawrite[x].urb); + usb_kill_urb(&hwusb->datawrite[x].urb); + } + hwusb->next_tx_ind = 0; + hwusb->next_write_ind = 0; + return 0; +} + +int sdla_usb_setup(sdlahw_card_t *hwcard, int new_usbdev) +{ + sdlahw_usb_t *hwusb = NULL; netskb_t *skb; int err, bits, x = 0, mod_no = 0; u8 data8; - WAN_ASSERT(hw == NULL); - SDLA_MAGIC(hw); - WAN_ASSERT(hw->hwcpu == NULL); - WAN_ASSERT(hw->hwcpu->hwcard == NULL); - hwcard = hw->hwcpu->hwcard; - + WAN_ASSERT(hwcard == NULL); + hwusb = &hwcard->u_usb; DEBUG_USB("%s: Creating private data for usb%s...\n", - hw->devname,hwcard->u_usb.bus_id); + hwcard->name,hwusb->bus_id); - WAN_TASKLET_INIT((&hwcard->u_usb.bh_task),0,sdla_usb_bh,hw); + if (!new_usbdev){ + DEBUG_EVENT("%s: Loading USB-FXO firmware code...", + hwcard->name); + wait_just_a_bit(SDLA_USBFXO_BL_DELAY, 0); + } + + WAN_TASKLET_INIT((&hwusb->bh_task), 0, sdla_usb_bh, hwcard); - WAN_IFQ_INIT(&hwcard->u_usb.rx_cmd_free_list, WP_USB_MAX_RX_CMD_QLEN); - WAN_IFQ_INIT(&hwcard->u_usb.rx_cmd_list, WP_USB_MAX_RX_CMD_QLEN); + hwusb->writebuf = wan_malloc(MAX_READ_BUF_LEN+MAX_USB_TX_LEN+1); + if (hwusb->writebuf == NULL){ + DEBUG_EVENT("%s: Failed to allocate TX buffer!\n", + hwcard->name); + return -ENOMEM; + } + memset(hwusb->writebuf,0x00,MAX_READ_BUF_LEN+MAX_USB_TX_LEN+1); + + hwusb->readbuf = wan_malloc(MAX_READ_BUF_LEN+MAX_USB_RX_LEN+1); + if (hwusb->readbuf == NULL){ + DEBUG_EVENT("%s: Failed to allocate RX buffer!\n", + hwcard->name); + return -ENOMEM; + } + memset(hwusb->readbuf,0x00,MAX_READ_BUF_LEN+MAX_USB_RX_LEN+1); + //memset(&hwusb->guard1[0],0x00,1000); + //memset(&hwusb->guard2[0],0x00,1000); + WAN_IFQ_INIT(&hwusb->rx_cmd_free_list, WP_USB_MAX_RX_CMD_QLEN); + WAN_IFQ_INIT(&hwusb->rx_cmd_list, WP_USB_MAX_RX_CMD_QLEN); for(x = 0; x < WP_USB_MAX_RX_CMD_QLEN; x++){ skb = wan_skb_alloc(10); if (!skb){ DEBUG_ERROR("%s: ERROR: Failed to allocate RX cmd buffer!\n", - hw->devname); + hwcard->name); goto cleanup; } - wan_skb_queue_tail(&hwcard->u_usb.rx_cmd_free_list, skb); - + wan_skb_queue_tail(&hwusb->rx_cmd_free_list, skb); } - WAN_IFQ_INIT(&hwcard->u_usb.tx_cmd_free_list, WP_USB_MAX_TX_CMD_QLEN); - WAN_IFQ_INIT(&hwcard->u_usb.tx_cmd_list, WP_USB_MAX_TX_CMD_QLEN); - for(x = 0; x < WP_USB_MAX_RX_CMD_QLEN; x++){ + WAN_IFQ_INIT(&hwusb->tx_cmd_free_list, WP_USB_MAX_TX_CMD_QLEN); + WAN_IFQ_INIT(&hwusb->tx_cmd_list, WP_USB_MAX_TX_CMD_QLEN); + for(x = 0; x < WP_USB_MAX_TX_CMD_QLEN; x++){ skb = wan_skb_alloc(10); if (!skb){ DEBUG_ERROR("%s: ERROR: Failed to allocate TX cmd buffer!\n", - hw->devname); + hwcard->name); goto cleanup; } - wan_skb_queue_tail(&hwcard->u_usb.tx_cmd_free_list, skb); + wan_skb_queue_tail(&hwusb->tx_cmd_free_list, skb); } - hwcard->u_usb.rxtx_len = WP_USB_RXTX_DATA_LEN; - hwcard->u_usb.rxtx_count = WP_USB_RXTX_DATA_COUNT; - hwcard->u_usb.rxtx_total_len = hwcard->u_usb.rxtx_len * hwcard->u_usb.rxtx_count; + hwusb->rxtx_len = WP_USB_RXTX_DATA_LEN; + hwusb->rxtx_count = WP_USB_RXTX_DATA_COUNT; + hwusb->rxtx_total_len = hwusb->rxtx_len * hwusb->rxtx_count; - hwcard->u_usb.rxtx_buf_len = hwcard->u_usb.rxtx_total_len * 4; - hwcard->u_usb.read_buf_len = hwcard->u_usb.rxtx_buf_len * (WP_USB_MAX_RW_COUNT + 2); - hwcard->u_usb.write_buf_len = hwcard->u_usb.rxtx_buf_len * (WP_USB_MAX_RW_COUNT + 2); + hwusb->rxtx_buf_len = hwusb->rxtx_total_len * 4; + hwusb->read_buf_len = hwusb->rxtx_buf_len * (WP_USB_MAX_RW_COUNT + 2); + hwusb->write_buf_len = hwusb->rxtx_buf_len * (WP_USB_MAX_RW_COUNT + 2); - wan_spin_lock_init(&hwcard->u_usb.cmd_lock,"usb_cmd"); - wan_spin_lock_irq_init(&hwcard->u_usb.lock,"usb_bh_lock"); - hwcard->u_usb.ctrl_idle_pattern = WP_USB_CTRL_IDLE_PATTERN; - if (sdla_usb_set_config_single(hw, CP2101_UART, UART_ENABLE)) { + wan_spin_lock_init(&hwusb->cmd_lock,"usb_cmd"); + wan_spin_lock_irq_init(&hwusb->lock,"usb_bh_lock"); + hwusb->ctrl_idle_pattern = WP_USB_CTRL_IDLE_PATTERN; + if (sdla_usb_set_config_single(hwcard, CP2101_UART, UART_ENABLE)) { DEBUG_ERROR("%s: ERROR: Unable to enable UART!\n", - hw->devname); + hwcard->name); goto cleanup; } - if (sdla_usb_set_config_single(hw, CP2101_BAUDRATE, (BAUD_RATE_GEN_FREQ / WP_USB_BAUD_RATE))){ + if (sdla_usb_set_config_single(hwcard, CP2101_BAUDRATE, (BAUD_RATE_GEN_FREQ / WP_USB_BAUD_RATE))){ DEBUG_EVENT( "%s: ERROR: Baud rate requested not supported by device (%d bps)!\n", - hw->devname, WP_USB_BAUD_RATE); + hwcard->name, WP_USB_BAUD_RATE); goto cleanup; } - sdla_usb_get_config(hw, CP2101_BITS, &bits, 2); + sdla_usb_get_config(hwcard, CP2101_BITS, &bits, 2); bits &= ~BITS_DATA_MASK; bits |= BITS_DATA_8; - if (sdla_usb_set_config(hw, CP2101_BITS, &bits, 2)){ + if (sdla_usb_set_config(hwcard, CP2101_BITS, &bits, 2)){ DEBUG_EVENT( "%s: ERROR: Number of data bits requested not supported by device (%02X)!\n", - hw->devname, bits); + hwcard->name, bits); goto cleanup; } - hwcard->u_usb.urbcount_read = MAX_READ_URB_COUNT; //4 - hwcard->u_usb.urb_read_ind = 0; - for (x = 0; x < hwcard->u_usb.urbcount_read; x++){ - hwcard->u_usb.dataread[x].id = x; - hwcard->u_usb.dataread[x].pvt = hw; - wan_set_bit(1, &hwcard->u_usb.datawrite[x].ready); + hwusb->urbcount_read = MAX_READ_URB_COUNT; //4 + hwusb->urb_read_ind = 0; + for (x = 0; x < hwusb->urbcount_read; x++){ + hwusb->dataread[x].id = x; + hwusb->dataread[x].pvt = hwcard; + wan_set_bit(SDLA_URB_STATUS_READY, &hwusb->datawrite[x].ready); } - hwcard->u_usb.urbcount_write = MAX_WRITE_URB_COUNT; //4 - hwcard->u_usb.urb_write_ind = 0; - for (x = 0; x < hwcard->u_usb.urbcount_write; x++){ - hwcard->u_usb.datawrite[x].id = x; - hwcard->u_usb.datawrite[x].pvt = hw; - wan_set_bit(1, &hwcard->u_usb.datawrite[x].ready); + hwusb->urbcount_write = MAX_WRITE_URB_COUNT; //4 + hwusb->urb_write_ind = 0; + for (x = 0; x < hwusb->urbcount_write; x++){ + hwusb->datawrite[x].id = x; + hwusb->datawrite[x].pvt = hwcard; + wan_set_bit(SDLA_URB_STATUS_READY, &hwusb->datawrite[x].ready); } - if (sdla_prepare_transfer_urbs(hw, hwcard->u_usb.usb_intf)) { + if (sdla_prepare_transfer_urbs(hwcard, hwusb->usb_intf)) { DEBUG_EVENT( "%s: Failed to prepare the urbs for transfer!\n", - hw->devname); + hwcard->name); goto cleanup; } - hwcard->u_usb.next_rx_ind = 0; - hwcard->u_usb.next_read_ind = 0; - hwcard->u_usb.next_tx_ind = 0; - hwcard->u_usb.next_write_ind = 0; + hwusb->next_rx_ind = 0; + hwusb->next_read_ind = 0; + hwusb->next_tx_ind = 0; + hwusb->next_write_ind = 0; /* Create dummy voice */ for(mod_no = 0; mod_no < 2; mod_no++){ - memset(&hwcard->u_usb.regs[mod_no][0], 0xFF, 110); + memset(&hwusb->regs[mod_no][0], 0xFF, 110); } /* init initial and idle buffer */ for (x=0; x < MAX_USB_TX_LEN;x++){ - hwcard->u_usb.writebuf[x] = idlebuf[x]; - hwcard->u_usb.idlebuf[x] = idlebuf[x]; + hwusb->writebuf[x] = idlebuf[x]; + hwusb->idlebuf[x] = idlebuf[x]; } - usb_set_intfdata(hwcard->u_usb.usb_intf, hw); - wan_set_bit(WP_USB_STATUS_READY, &hwcard->u_usb.status); + usb_set_intfdata(hwusb->usb_intf, hwcard); + hwcard->internal_used++; + hwcard->core_rev = 0xFF; + wan_set_bit(WP_USB_STATUS_READY, &hwusb->status); /* Verifing sync with USB-FXO device */ - hwcard->u_usb.opmode = SDLA_USB_OPMODE_VOICE; - for (x = 0; x < hwcard->u_usb.urbcount_read; x++){ - DEBUG_EVENT("%s: Start read sequence...\n", - hw->devname); - if (wp_usb_start_transfer(&hwcard->u_usb.dataread[x])) { + hwusb->opmode = SDLA_USB_OPMODE_VOICE; + for (x = 0; x < hwusb->urbcount_read; x++){ + if (wp_usb_start_transfer(&hwusb->dataread[x])) { DEBUG_EVENT( "%s: Failed to start RX:%d transfer!\n", - hw->devname, x); + hwcard->name, x); goto cleanup; } } - err = 0; - do{ - if (err++ > 10) break; - wait_just_a_bit(SDLA_USBFXO_READ_DELAY, 0); - } while(!hwcard->u_usb.rx_sync); + err = sdla_usb_search_rxsync(hwcard); + if (!err && hwusb->rx_sync){ - if (hwcard->u_usb.rx_sync){ + hwusb->opmode = SDLA_USB_OPMODE_VOICE; - hwcard->u_usb.opmode = SDLA_USB_OPMODE_VOICE; - + /* Waiting for USB device to sync */ + sdla_usb_search_txsync(hwcard); + /* Read hardware ID */ - err = sdla_usb_cpu_read(hw, SDLA_USB_CPU_REG_DEVICEID, &data8); - if (err){ - DEBUG_EVENT("%s: Failed to read USB Device ID (err=%d)!\n", - hw->devname, err); - goto cleanup; - } - if (data8 != 0x55){ - DEBUG_EVENT("%s: Failed to verify USB Device ID (%X:55)!\n", - hw->devname, data8); + err = __sdla_usb_cpu_read(hwcard, SDLA_USB_CPU_REG_DEVICEID, &data8); + if (data8 != SDLA_USB_DEVICEID){ + DEBUG_EVENT("%s: Failed to read USB Device ID (%02X:err=%d)!\n", + hwcard->name, data8, err); goto cleanup; } + DEBUG_USB("%s: Detected USB-FXO interface!\n", + hwcard->name); + /* Read hardware version */ - err = sdla_usb_cpu_read(hw, SDLA_USB_CPU_REG_HARDWAREVER, &data8); + err = __sdla_usb_cpu_read(hwcard, SDLA_USB_CPU_REG_HARDWAREVER, &data8); if (err){ DEBUG_EVENT("%s: Failed to read USB Hardware Version (err=%d)!\n", - hw->devname, err); + hwcard->name, err); goto cleanup; } - DEBUG_EVENT("%s: USB-FXO Hardware Version %d.%d!\n", - hw->devname, (data8 >> 4) & 0x0F, data8 & 0x0F); + hwusb->hw_rev = data8; /* Read firmware version */ - err = sdla_usb_cpu_read(hw, SDLA_USB_CPU_REG_FIRMWAREVER, &data8); + err = __sdla_usb_cpu_read(hwcard, SDLA_USB_CPU_REG_FIRMWAREVER, &data8); if (err){ DEBUG_EVENT("%s: Failed to read USB Firmware Version (err=%d)!\n", - hw->devname, err); + hwcard->name, err); goto cleanup; } - DEBUG_EVENT("%s: USB-FXO Firmware Version %d.%d!\n", - hw->devname, (data8 >> 4) & 0x0F, data8 & 0x0F); + hwcard->core_rev = data8; + + /* Read EC channels number */ + __sdla_usb_cpu_read(hwcard, SDLA_USB_CPU_REG_EC_NUM, &data8); + hwcard->hwec_chan_no = data8; + if (hwcard->core_rev < 0x20){ + /* Undefined register before ver 2.0 */ + hwcard->hwec_chan_no = 0x00; + /* TX Sync is not implemented in early version */ + hwusb->tx_sync = 1; + }else{ + if (!hwusb->tx_sync){ + DEBUG_EVENT("%s: USB device is out of sync!\n", + hwcard->name); + goto cleanup; + } + } + + /* Reset register to default values */ + __sdla_usb_cpu_write(hwcard, SDLA_USB_CPU_REG_CTRL, SDLA_USB_CPU_BIT_CTRL_RESET); + hwusb->reg_cpu_ctrl = 0x00; + + __sdla_usb_cpu_read(hwcard, SDLA_USB_CPU_REG_FIFO_STATUS, &data8); + __sdla_usb_cpu_read(hwcard, SDLA_USB_CPU_REG_UART_STATUS, &data8); + __sdla_usb_cpu_read(hwcard, SDLA_USB_CPU_REG_HOSTIF_STATUS, &data8); }else{ DEBUG_EVENT("%s: USB-FXO Device in Firmware Update mode...\n", - hw->devname); - hwcard->u_usb.opmode = SDLA_USB_OPMODE_API; - + hwcard->name); + hwusb->opmode = SDLA_USB_OPMODE_API; + hwusb->hw_rev = 0xFF; + hwcard->core_rev= 0xFF; } - sdla_usb_cpu_read(hw, SDLA_USB_CPU_REG_FIFO_STATUS, &data8); - sdla_usb_cpu_read(hw, SDLA_USB_CPU_REG_UART_STATUS, &data8); - sdla_usb_cpu_read(hw, SDLA_USB_CPU_REG_HOSTIF_STATUS, &data8); return 0; cleanup: - wan_clear_bit(WP_USB_STATUS_READY, &hwcard->u_usb.status); - WAN_IFQ_PURGE(&hwcard->u_usb.tx_cmd_free_list); - WAN_IFQ_DESTROY(&hwcard->u_usb.tx_cmd_free_list); - WAN_IFQ_PURGE(&hwcard->u_usb.rx_cmd_free_list); - WAN_IFQ_DESTROY(&hwcard->u_usb.rx_cmd_free_list); - WAN_TASKLET_KILL(&hwcard->u_usb.bh_task); - usb_set_intfdata(hwcard->u_usb.usb_intf, NULL); + wan_clear_bit(WP_USB_STATUS_READY, &hwusb->status); + WAN_IFQ_PURGE(&hwusb->tx_cmd_free_list); + WAN_IFQ_DESTROY(&hwusb->tx_cmd_free_list); + WAN_IFQ_PURGE(&hwusb->rx_cmd_free_list); + WAN_IFQ_DESTROY(&hwusb->rx_cmd_free_list); + WAN_TASKLET_KILL(&hwusb->bh_task); + if (usb_get_intfdata(hwusb->usb_intf)){ + hwcard->internal_used--; + usb_set_intfdata(hwusb->usb_intf, NULL); + } return -ENODEV; } -int sdla_usb_down(sdlahw_t *hw, int force) +int sdla_usb_down(sdlahw_card_t *hwcard, int force) { - sdlahw_card_t *hwcard; + sdlahw_usb_t *hwusb = NULL; int x = 0; - DEBUG_EVENT("%s: Releasing private data...\n", hw->devname); - WAN_ASSERT(hw == NULL); - WAN_ASSERT(hw->hwcpu == NULL); - WAN_ASSERT(hw->hwcpu->hwcard == NULL); - hwcard = hw->hwcpu->hwcard; + WAN_ASSERT(hwcard == NULL); + hwusb = &hwcard->u_usb; + DEBUG_EVENT("%s: Releasing private data...\n", hwcard->name); - wan_clear_bit(WP_USB_STATUS_READY, &hwcard->u_usb.status); + wan_clear_bit(WP_USB_STATUS_READY, &hwusb->status); + WAN_TASKLET_KILL(&hwusb->bh_task); /* Do not clear the structures if force=1 */ - if (force) return 0; - WAN_IFQ_PURGE(&hwcard->u_usb.tx_cmd_free_list); - WAN_IFQ_DESTROY(&hwcard->u_usb.tx_cmd_free_list); - WAN_IFQ_PURGE(&hwcard->u_usb.rx_cmd_free_list); - WAN_IFQ_DESTROY(&hwcard->u_usb.rx_cmd_free_list); - WAN_IFQ_PURGE(&hwcard->u_usb.tx_cmd_list); - WAN_IFQ_DESTROY(&hwcard->u_usb.tx_cmd_list); - WAN_IFQ_PURGE(&hwcard->u_usb.rx_cmd_list); - WAN_IFQ_DESTROY(&hwcard->u_usb.rx_cmd_list); + WAN_IFQ_PURGE(&hwusb->tx_cmd_free_list); + WAN_IFQ_DESTROY(&hwusb->tx_cmd_free_list); + WAN_IFQ_PURGE(&hwusb->rx_cmd_free_list); + WAN_IFQ_DESTROY(&hwusb->rx_cmd_free_list); + WAN_IFQ_PURGE(&hwusb->tx_cmd_list); + WAN_IFQ_DESTROY(&hwusb->tx_cmd_list); + WAN_IFQ_PURGE(&hwusb->rx_cmd_list); + WAN_IFQ_DESTROY(&hwusb->rx_cmd_list); - for (x = 0; x < hwcard->u_usb.urbcount_read; x++){ - usb_unlink_urb(&hwcard->u_usb.dataread[x].urb); - usb_kill_urb(&hwcard->u_usb.dataread[x].urb); + for (x = 0; x < hwusb->urbcount_read; x++){ + usb_unlink_urb(&hwusb->dataread[x].urb); + usb_kill_urb(&hwusb->dataread[x].urb); } - for (x = 0; x < hwcard->u_usb.urbcount_write; x++){ - usb_unlink_urb(&hwcard->u_usb.datawrite[x].urb); - usb_kill_urb(&hwcard->u_usb.datawrite[x].urb); + for (x = 0; x < hwusb->urbcount_write; x++){ + usb_unlink_urb(&hwusb->datawrite[x].urb); + usb_kill_urb(&hwusb->datawrite[x].urb); + } + if (hwusb->writebuf) wan_free(hwusb->writebuf); + if (hwusb->readbuf) wan_free(hwusb->readbuf); + if (usb_get_intfdata(hwusb->usb_intf)){ + hwcard->internal_used--; + usb_set_intfdata(hwusb->usb_intf, NULL); } - - WAN_TASKLET_KILL(&hwcard->u_usb.bh_task); - usb_set_intfdata(hwcard->u_usb.usb_intf, NULL); return 0; } diff --git a/patches/kdrivers/src/net/sdlamain.c b/patches/kdrivers/src/net/sdlamain.c index 46fe7c2..6204688 100644 --- a/patches/kdrivers/src/net/sdlamain.c +++ b/patches/kdrivers/src/net/sdlamain.c @@ -350,6 +350,8 @@ static int check_aft_conflicts (sdla_t* card,wandev_conf_t* conf, int*); static int wanpipe_register_fw_to_api(void); static int wanpipe_unregister_fw_from_api(void); +static int wan_add_device(void); +static int wan_delete_device(char*); /****** Global Data ********************************************************** * Note: All data must be explicitly initialized!!! @@ -371,6 +373,8 @@ typedef struct{ static int DBG_ARRAY_CNT; func_debug_t DEBUG_ARRAY[100]; +extern sdladrv_callback_t sdladrv_callback; + /******* Kernel Loadable Module Entry Points ********************************/ /*============================================================================ @@ -394,7 +398,6 @@ MODULE_LICENSE("GPL"); int __init wanpipe_init(void) { int i, cnt, err = 0; - sdla_t *card,*tmpcard; ncards=0; @@ -405,13 +408,16 @@ int __init wanpipe_init(void) /* Probe for wanpipe cards and return the number found */ DEBUG_EVENT("wanpipe: Probing for WANPIPE hardware.\n"); - ncards = sdla_hw_probe(); + cnt = sdla_hw_probe(); #if defined(CONFIG_PRODUCT_WANPIPE_USB) - ncards += sdla_get_hw_usb_adptr_cnt(); + cnt += sdla_get_hw_usb_adptr_cnt(); + /* Hot-plug is not supported yet */ + sdladrv_callback.add_device = wan_add_device; + sdladrv_callback.delete_device = wan_delete_device; #endif - if (ncards){ + if (cnt){ DEBUG_EVENT("wanpipe: Allocating maximum %i devices: wanpipe%i - wanpipe%i.\n", - ncards,1,ncards); + cnt,1,cnt); }else{ DEBUG_EVENT("wanpipe: No AFT/S514/S508 cards found, unloading modules!\n"); return -ENODEV; @@ -420,66 +426,13 @@ int __init wanpipe_init(void) card_list=NULL; wanpipe_debug=NULL; - for (i=0;ilist; - wan_free(tmpcard); - tmpcard=tmp; - } - card_list=NULL; - return -ENOMEM; - } - memset(tmpcard,0,sizeof(sdla_t)); - tmpcard->list=card_list; - card_list=tmpcard; + for (i = 0; i < cnt; i++){ + if (wan_add_device()) break; } - - cnt=0; - /* Register adapters with WAN router */ - for (card = card_list; card; card = card->list) { - - wan_device_t* wandev = &card->wandev; - - card->next = NULL; - sprintf(card->devname, "%s%d", drvname, ++cnt); - card->card_no=cnt; - wandev->magic = ROUTER_MAGIC; - wandev->name = card->devname; - wandev->priv = card; - wandev->enable_tx_int = 0; - wandev->setup = &setup; - wandev->shutdown = &shutdown; - wandev->ioctl = &ioctl; - wandev->debugging = &debugging; - err = register_wan_device(wandev); - if (err) { - DEBUG_EVENT("%s: %s registration failed with error %d!\n", - drvname, card->devname, err); - break; - } - } - if (cnt){ - ncards = cnt; /* adjust actual number of cards */ - }else { - sdla_t *tmp; - for (tmpcard=card_list;tmpcard;){ - unregister_wan_device(tmpcard->devname); - tmp=tmpcard->list; - wan_free(tmpcard); - tmpcard=tmp; - } - card_list=NULL; + if (ncards == 0){ DEBUG_EVENT("IN Init Module: NO Cards registered\n"); - err = -ENODEV; + return -ENODEV; } - - if (err){ - return err; - } - err=wanpipe_register_fw_to_api(); if (err){ @@ -512,21 +465,21 @@ int __init wanpipe_init(void) */ void __exit wanpipe_exit(void) { - sdla_t *tmpcard, *tmp; - wanpipe_unregister_fw_from_api(); - if (!card_list) + if (!card_list){ return; - - for (tmpcard=card_list;tmpcard;){ - unregister_wan_device(tmpcard->devname); - tmp=tmpcard->list; - wan_free(tmpcard); - tmpcard=tmp; } - + +#if defined(CONFIG_PRODUCT_WANPIPE_USB) + sdladrv_callback.add_device = NULL; + sdladrv_callback.delete_device = NULL; +#endif + /* Remove all devices */ + while(card_list){ + wan_delete_device(card_list->devname); + } card_list=NULL; wanpipe_codec_free(); @@ -541,6 +494,77 @@ module_exit(wanpipe_exit); /******* WAN Device Driver Entry Points *************************************/ +static int wan_add_device(void) +{ + sdla_t *card; + wan_device_t *wandev; + int err = 0; + + card = wan_kmalloc(sizeof(sdla_t)); + if (card == NULL){ + return -ENOMEM; + } + + memset(card, 0, sizeof(sdla_t)); + card->next = NULL; + sprintf(card->devname, "%s%d", drvname, ncards+1); + wandev = &card->wandev; + wandev->magic = ROUTER_MAGIC; + wandev->name = card->devname; + wandev->priv = card; + wandev->enable_tx_int = 0; + wandev->setup = &setup; + wandev->shutdown = &shutdown; + wandev->ioctl = &ioctl; + wandev->debugging = &debugging; + card->card_no = ncards+1; + err = register_wan_device(wandev); + if (err) { + DEBUG_EVENT("%s: %s registration failed with error %d!\n", + drvname, card->devname, err); + wan_free(card); + return -EINVAL; + } + + card->list=card_list; + card_list=card; + ncards++; + return 0; +} + +static int wan_delete_device(char *devname) +{ + sdla_t *card = NULL, *tmp; + + if (strcmp(card_list->devname, devname) == 0){ + card = card_list; + card_list = card_list->list; + }else{ + for (tmp = card_list; tmp; tmp = tmp->list){ + if (tmp->list && strcmp(tmp->list->devname, devname) == 0){ + card = tmp->list; + tmp->list = card->list; + card->list = NULL; + break; + } + } + if (card == NULL){ + DEBUG_EVENT("%s: Failed to find device in a list!\n", + devname); + return -EINVAL; + } + } + if (card->wandev.state != WAN_UNCONFIGURED){ + DEBUG_EVENT("%s: Device is still running!\n", + card->devname); + return -EINVAL; + } + + unregister_wan_device(card->devname); + wan_free(card); + return 0; +} + /*============================================================================ * Setup/configure WAN link driver. * o check adapter state @@ -1716,6 +1740,16 @@ STATIC WAN_IRQ_RETVAL sdla_isr (int irq, void* dev_id) if (card->isr){ WAN_IRQ_CALL(card->isr, (card), val); } + +#ifdef CONFIG_SMP + if (!spin_is_locked(&card->wandev.lock)) { + if (WAN_NET_RATELIMIT()) { + DEBUG_ERROR("%s:%s Critical error: driver locking has been corrupted, isr lock left unlocked!\n", + __FUNCTION__,__LINE__); + } + } +#endif + spin_unlock(&card->wandev.lock); WAN_IRQ_RETURN(val); @@ -1728,6 +1762,7 @@ STATIC WAN_IRQ_RETVAL sdla_isr (int irq, void* dev_id) if (card->isr){ WAN_IRQ_CALL(card->isr, (card), val); } + spin_unlock_irqrestore(&card->wandev.lock,flags); WAN_IRQ_RETURN(val); } diff --git a/patches/kdrivers/src/net/wanpipe_logger.c b/patches/kdrivers/src/net/wanpipe_logger.c index a49e6a1..b3c7d07 100644 --- a/patches/kdrivers/src/net/wanpipe_logger.c +++ b/patches/kdrivers/src/net/wanpipe_logger.c @@ -41,6 +41,8 @@ if(0){ \ (queue == &logger_api_dev.wp_event_list ? "wp_event_list":"wp_event_free_list"), \ wan_skb_queue_len(queue)); \ } + +#define WAN_MESSAGE_DISCARD_COUNT 1000 /*================================================================= * Macro Definitions @@ -96,9 +98,6 @@ typedef struct wp_logger_api_dev { void *cdev; u32 magic_no; -#if defined(__WINDOWS__) - LONG spin_flag; -#endif } wp_logger_api_dev_t; @@ -145,20 +144,12 @@ static u_int32_t* wp_logger_type_to_variable_ptr(u_int32_t logger_type) static void wp_logger_spin_lock_irq(wan_smp_flag_t *flags) { -#if defined(__WINDOWS__) - wan_lock_global_irq_spin_flag(&logger_api_dev.spin_flag, flags); -#else wan_spin_lock_irq(&logger_api_dev.lock, flags); -#endif } static void wp_logger_spin_unlock_irq(wan_smp_flag_t *flags) { -#if defined(__WINDOWS__) - wan_unlock_global_irq_spin_flag(&logger_api_dev.spin_flag, flags); -#else wan_spin_unlock_irq(&logger_api_dev.lock, flags); -#endif } static int wp_logger_increment_open_cnt(void) @@ -572,6 +563,8 @@ int wp_logger_repeating_message_filter(u_int32_t logger_type, u_int32_t evt_type if(!apply_filter){ /* consider it as NOT a repeating message */ + memset(previous_error_message, 0x00, sizeof(previous_error_message)); + repeating_error_message_counter = 0; return 0; } @@ -587,13 +580,25 @@ int wp_logger_repeating_message_filter(u_int32_t logger_type, u_int32_t evt_type if(!memcmp(previous_error_message, current_error_message, sizeof(current_error_message))){ - ++repeating_error_message_counter; - /* every 100 messages print the repeating message counter */ - if((repeating_error_message_counter % 100 == 0)){ - wp_snprintf(tmp_message_buf, sizeof(tmp_message_buf), - "* Message repeated %d times.\n", repeating_error_message_counter); - wp_logger_input(logger_type, evt_type, tmp_message_buf); + /* Every WAN_MESSAGE_DISCARD_COUNT messages print the repeating message + * and the counter how many times it was repeated. */ + + if(!(repeating_error_message_counter % WAN_MESSAGE_DISCARD_COUNT)){ + + if (repeating_error_message_counter) { + + /* print the repeating message */ + wp_logger_input(logger_type, evt_type, current_error_message); + + /* and say how many times it was repeated. */ + wp_snprintf(tmp_message_buf, sizeof(tmp_message_buf), + "* Message repeated %d times.\n", repeating_error_message_counter); + wp_logger_input(logger_type, evt_type, tmp_message_buf); + } } + + ++repeating_error_message_counter; + /* is IS a repeating message */ return 1; @@ -606,6 +611,7 @@ int wp_logger_repeating_message_filter(u_int32_t logger_type, u_int32_t evt_type wp_logger_input(logger_type, evt_type, tmp_message_buf); repeating_error_message_counter = 0; } + /* store current message for comparison with a future message */ memcpy(previous_error_message, current_error_message, sizeof(current_error_message)); @@ -680,7 +686,7 @@ int wp_logger_create(void) /* Already initialized. */ return 0; } - + memset(&logger_api_dev, 0, sizeof(wp_logger_api_dev_t)); logger_api_dev.magic_no = WANPIPE_MAGIC; diff --git a/patches/kdrivers/src/net/wanpipe_multppp.c b/patches/kdrivers/src/net/wanpipe_multppp.c index 94885b3..97b42d7 100644 --- a/patches/kdrivers/src/net/wanpipe_multppp.c +++ b/patches/kdrivers/src/net/wanpipe_multppp.c @@ -1060,12 +1060,12 @@ static int del_if (wan_device_t* wandev, netdevice_t* dev) /* TE1 - Unconfiging, only on shutdown */ if (IS_TE1_CARD(card)) { - if (card->wandev.fe_iface.pre_release){ - card->wandev.fe_iface.pre_release(&card->fe); - } if (card->wandev.fe_iface.unconfig){ card->wandev.fe_iface.unconfig(&card->fe); } + if (card->wandev.fe_iface.post_unconfig){ + card->wandev.fe_iface.post_unconfig(&card->fe); + } } return 0; } diff --git a/patches/kdrivers/src/net/wanpipe_tdm_api.c b/patches/kdrivers/src/net/wanpipe_tdm_api.c index 38cfd53..a3e7c5e 100644 --- a/patches/kdrivers/src/net/wanpipe_tdm_api.c +++ b/patches/kdrivers/src/net/wanpipe_tdm_api.c @@ -88,8 +88,8 @@ #define MAX_TDM_API_CHANNELS 32 static int wp_tdmapi_global_cnt=0; -static u8 *rx_gains; -static u8 *tx_gains; +static u8 *rx_gains=NULL; +static u8 *tx_gains=NULL; static wanpipe_tdm_api_dev_t tdmapi_ctrl; /*============================================================== @@ -102,7 +102,7 @@ static int wp_tdmapi_write_msg(void *obj , netskb_t *skb, wp_api_hdr_t *hdr); static int wp_tdmapi_release(void *obj); static void wp_tdmapi_report_rbsbits(void* card_id, int channel, unsigned char rbsbits); -static void wp_tdmapi_report_alarms(void* card_id, unsigned long te_alarm); +static void wp_tdmapi_report_alarms(void* card_id, uint32_t te_alarm); static void wp_tdmapi_tone(void* card_id, wan_event_t*); static void wp_tdmapi_hook(void* card_id, wan_event_t*); static void wp_tdmapi_ringtrip(void* card_id, wan_event_t*); @@ -121,7 +121,6 @@ static int wanpipe_tdm_api_event_ioctl(wanpipe_tdm_api_dev_t*, wanpipe_api_cmd_t static wanpipe_tdm_api_dev_t *wp_tdmapi_search(sdla_t *card, int fe_chan); static int wanpipe_tdm_api_handle_event(wanpipe_tdm_api_dev_t *tdm_api, netskb_t *skb); -static int wp_tdmapi_push_to_bh_queue(wanpipe_tdm_api_dev_t *tdm_api, netskb_t *skb); static int wp_tdmapi_unreg_notify_ctrl(wanpipe_tdm_api_dev_t *tdm_api); #if defined(__LINUX__) @@ -253,19 +252,11 @@ static void wp_tdmapi_init_buffs(wanpipe_tdm_api_dev_t *tdm_api, int option) } if (option == WP_API_FLUSH_ALL || option == WP_API_FLUSH_EVENT) { - /* The global Ctrl device does NOT use event_free_list */ - if (tdm_api == &tdmapi_ctrl) { - while((skb=wan_skb_dequeue(&tdm_api->wp_event_list))) { - wan_skb_init(skb,hdr_sz); - wan_skb_trim(skb,0); - wan_skb_queue_tail(&tdm_api->wp_dealloc_list,skb); - } - } else { - while((skb=wan_skb_dequeue(&tdm_api->wp_event_list))) { - wan_skb_init(skb,hdr_sz); - wan_skb_trim(skb,0); - wan_skb_queue_tail(&tdm_api->wp_event_free_list,skb); - } + + while((skb=wan_skb_dequeue(&tdm_api->wp_event_list))) { + wan_skb_init(skb,hdr_sz); + wan_skb_trim(skb,0); + wan_skb_queue_tail(&tdm_api->wp_event_free_list,skb); } } @@ -419,6 +410,7 @@ static int wp_tdmapi_reg_globals(void) wp_tdmapi_fops.write = NULL; wp_tdmapi_fops.poll = wp_tdmapi_poll; + /* initialize global ctrl dev */ { wanpipe_cdev_t *cdev; wanpipe_tdm_api_dev_t *tdm_api; @@ -449,10 +441,16 @@ static int wp_tdmapi_reg_globals(void) wan_set_bit(0,&tdm_api->init); wan_spin_lock_init(&tdm_api->lock, "ctrldev_lock"); + wan_spin_lock_init(&tdm_api->irq_lock, "ctrldev_irq_lock"); cdev->dev_ptr=&tdmapi_ctrl; tdm_api->cdev=cdev; + err=wp_tdmapi_alloc_q(tdm_api, &tdm_api->wp_event_free_list, WP_TDM_API_EVENT_MAX_LEN, WP_TDM_MAX_CTRL_EVENT_Q_LEN); + if (err) { + return err; + } + memcpy(&cdev->ops, &wp_tdmapi_fops, sizeof(wanpipe_cdev_ops_t)); err=wanpipe_cdev_tdm_ctrl_create(cdev); @@ -502,12 +500,16 @@ static void wp_ctrl_dev_delete(void) static int wp_tdmapi_unreg_globals(void) { - DEBUG_EVENT("%s(): Unregistering Global API Devices!\n",__FUNCTION__); + WAN_DEBUG_FUNC_START; + + DEBUG_TEST("%s(): Unregistering Global API Devices!\n",__FUNCTION__); #if !defined(__WINDOWS__) wanpipe_wandev_timer_free(); #endif + DEBUG_TDMAPI("%s(): Unregistering Clrl Devices!\n",__FUNCTION__); + wp_ctrl_dev_delete(); if (tx_gains) { @@ -519,6 +521,8 @@ static int wp_tdmapi_unreg_globals(void) rx_gains=NULL; } + WAN_DEBUG_FUNC_END; + return 0; } @@ -535,6 +539,7 @@ int wanpipe_tdm_api_reg(wanpipe_tdm_api_dev_t *tdm_api) wanpipe_tdm_api_card_dev_t *tdm_card_dev=NULL; wan_spin_lock_init(&tdm_api->lock, "wan_tdmapi_lock"); + wan_spin_lock_init(&tdm_api->irq_lock, "wan_tdmapi_irq_lock"); if (wp_tdmapi_global_cnt == 0){ err=wp_tdmapi_reg_globals(); @@ -587,6 +592,17 @@ int wanpipe_tdm_api_reg(wanpipe_tdm_api_dev_t *tdm_api) if (max_timeslot > tdm_card_dev->max_timeslots) { tdm_card_dev->max_timeslots=max_timeslot; } + + /* Calculate number of timeslots this channel has. + SPAN mode versus CHAN. We cannot assume 1 time slot */ + for (i=0;i<32;i++) { + if (wan_test_bit(i,&tdm_api->active_ch)) { + tdm_api->timeslots++; + } + } + } else { + /* Just initialize for hdlc channels */ + tdm_api->timeslots=1; } wan_skb_queue_init(&tdm_api->wp_rx_list); @@ -614,8 +630,10 @@ int wanpipe_tdm_api_reg(wanpipe_tdm_api_dev_t *tdm_api) goto tdm_api_reg_error_exit; } + /* Default initialization */ tdm_api->cfg.rx_queue_sz =WP_TDM_MAX_RX_Q_LEN; tdm_api->tx_channelized =0; + tdm_api->buffer_multiplier = 1; DEBUG_TDMAPI("%s(): usr_period: %d, hw_mtu_mru: %d\n", __FUNCTION__, tdm_api->cfg.usr_period, tdm_api->cfg.hw_mtu_mru); @@ -692,7 +710,11 @@ int wanpipe_tdm_api_reg(wanpipe_tdm_api_dev_t *tdm_api) } if (tdm_api->cfg.idle_flag == 0) { + if (tdm_api->cfg.hw_tdm_coding == WP_MULAW) { tdm_api->cfg.idle_flag=0xFF; + } else { + tdm_api->cfg.idle_flag=0xD5; + } } } @@ -708,8 +730,8 @@ int wanpipe_tdm_api_reg(wanpipe_tdm_api_dev_t *tdm_api) sprintf(tmp_name,"wanpipe%d_if%d",tdm_api->tdm_span,tdm_api->tdm_chan); - DEBUG_TDMAPI("%s: Configuring TDM API NAME=%s Qlen=%i\n", - card->devname,tmp_name, tdm_api->cfg.tx_queue_sz); + DEBUG_TDMAPI("%s: Configuring TDM API NAME=%s Qlen=%i TS=%i\n", + card->devname,tmp_name, tdm_api->cfg.tx_queue_sz, tdm_api->timeslots); /* Initialize Event Callback functions */ card->wandev.event_callback.rbsbits = NULL; /*wp_tdmapi_rbsbits;*/ @@ -860,6 +882,8 @@ int wanpipe_tdm_api_unreg(wanpipe_tdm_api_dev_t *tdm_api) sdla_t *card = tdm_api->card; int err; + WAN_DEBUG_FUNC_START; + wan_set_bit(WP_TDM_DOWN,&tdm_api->critical); if (wan_test_bit(0,&tdm_api->used)) { @@ -884,7 +908,7 @@ int wanpipe_tdm_api_unreg(wanpipe_tdm_api_dev_t *tdm_api) #if defined(WAN_TASKQ_STOP) err=WAN_TASKQ_STOP((&tdm_api->wp_api_task)); - DEBUG_EVENT("%s: %s\n",tdm_api->name, err?"TASKQ Successfully Stopped":"TASKQ Not Running"); + DEBUG_TDMAPI("%s: %s: %s\n",card->devname, tdm_api->name, err?"TASKQ Successfully Stopped":"TASKQ Not Running"); #endif wp_tdmapi_unreg_notify_ctrl(tdm_api); @@ -899,11 +923,6 @@ int wanpipe_tdm_api_unreg(wanpipe_tdm_api_dev_t *tdm_api) tdm_api->cdev=NULL; } - wp_tdmapi_global_cnt--; - if (wp_tdmapi_global_cnt == 0) { - wp_tdmapi_unreg_globals(); - } - if (card->tdm_api_dev) { wanpipe_tdm_api_card_dev_t *tdm_card_dev = card->tdm_api_dev; @@ -925,16 +944,25 @@ int wanpipe_tdm_api_unreg(wanpipe_tdm_api_dev_t *tdm_api) card->hw_iface.hw_unlock(card->hw,&smp_flags1); } - wan_free(card->tdm_api_dev); card->tdm_api_dev=NULL; + wan_free(tdm_card_dev); } } + wp_tdmapi_global_cnt--; + if (wp_tdmapi_global_cnt == 0) { + wp_tdmapi_unreg_globals(); + } + + WAN_DEBUG_FUNC_END; + return 0; } int wanpipe_tdm_api_kick(wanpipe_tdm_api_dev_t *tdm_api) { + int rc=0; + if (tdm_api == NULL || !wan_test_bit(0,&tdm_api->init)){ return -ENODEV; } @@ -947,9 +975,18 @@ int wanpipe_tdm_api_kick(wanpipe_tdm_api_dev_t *tdm_api) } } } else { - wp_tdm_api_start(tdm_api); - if (wan_test_bit(0,&tdm_api->used)) { - wp_wakeup_tx_tdmapi(tdm_api); + /* By default tdm_api->buffer_multiplier is set to 1 therefore we + can use it to check it tx is available */ + if (tdm_api->write_hdlc_check) { + rc=tdm_api->write_hdlc_check(tdm_api->chan, 0, tdm_api->buffer_multiplier); + } + if (rc == 0 || + wan_skb_queue_len(&tdm_api->wp_rx_list) >= tdm_api->buffer_multiplier || + wan_skb_queue_len(&tdm_api->wp_event_list)) { + wp_tdm_api_start(tdm_api); + if (wan_test_bit(0,&tdm_api->used)) { + wp_wakeup_tx_tdmapi(tdm_api); + } } } @@ -1071,6 +1108,7 @@ static int wp_tdmapi_open(void *obj) cnt = wp_tdm_inc_open_cnt(tdm_api); if (cnt == 1) { + wp_tdmapi_init_buffs(tdm_api, WP_API_FLUSH_ALL); tdm_api->rx_gain=NULL; @@ -1094,13 +1132,17 @@ static int gread_cnt=0; static int wp_tdmapi_read_msg(void *obj , netskb_t **skb_ptr, wp_api_hdr_t *hdr, int count) { wanpipe_tdm_api_dev_t *tdm_api = (wanpipe_tdm_api_dev_t*)obj; - netskb_t *skb; + netskb_t *skb=NULL; wan_smp_flag_t irq_flags; sdla_t *card; int rx_q_len=0; u8 *buf; + if (tdm_api == NULL || !wan_test_bit(0,&tdm_api->init) || !wan_test_bit(0,&tdm_api->used) || !hdr) { + if (hdr) { + hdr->wp_api_hdr_operation_status = SANG_STATUS_GENERAL_ERROR; + } return -ENODEV; } @@ -1123,10 +1165,86 @@ static int wp_tdmapi_read_msg(void *obj , netskb_t **skb_ptr, wp_api_hdr_t *hdr, irq_flags=0; - wptdm_os_lock_irq(&card->wandev.lock,&irq_flags); - skb=wan_skb_dequeue(&tdm_api->wp_rx_list); - rx_q_len = wan_skb_queue_len(&tdm_api->wp_rx_list); - wptdm_os_unlock_irq(&card->wandev.lock,&irq_flags); + if (tdm_api->buffer_multiplier > 1) { + netskb_t *nskb; + char * buf, *u_buf; + int single_len; + int multiplier=tdm_api->buffer_multiplier; + int i; + + wptdm_os_lock_irq(&card->wandev.lock,&irq_flags); + + if (wan_skb_queue_len(&tdm_api->wp_rx_list) < multiplier) { + wptdm_os_unlock_irq(&card->wandev.lock,&irq_flags); + DEBUG_ERROR("%s: %s:%d: Error: Rx queue len %i: multiplier %i mismatch\n", + tdm_api->name,__FUNCTION__,__LINE__,wan_skb_queue_len(&tdm_api->wp_rx_list),multiplier); + hdr->wp_api_hdr_operation_status = SANG_STATUS_NO_DATA_AVAILABLE; + return -ENOBUFS; + } + + skb=wan_skb_dequeue(&tdm_api->wp_rx_list); + if (!skb) { + wptdm_os_unlock_irq(&card->wandev.lock,&irq_flags); + DEBUG_ERROR("%s: %s:%d: Error rx queue emtpy on first skb: multiplier %i\n", + tdm_api->name,__FUNCTION__,__LINE__,multiplier); + hdr->wp_api_hdr_operation_status = SANG_STATUS_NO_DATA_AVAILABLE; + return -ENOBUFS; + } + + wptdm_os_unlock_irq(&card->wandev.lock,&irq_flags); + + /* This section must be unlocked because we are allocating memory */ + single_len = (wan_skb_len(skb)-sizeof(wp_api_hdr_t)); + nskb=wan_skb_kalloc(wan_skb_len(skb)+(single_len*multiplier)); + if (!nskb) { + hdr->wp_api_hdr_operation_status = SANG_STATUS_NO_DATA_AVAILABLE; + return -ENOMEM; + } + + buf=wan_skb_put(nskb,sizeof(wp_api_hdr_t)+single_len); + u_buf=wan_skb_data(skb); + memcpy(buf,u_buf,sizeof(wp_api_hdr_t)+single_len); + + wptdm_os_lock_irq(&card->wandev.lock,&irq_flags); + + wan_skb_queue_tail(&tdm_api->wp_dealloc_list,skb); + skb=NULL; + + /* Count 1 less then multiplier because we already pulled one buffer above */ + for (i=1;iwp_rx_list); + if (!skb) { + wptdm_os_unlock_irq(&card->wandev.lock,&irq_flags); + DEBUG_ERROR("%s:%d: Error rx queue emtpy on %i skb - multiplier %i\n", + __FUNCTION__,__LINE__,i+1,multiplier); + wan_skb_free(nskb); + wan_skb_free(skb); + hdr->wp_api_hdr_operation_status = SANG_STATUS_NO_DATA_AVAILABLE; + return -ENOBUFS; + } + + u_buf=wan_skb_data(skb); + u_buf = &u_buf[sizeof(wp_api_hdr_t)]; + + buf=wan_skb_put(nskb,single_len); + memcpy(buf,u_buf,single_len); + + wan_skb_queue_tail(&tdm_api->wp_dealloc_list,skb); + skb=NULL; + } + + skb=nskb; + rx_q_len = wan_skb_queue_len(&tdm_api->wp_rx_list); + wptdm_os_unlock_irq(&card->wandev.lock,&irq_flags); + + } else { + + wptdm_os_lock_irq(&card->wandev.lock,&irq_flags); + skb=wan_skb_dequeue(&tdm_api->wp_rx_list); + rx_q_len = wan_skb_queue_len(&tdm_api->wp_rx_list); + wptdm_os_unlock_irq(&card->wandev.lock,&irq_flags); + } + if (!skb){ hdr->wp_api_hdr_operation_status = SANG_STATUS_NO_DATA_AVAILABLE; return -ENOBUFS; @@ -1145,11 +1263,10 @@ static int wp_tdmapi_read_msg(void *obj , netskb_t **skb_ptr, wp_api_hdr_t *hdr, } #endif - if (count < (int)(wan_skb_len(skb) - sizeof(wp_api_hdr_t)) || + if (count < (int)(wan_skb_len(skb)) || + wan_skb_len(skb) < sizeof(wp_api_hdr_t)){ - wan_skb_len(skb) < sizeof(wp_api_hdr_t)){ - - DEBUG_ERROR("%s:%d TDMAPI READ: Error: Count=%i < Skb=%i < HDR=%i Critical Error\n", + DEBUG_ERROR("%s:%d User API Error: User Rx Len=%i < Driver Rx Len=%i (hdr=%i). User API must increase expected rx lenght!\n", __FUNCTION__,__LINE__,count,wan_skb_len(skb),sizeof(wp_api_hdr_t)); wan_skb_free(skb); hdr->wp_api_hdr_operation_status = SANG_STATUS_BUFFER_TOO_SMALL; @@ -1160,7 +1277,7 @@ static int wp_tdmapi_read_msg(void *obj , netskb_t **skb_ptr, wp_api_hdr_t *hdr, /* copy header info (such as time stamp) */ memcpy(hdr, buf, sizeof(wp_api_hdr_t)); - + if (WPTDM_SPAN_OP_MODE(tdm_api) || tdm_api->hdlc_framing) { /* do nothing */ @@ -1168,16 +1285,17 @@ static int wp_tdmapi_read_msg(void *obj , netskb_t **skb_ptr, wp_api_hdr_t *hdr, } else { netskb_t *tmp_skb; - /* Allocate a rx another free skb frame */ - tmp_skb=wan_skb_alloc(WP_TDM_API_MAX_LEN); + /* Allocate another free skb for RX */ + tmp_skb=wan_skb_kalloc(WP_TDM_API_MAX_LEN); if (tmp_skb) { wan_skb_init(tmp_skb,sizeof(wp_api_hdr_t)); wan_skb_trim(tmp_skb,0); + wptdm_os_lock_irq(&card->wandev.lock,&irq_flags); wan_skb_queue_tail(&tdm_api->wp_rx_free_list,tmp_skb); + wptdm_os_unlock_irq(&card->wandev.lock,&irq_flags); } } - hdr->wp_api_rx_hdr_number_of_frames_in_queue = (u8)rx_q_len; hdr->wp_api_rx_hdr_max_queue_length = (u8)tdm_api->cfg.rx_queue_sz; @@ -1185,6 +1303,8 @@ static int wp_tdmapi_read_msg(void *obj , netskb_t **skb_ptr, wp_api_hdr_t *hdr, hdr->wp_api_hdr_data_length = wan_skb_len(skb)-sizeof(wp_api_hdr_t); if (wan_skb_len(skb) >= sizeof(wp_api_hdr_t)) { + /* Copy back the updated header info into the skb header + section. */ memcpy(buf,hdr,sizeof(wp_api_hdr_t)); } else { DEBUG_ERROR("%s: Internal Error: Rx Data Invalid %i\n",tdm_api->name,wan_skb_len(skb)); @@ -1193,11 +1313,11 @@ static int wp_tdmapi_read_msg(void *obj , netskb_t **skb_ptr, wp_api_hdr_t *hdr, *skb_ptr = skb; //NENAD - DEBUG_TEST("%s: RX Q=%i RX Q MAX=%i SIZE=%i\n", + DEBUG_TEST("%s: RX Q=%i RX Q MAX=%i SIZE=%i %p\n", tdm_api->name, hdr->wp_api_rx_hdr_number_of_frames_in_queue, hdr->wp_api_rx_hdr_max_queue_length, - wan_skb_len(skb)); + wan_skb_len(skb), skb); return 0; @@ -1206,7 +1326,7 @@ static int wp_tdmapi_read_msg(void *obj , netskb_t **skb_ptr, wp_api_hdr_t *hdr, } -static int wp_tdmapi_tx(wanpipe_tdm_api_dev_t *tdm_api, netskb_t *skb, wp_api_hdr_t *hdr) +static int wp_tdmapi_tx (wanpipe_tdm_api_dev_t *tdm_api, netskb_t *skb, wp_api_hdr_t *hdr) { int err=-EINVAL; @@ -1217,14 +1337,83 @@ static int wp_tdmapi_tx(wanpipe_tdm_api_dev_t *tdm_api, netskb_t *skb, wp_api_h return -EINVAL; } - if (tdm_api->write_hdlc_frame) { - err=tdm_api->write_hdlc_frame(tdm_api->chan,skb, hdr); + if (tdm_api->buffer_multiplier > 1) { + + netskb_t *nskb; + int len,i; + char *buf; + char *u_buf=wan_skb_data(skb); + + + if (tdm_api->write_hdlc_check) { + int rc=tdm_api->write_hdlc_check(tdm_api->chan, 0, tdm_api->buffer_multiplier); + if (rc) { + DEBUG_ERROR("%s: Error: %s() Write check failed for multiplier %i\n", + tdm_api->name, __FUNCTION__,tdm_api->buffer_multiplier); + err=-EINVAL; + goto wp_tdmapi_tx_exit; + } + } + + if ((wan_skb_len(skb) % tdm_api->buffer_multiplier) != 0) { + DEBUG_ERROR("%s: Error: %s() buf size %i is not divisable by multiplier %i\n", + tdm_api->name, __FUNCTION__,wan_skb_len(skb),tdm_api->buffer_multiplier); + err=-EINVAL; + goto wp_tdmapi_tx_exit; + } + + len = wan_skb_len(skb) / tdm_api->buffer_multiplier; + + for (i=0;ibuffer_multiplier;i++) { + + nskb=wan_skb_kalloc(len+sizeof(wp_api_hdr_t)); + if (!nskb) { + err = -ENOMEM; + break; + } + + buf=wan_skb_put(nskb,len); + memcpy(buf,&u_buf[i*len],len); + + if (tdm_api->write_hdlc_frame) { + err=tdm_api->write_hdlc_frame(tdm_api->chan,nskb,hdr); + if (err) { + if (WAN_NET_RATELIMIT()) { + DEBUG_ERROR("%s: Error: %s() write_hdlc_frame failed on multiple %i/%i len=%i\n", + tdm_api->name, __FUNCTION__,i+1,tdm_api->buffer_multiplier,len); + } + wan_skb_free(nskb); + break; + } + } else { + wan_skb_free(nskb); + DEBUG_ERROR("%s: Error: %s() tdm_api->write_hdlc_frame is NULL: critical\n", + tdm_api->name, __FUNCTION__); + err=-EINVAL; + break; + } + nskb=NULL; + } + + /* Free the orignal copy of the skb */ + if (err==0) { + wan_skb_free(skb); + skb=NULL; + } + } else { - DEBUG_ERROR("%s: Error: %s() tdm_api->write_hdlc_frame is NULL: critical\n", - tdm_api->name, __FUNCTION__); - return -EINVAL; + + if (tdm_api->write_hdlc_frame) { + err=tdm_api->write_hdlc_frame(tdm_api->chan,skb, hdr); + } else { + DEBUG_ERROR("%s: Error: %s() tdm_api->write_hdlc_frame is NULL: critical\n", + tdm_api->name, __FUNCTION__); + err=-EINVAL; + } } +wp_tdmapi_tx_exit: + if (err == -EBUSY) { /* Busy condition */ hdr->wp_api_hdr_operation_status = SANG_STATUS_DEVICE_BUSY; @@ -1275,6 +1464,7 @@ static int wp_tdmapi_write_msg(void *obj, netskb_t *skb, wp_api_hdr_t *hdr) if (tdm_api == NULL || !wan_test_bit(0,&tdm_api->init) || !wan_test_bit(0,&tdm_api->used)){ return -ENODEV; } + if (tdm_api == &tdmapi_ctrl) { hdr->wp_api_hdr_operation_status = SANG_STATUS_INVALID_DEVICE; WP_AFT_CHAN_ERROR_STATS(tdm_api->cfg.stats,tx_errors); @@ -1306,12 +1496,21 @@ static int wp_tdmapi_write_msg(void *obj, netskb_t *skb, wp_api_hdr_t *hdr) return -EINVAL; } - if (WPTDM_SPAN_OP_MODE(tdm_api) || tdm_api->hdlc_framing) { + if (tdm_api->buffer_multiplier > 1) { + + if ((wan_skb_len(skb) - sizeof(wp_api_hdr_t)) % tdm_api->buffer_multiplier != 0 ) { + DEBUG_ERROR("%s: Error: TDM API Tx packet len %i not divisible by multiple %i\n", + tdm_api->name, wan_skb_len(skb), tdm_api->buffer_multiplier); + hdr->wp_api_hdr_operation_status =SANG_STATUS_TX_DATA_TOO_LONG; + WP_AFT_CHAN_ERROR_STATS(tdm_api->cfg.stats,tx_errors); + return -EFBIG; + } + + } else if (WPTDM_SPAN_OP_MODE(tdm_api) || tdm_api->hdlc_framing) { if (wan_skb_len(skb) > (int)(tdm_api->cfg.usr_mtu_mru + sizeof(wp_api_hdr_t))) { - if (WAN_NET_RATELIMIT()) { - DEBUG_ERROR("%s: Error: TDM API Tx packet too big %d Max=%d\n", + DEBUG_ERROR("%s: Error: TDM API Tx packet too big %d Max=%d\n", tdm_api->name,wan_skb_len(skb), (tdm_api->cfg.usr_mtu_mru + sizeof(wp_api_hdr_t))); - } + hdr->wp_api_hdr_operation_status =SANG_STATUS_TX_DATA_TOO_LONG; WP_AFT_CHAN_ERROR_STATS(tdm_api->cfg.stats,tx_errors); return -EFBIG; @@ -1444,23 +1643,25 @@ static int wp_tdmapi_release(void *obj) wan_clear_bit(0,&tdm_api->used); wp_wakeup_rx_tdmapi(tdm_api); - wan_spin_lock(&tdm_api->lock,&flag); + wan_mutex_lock(&tdm_api->lock,&flag); tdm_api->cfg.rbs_rx_bits=-1; tdm_api->cfg.rbs_tx_bits=-1; - wan_spin_unlock(&tdm_api->lock,&flag); + wan_mutex_unlock(&tdm_api->lock,&flag); } return 0; } + static int wan_skb_push_to_ctrl_event (netskb_t *skb) { wanpipe_tdm_api_dev_t *tdm_api = &tdmapi_ctrl; netskb_t *ctrl_skb; + wan_smp_flag_t flags; - if (!skb || !tdm_api) { + if (!skb) { DEBUG_ERROR("TDMAPI: Error: Null skb argument!\n"); return -ENODEV; } @@ -1468,10 +1669,30 @@ static int wan_skb_push_to_ctrl_event (netskb_t *skb) if (!wan_test_bit(0,&tdm_api->used)) { return -EBUSY; } + + wan_spin_lock_irq(&tdm_api->irq_lock, &flags); + ctrl_skb=wan_skb_dequeue(&tdm_api->wp_event_free_list); + wan_spin_unlock_irq(&tdm_api->irq_lock, &flags); - ctrl_skb=wan_skb_copy(skb); if (ctrl_skb){ + + int len = wan_skb_len(skb); + u8 *buf; + if (len > wan_skb_tailroom(ctrl_skb)) { + + DEBUG_ERROR("TDMAPI: Error: TDM API CTRL Event Buffer Overflow Elen=%i Max=%i!\n", + len,wan_skb_tailroom(ctrl_skb)); + + WP_AFT_CHAN_ERROR_STATS(tdm_api->cfg.stats,rx_events_dropped); + return -EFAULT; + } + buf=wan_skb_put(ctrl_skb,len); + memcpy(buf,wan_skb_data(skb),len); + + wan_spin_lock_irq(&tdm_api->irq_lock, &flags); wanpipe_tdm_api_handle_event(tdm_api,ctrl_skb); + wan_spin_unlock_irq(&tdm_api->irq_lock, &flags); + } else { WP_AFT_CHAN_ERROR_STATS(tdm_api->cfg.stats,rx_events_dropped); } @@ -1539,7 +1760,7 @@ static unsigned int wp_tdmapi_poll(void *obj) wan_spin_lock_irq(&card->wandev.lock,&irq_flags); /* Tx Poll */ - if (!wan_test_bit(0,&tdm_api->cfg.tx_disable)){ + if (!wan_test_bit(0,&tdm_api->cfg.tx_disable)) { if (tdm_api->tx_channelized) { if (wan_skb_queue_len(&tdm_api->wp_tx_list) < (int)tdm_api->cfg.tx_queue_sz) { wp_tdm_api_start(tdm_api); @@ -1548,18 +1769,14 @@ static unsigned int wp_tdmapi_poll(void *obj) } else { rc=1; + /* tdm_api->buffer_multiplir is by default 1 so we can use it to check + for available buffers */ if (tdm_api->write_hdlc_check) { - rc=tdm_api->write_hdlc_check(tdm_api->chan, 0); + rc=tdm_api->write_hdlc_check(tdm_api->chan, 0, tdm_api->buffer_multiplier); } - if (!is_tdm_api_stopped(tdm_api) || rc == 0 ){ -#if 0 - if (rc == 0 && is_tdm_api_stopped(tdm_api)) { -#warning "NENAD" - DEBUG_EVENT("%s: POLL is_tdm_api_stopped()=%i but rc=%i\n", - tdmapi->name,is_tdm_api_stopped(tdm_api),rc); - } -#endif + if (rc == 0) { + /* Wake up the user application tx available */ wp_tdm_api_start(tdm_api); ret |= POLLOUT | POLLWRNORM; } @@ -1567,9 +1784,12 @@ static unsigned int wp_tdmapi_poll(void *obj) } /* Rx Poll */ - if (!wan_test_bit(0,&tdm_api->cfg.rx_disable) && - wan_skb_queue_len(&tdm_api->wp_rx_list)) { - ret |= POLLIN | POLLRDNORM; + if (!wan_test_bit(0,&tdm_api->cfg.rx_disable)) { + /* tdm_api->buffer_multiplir is by default 1 so we can use it to check + for available buffers */ + if (wan_skb_queue_len(&tdm_api->wp_rx_list) >= tdm_api->buffer_multiplier) { + ret |= POLLIN | POLLRDNORM; + } } if (wan_skb_queue_len(&tdm_api->wp_event_list)) { @@ -1584,6 +1804,18 @@ static unsigned int wp_tdmapi_poll(void *obj) static int wanpipe_tdm_api_handle_event(wanpipe_tdm_api_dev_t *tdm_api, netskb_t *skb) { + wp_api_event_t *p_tdmapi_event = NULL; + wan_time_t sec; /* windows note: must use wan_time_t when calling wan_get_timestamp() + * because it take 64 bit paramter 1. */ + wan_suseconds_t usec; + + p_tdmapi_event = (wp_api_event_t*)wan_skb_data(skb); + + wan_get_timestamp(&sec, &usec); + + p_tdmapi_event->time_stamp_sec = sec; + p_tdmapi_event->time_stamp_usec = usec; + wan_skb_queue_tail(&tdm_api->wp_event_list,skb); tdm_api->cfg.stats.rx_events++; wp_wakeup_event_tdmapi(tdm_api); @@ -1651,7 +1883,9 @@ static int wanpipe_tdm_api_ioctl_handle_tdm_api_cmd(wanpipe_tdm_api_dev_t *tdm_a DEBUG_TDMAPI("%s: TDM API CMD: %i CMD Size=%i HDR Size=%i Even Size=%i\n", tdm_api->name,cmd,sizeof(wanpipe_api_cmd_t),sizeof(wp_api_hdr_t), sizeof(wp_api_event_t)); - wan_spin_lock(&tdm_api->lock,&flags); + wan_mutex_lock(&tdm_api->lock,&flags); + + /* Commands for HDLC Device */ if (tdm_api->hdlc_framing) { switch (cmd) { @@ -1669,6 +1903,14 @@ static int wanpipe_tdm_api_ioctl_handle_tdm_api_cmd(wanpipe_tdm_api_dev_t *tdm_a case WP_API_CMD_DRIVER_VERSION: case WP_API_CMD_FIRMWARE_VERSION: case WP_API_CMD_CPLD_VERSION: + case WP_API_CMD_FLUSH_BUFFERS: + case WP_API_CMD_FLUSH_RX_BUFFERS: + case WP_API_CMD_FLUSH_TX_BUFFERS: + case WP_API_CMD_FLUSH_EVENT_BUFFERS: + case WP_API_CMD_SET_TX_Q_SIZE: + case WP_API_CMD_GET_TX_Q_SIZE: + case WP_API_CMD_GET_RX_Q_SIZE: + case WP_API_CMD_SET_RX_Q_SIZE: break; default: DEBUG_EVENT("%s: Invalid TDM API HDLC CMD %i\n", tdm_api->name,cmd); @@ -1678,15 +1920,22 @@ static int wanpipe_tdm_api_ioctl_handle_tdm_api_cmd(wanpipe_tdm_api_dev_t *tdm_a } } + /* Commands for CTRL Device */ + if (tdm_api == &tdmapi_ctrl) { + wan_smp_flag_t irq_flags; + /* Note that in case of tdmapi_ctrl the lock has already been taken above so no need to lock here */ err=-EOPNOTSUPP; switch (cmd) { case WP_API_CMD_READ_EVENT: + + wan_spin_lock_irq(&tdm_api->irq_lock,&irq_flags); skb=wan_skb_dequeue(&tdm_api->wp_event_list); + wan_spin_unlock_irq(&tdm_api->irq_lock,&irq_flags); if (!skb){ usr_tdm_api.result=SANG_STATUS_NO_DATA_AVAILABLE; err=-ENOBUFS; @@ -1695,12 +1944,18 @@ static int wanpipe_tdm_api_ioctl_handle_tdm_api_cmd(wanpipe_tdm_api_dev_t *tdm_a memcpy(&usr_tdm_api.event, wan_skb_data(skb), sizeof(wp_api_event_t)); - wan_skb_free(skb); + wan_skb_init(skb,sizeof(wp_api_hdr_t)); + wan_skb_trim(skb,0); + + wan_spin_lock_irq(&tdm_api->irq_lock,&irq_flags); + wan_skb_queue_tail(&tdm_api->wp_event_free_list,skb); + wan_spin_unlock_irq(&tdm_api->irq_lock,&irq_flags); + err=0; break; default: - DEBUG_EVENT("%s: Invalid TDM API for CTRL DEVICE %i\n", tdm_api->name,cmd); + DEBUG_WARNING("%s: Warning: Invalid TDM API cmd=%d for CTRL DEVICE\n", tdm_api->name, cmd); usr_tdm_api.result=SANG_STATUS_OPTION_NOT_SUPPORTED; err=-EOPNOTSUPP; break; @@ -1709,6 +1964,8 @@ static int wanpipe_tdm_api_ioctl_handle_tdm_api_cmd(wanpipe_tdm_api_dev_t *tdm_a goto tdm_api_exit; } + /* Commands for TDM API Device */ + switch (cmd) { case WP_API_CMD_OPEN_CNT: @@ -1726,17 +1983,11 @@ static int wanpipe_tdm_api_ioctl_handle_tdm_api_cmd(wanpipe_tdm_api_dev_t *tdm_a case WP_API_CMD_SET_USR_PERIOD: - if (WPTDM_SPAN_OP_MODE(tdm_api)) { - usr_tdm_api.result=SANG_STATUS_OPTION_NOT_SUPPORTED; - err=-EOPNOTSUPP; - goto tdm_api_exit; - } - if (usr_tdm_api.usr_period >= 10 && (usr_tdm_api.usr_period % 10) == 0 && usr_tdm_api.usr_period <= 1000) { - usr_tdm_api.usr_mtu_mru = usr_tdm_api.usr_period*tdm_api->cfg.hw_mtu_mru; + usr_tdm_api.usr_mtu_mru = usr_tdm_api.usr_period*tdm_api->cfg.hw_mtu_mru*tdm_api->buffer_multiplier*tdm_api->timeslots; } else { usr_tdm_api.result=SANG_STATUS_INVALID_PARAMETER; @@ -1747,11 +1998,12 @@ static int wanpipe_tdm_api_ioctl_handle_tdm_api_cmd(wanpipe_tdm_api_dev_t *tdm_a } usr_tdm_api.usr_mtu_mru = wanpipe_codec_calc_new_mtu(tdm_api->cfg.tdm_codec, - usr_tdm_api.usr_mtu_mru); + usr_tdm_api.usr_mtu_mru)*tdm_api->buffer_multiplier*tdm_api->timeslots; + tdm_api->cfg.usr_period = usr_tdm_api.usr_period; tdm_api->cfg.usr_mtu_mru = usr_tdm_api.usr_mtu_mru; - tdm_api->mtu_mru = tdm_api->cfg.usr_period*tdm_api->cfg.hw_mtu_mru+sizeof(wp_api_hdr_t); + tdm_api->mtu_mru = tdm_api->cfg.usr_period*tdm_api->cfg.hw_mtu_mru*tdm_api->timeslots+sizeof(wp_api_hdr_t); break; @@ -1786,7 +2038,7 @@ static int wanpipe_tdm_api_ioctl_handle_tdm_api_cmd(wanpipe_tdm_api_dev_t *tdm_a if (usr_tdm_api.tdm_codec == WP_NONE) { - usr_tdm_api.usr_mtu_mru = tdm_api->cfg.hw_mtu_mru * tdm_api->cfg.usr_period; + usr_tdm_api.usr_mtu_mru = tdm_api->cfg.hw_mtu_mru * tdm_api->cfg.usr_period * tdm_api->buffer_multiplier * tdm_api->timeslots; } else { wp_codec_ops = WANPIPE_CODEC_OPS[tdm_api->cfg.hw_tdm_coding][usr_tdm_api.tdm_codec]; @@ -1799,7 +2051,7 @@ static int wanpipe_tdm_api_ioctl_handle_tdm_api_cmd(wanpipe_tdm_api_dev_t *tdm_a goto tdm_api_exit; } usr_tdm_api.usr_mtu_mru = wanpipe_codec_calc_new_mtu(usr_tdm_api.tdm_codec, - tdm_api->cfg.usr_mtu_mru); + tdm_api->cfg.usr_mtu_mru) * tdm_api->buffer_multiplier * tdm_api->timeslots; } tdm_api->cfg.usr_mtu_mru=usr_tdm_api.usr_mtu_mru; @@ -1859,10 +2111,7 @@ static int wanpipe_tdm_api_ioctl_handle_tdm_api_cmd(wanpipe_tdm_api_dev_t *tdm_a case WP_API_CMD_ENABLE_HWEC: if (card && card->wandev.ec_enable) { - wan_smp_flag_t smp_flags1; - card->hw_iface.hw_lock(card->hw,&smp_flags1); err=card->wandev.ec_enable(card, 1, channel); - card->hw_iface.hw_unlock(card->hw,&smp_flags1); } else{ usr_tdm_api.result=SANG_STATUS_OPTION_NOT_SUPPORTED; err = -EOPNOTSUPP; @@ -1871,10 +2120,7 @@ static int wanpipe_tdm_api_ioctl_handle_tdm_api_cmd(wanpipe_tdm_api_dev_t *tdm_a case WP_API_CMD_DISABLE_HWEC: if (card && card->wandev.ec_enable) { - wan_smp_flag_t smp_flags1; - card->hw_iface.hw_lock(card->hw,&smp_flags1); err=card->wandev.ec_enable(card, 0, channel); - card->hw_iface.hw_unlock(card->hw,&smp_flags1); } else { usr_tdm_api.result=SANG_STATUS_OPTION_NOT_SUPPORTED; err = -EOPNOTSUPP; @@ -1895,6 +2141,14 @@ static int wanpipe_tdm_api_ioctl_handle_tdm_api_cmd(wanpipe_tdm_api_dev_t *tdm_a } break; + case WP_API_CMD_GET_HW_EC_CHAN: + if (wan_test_bit(channel, &card->wandev.fe_ec_map)) { + usr_tdm_api.hw_ec = WANOPT_YES; + } else { + usr_tdm_api.hw_ec = WANOPT_NO; + } + break; + case WP_API_CMD_GET_HW_DTMF: if (card && card->wandev.ec_state) { wan_hwec_dev_state_t ecdev_state = {0}; @@ -1905,7 +2159,7 @@ static int wanpipe_tdm_api_ioctl_handle_tdm_api_cmd(wanpipe_tdm_api_dev_t *tdm_a usr_tdm_api.hw_dtmf = WANOPT_NO; } } else { - usr_tdm_api.hw_fax = WANOPT_NO; + usr_tdm_api.hw_dtmf = WANOPT_NO; } break; @@ -2189,7 +2443,7 @@ static int wanpipe_tdm_api_ioctl_handle_tdm_api_cmd(wanpipe_tdm_api_dev_t *tdm_a break; } - wan_spin_unlock(&tdm_api->lock, &flags); + wan_mutex_unlock(&tdm_api->lock, &flags); if (!rx_gains) { rx_gains = wan_malloc(usr_tdm_api.data_len); @@ -2208,7 +2462,7 @@ static int wanpipe_tdm_api_ioctl_handle_tdm_api_cmd(wanpipe_tdm_api_dev_t *tdm_a goto tdm_api_unlocked_exit; } - wan_spin_lock(&tdm_api->lock,&flags); + wan_mutex_lock(&tdm_api->lock,&flags); tdm_api->rx_gain = rx_gains; @@ -2232,7 +2486,7 @@ static int wanpipe_tdm_api_ioctl_handle_tdm_api_cmd(wanpipe_tdm_api_dev_t *tdm_a break; } - wan_spin_unlock(&tdm_api->lock, &flags); + wan_mutex_unlock(&tdm_api->lock, &flags); if (!tx_gains) { tx_gains = wan_malloc(usr_tdm_api.data_len); @@ -2250,7 +2504,7 @@ static int wanpipe_tdm_api_ioctl_handle_tdm_api_cmd(wanpipe_tdm_api_dev_t *tdm_a err=-EFAULT; goto tdm_api_unlocked_exit; } - wan_spin_lock(&tdm_api->lock,&flags); + wan_mutex_lock(&tdm_api->lock,&flags); tdm_api->tx_gain = tx_gains; @@ -2354,11 +2608,41 @@ static int wanpipe_tdm_api_ioctl_handle_tdm_api_cmd(wanpipe_tdm_api_dev_t *tdm_a break; case WP_API_CMD_ENABLE_LOOP: - tdm_api->cfg.loop=1; + + if (WPTDM_CHAN_OP_MODE(tdm_api)) { + if (wan_test_bit(channel, &card->wandev.fe_ec_map)) { + if (card && card->wandev.ec_enable) { + int terr=card->wandev.ec_enable(card, 0, channel); + if (terr == 0) { + tdm_api->loop_reenable_hwec=1; + } + } + } + + tdm_api->cfg.loop=1; + + } else { + err=-EOPNOTSUPP; + } + + break; case WP_API_CMD_DISABLE_LOOP: - tdm_api->cfg.loop=0; + + if (WPTDM_CHAN_OP_MODE(tdm_api)) { + if (tdm_api->loop_reenable_hwec) { + if (card && card->wandev.ec_enable) { + card->wandev.ec_enable(card, 1, channel); + } + } + + tdm_api->cfg.loop=0; + } else { + err=-EOPNOTSUPP; + } + + break; case WP_API_CMD_DRIVER_VERSION: @@ -2373,6 +2657,26 @@ static int wanpipe_tdm_api_ioctl_handle_tdm_api_cmd(wanpipe_tdm_api_dev_t *tdm_a } break; + case WP_API_CMD_BUFFER_MULTIPLIER: + + if (WPTDM_SPAN_OP_MODE(tdm_api) && !tdm_api->hdlc_framing) { + int mult = *(uint32_t*)&usr_tdm_api.data[0]; + if (mult > TDMAPI_MAX_BUFFER_MULTIPLIER) { + DEBUG_ERROR("%s: Error: Inavlid buffer multiplier %i\n",tdm_api->name,mult); + err=-EINVAL; + goto tdm_api_exit; + } + if (mult < 2) { + tdm_api->buffer_multiplier = 1; + } else { + tdm_api->buffer_multiplier = mult; + } + tdm_api->cfg.usr_mtu_mru = tdm_api->cfg.usr_period*tdm_api->cfg.hw_mtu_mru*tdm_api->buffer_multiplier *tdm_api->timeslots; + DEBUG_TDMAPI("%s: Setting Multiplier %i, New MTU %i (p=%i,hwmtu=%i)\n", + tdm_api->name,tdm_api->buffer_multiplier,tdm_api->cfg.usr_mtu_mru,tdm_api->cfg.usr_period,tdm_api->cfg.hw_mtu_mru); + } + break; + default: DEBUG_EVENT("%s: Invalid TDM API CMD %i\n", tdm_api->name,cmd); usr_tdm_api.result=SANG_STATUS_OPTION_NOT_SUPPORTED; @@ -2381,7 +2685,7 @@ static int wanpipe_tdm_api_ioctl_handle_tdm_api_cmd(wanpipe_tdm_api_dev_t *tdm_a } tdm_api_exit: - wan_spin_unlock(&tdm_api->lock, &flags); + wan_mutex_unlock(&tdm_api->lock, &flags); tdm_api_unlocked_exit: @@ -2852,6 +3156,7 @@ static int wanpipe_tdm_api_channelized_rx (wanpipe_tdm_api_dev_t *tdm_api, u8 *r #endif data_ptr=wan_skb_put(tdm_api->rx_skb,hdrsize); + memset(data_ptr,0,hdrsize); } #if 0 @@ -3129,7 +3434,12 @@ int wanpipe_tdm_api_span_rx (wanpipe_tdm_api_dev_t *tdm_api, netskb_t *skb) tdm_api->cfg.stats.rx_packets++; wptdm_os_unlock_irq(&card->wandev.lock,&flag); - wp_wakeup_rx_tdmapi(tdm_api); + + /* Buffer multiplier is by default 1 so we can use it to check if there + is something in the rx_list */ + if (wan_skb_queue_len(&tdm_api->wp_rx_list) >= tdm_api->buffer_multiplier) { + wp_wakeup_rx_tdmapi(tdm_api); + } return 0; } @@ -3206,7 +3516,7 @@ static void wp_tdmapi_report_rbsbits(void* card_id, int channel, unsigned char r p_tdmapi_event->wp_api_event_rbs_bits = (u8)rbsbits; - wp_tdmapi_push_to_bh_queue(tdm_api,skb); + wan_skb_push_to_ctrl_event(skb); if (!wan_test_bit(0,&tdm_api->used)) { wan_skb_init(skb,sizeof(wp_api_hdr_t)); @@ -3266,7 +3576,7 @@ static void wp_tdmapi_alarms(void* card_id, wan_event_t *event) p_tdmapi_event->wp_api_event_alarm = event->alarms; tdm_api->cfg.fe_alarms = event->alarms; - wp_tdmapi_push_to_bh_queue(tdm_api,skb); + wan_skb_push_to_ctrl_event(skb); if (!wan_test_bit(0,&tdm_api->used)) { wan_skb_init(skb,sizeof(wp_api_hdr_t)); @@ -3284,14 +3594,14 @@ static void wp_tdmapi_alarms(void* card_id, wan_event_t *event) return; } -static void wp_tdmapi_report_alarms(void* card_id, unsigned long te_alarm) +static void wp_tdmapi_report_alarms(void* card_id, uint32_t te_alarm) { wan_event_t event; u8 i; memset(&event,0,sizeof(event)); - event.alarms=(u32)te_alarm; + event.alarms=te_alarm; for (i=0; ievent_time_stamp = gettimeofday(); #endif - wp_tdmapi_push_to_bh_queue(tdm_api,skb); + wan_skb_push_to_ctrl_event(skb); if (!wan_test_bit(0,&tdm_api->used)) { wan_skb_init(skb,sizeof(wp_api_hdr_t)); @@ -3467,7 +3777,7 @@ static void wp_tdmapi_hook (void* card_id, wan_event_t *event) rx_hdr->event_time_stamp = gettimeofday(); #endif - wp_tdmapi_push_to_bh_queue(tdm_api,skb); + wan_skb_push_to_ctrl_event(skb); if (!wan_test_bit(0,&tdm_api->used)) { wan_skb_init(skb,sizeof(wp_api_hdr_t)); @@ -3497,7 +3807,7 @@ static void __wp_tdmapi_linkstatus (void* card_id, wan_event_t *event, int lock) flags=0; - DEBUG_TDMAPI("%s: Received Link Status Event at TDM_API (%d:%s)!\n", + DEBUG_TEST("%s: Received Link Status Event at TDM_API (%d:%s)!\n", card->devname, event->channel, (event->link_status==WAN_EVENT_LINK_STATUS_DISCONNECTED)?"Disconnected":"Connected"); @@ -3549,7 +3859,7 @@ static void __wp_tdmapi_linkstatus (void* card_id, wan_event_t *event, int lock) WP_API_EVENT_LINK_STATUS_DISCONNECTED; } - wp_tdmapi_push_to_bh_queue(tdm_api,skb); + wan_skb_push_to_ctrl_event(skb); if (!wan_test_bit(0,&tdm_api->used)) { wan_skb_init(skb,sizeof(wp_api_hdr_t)); @@ -3639,7 +3949,7 @@ static void wp_tdmapi_polarityreverse (void* card_id, wan_event_t *event) break; } - wp_tdmapi_push_to_bh_queue(tdm_api,skb); + wan_skb_push_to_ctrl_event(skb); if (!wan_test_bit(0,&tdm_api->used)) { wan_skb_init(skb,sizeof(wp_api_hdr_t)); @@ -3709,7 +4019,7 @@ static void wp_tdmapi_ringtrip (void* card_id, wan_event_t *event) rx_hdr->event_time_stamp = gettimeofday(); #endif - wp_tdmapi_push_to_bh_queue(tdm_api,skb); + wan_skb_push_to_ctrl_event(skb); if (!wan_test_bit(0,&tdm_api->used)) { wan_skb_init(skb,sizeof(wp_api_hdr_t)); @@ -3774,7 +4084,7 @@ static void wp_tdmapi_ringdetect (void* card_id, wan_event_t *event) rx_hdr->event_time_stamp = gettimeofday(); #endif - wp_tdmapi_push_to_bh_queue(tdm_api,skb); + wan_skb_push_to_ctrl_event(skb); if (!wan_test_bit(0,&tdm_api->used)) { wan_skb_init(skb,sizeof(wp_api_hdr_t)); @@ -3904,53 +4214,7 @@ static int remove_tdm_api_pointer_from_card(wanpipe_tdm_api_dev_t *tdm_api) return 0; } - -static int wp_tdmapi_push_to_bh_queue(wanpipe_tdm_api_dev_t *tdm_api, netskb_t *skb) -{ - netskb_t *ctrl_skb; - - if (!skb || !tdm_api) { - DEBUG_ERROR("TDMAPI: Error: Null skb argument!\n"); - return -ENODEV; - } - if (tdm_api == &tdmapi_ctrl) { - DEBUG_ERROR("%s:%d: TDMAPI: Error: tdm_api == tdmapi_ctrl!\n",__FUNCTION__,__LINE__); - return -EINVAL; - } - - if (!wan_test_bit(0,&tdmapi_ctrl.used)) { - return -EBUSY; - } - - ctrl_skb=wan_skb_dequeue(&tdm_api->wp_event_free_list); - if (ctrl_skb){ - int len = wan_skb_len(skb); - u8 *buf; - if (len > wan_skb_tailroom(ctrl_skb)) { - if (WAN_NET_RATELIMIT()){ - DEBUG_ERROR("TDMAPI: Error: TDM API CTRL Event Buffer Overflow Elen=%i Max=%i!\n", - len,wan_skb_tailroom(ctrl_skb)); - } - WP_AFT_CHAN_ERROR_STATS(tdm_api->cfg.stats,rx_events_dropped); - return -EFAULT; - } - buf=wan_skb_put(ctrl_skb,len); - memcpy(buf,wan_skb_data(skb),len); - - wan_skb_queue_tail(&tdm_api->wp_event_bh_list,ctrl_skb); - if (!wan_test_bit(WP_TDM_DOWN,&tdm_api->critical)) { - WAN_TASKQ_SCHEDULE((&tdm_api->wp_api_task)); - } - - } else { - WP_AFT_CHAN_ERROR_STATS(tdm_api->cfg.stats,rx_events_dropped); - } - - return 0; - - -} - +/* When a Port is unloaded tell ctrldev that the Port is 'disconnected' */ static int wp_tdmapi_unreg_notify_ctrl(wanpipe_tdm_api_dev_t *tdm_api) { sdla_t *card = tdm_api->card; @@ -3964,6 +4228,7 @@ static int wp_tdmapi_unreg_notify_ctrl(wanpipe_tdm_api_dev_t *tdm_api) wan_smp_flag_t flags; netskb_t *skb; u8 i; + flags=0; for (i=0;iwp_api_event_span = wp_tdmapi_get_span(card); p_tdmapi_event->wp_api_event_link_status = WP_API_EVENT_LINK_STATUS_DISCONNECTED; - wan_spin_lock(&tdmapi_ctrl.lock,&flags); wan_skb_push_to_ctrl_event(skb); - wan_spin_unlock(&tdmapi_ctrl.lock,&flags); wan_skb_init(skb,sizeof(wp_api_hdr_t)); wan_skb_trim(skb,0); @@ -4003,6 +4266,9 @@ static int wp_tdmapi_unreg_notify_ctrl(wanpipe_tdm_api_dev_t *tdm_api) } +/* The api task funciton is not used right now. we are leaving + the infrastructure here for future use */ + #if defined(__LINUX__) # if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) static void wp_api_task_func (void * tdmapi_ptr) @@ -4026,12 +4292,6 @@ static void wp_api_task_func (void * tdmapi_ptr, int arg) #endif sdla_t *card = tdm_api->card; - wan_smp_flag_t smp_flags; - wan_smp_flag_t smp_irq_flags; - netskb_t *skb; - - smp_irq_flags=0; - if (!card) { return; } @@ -4040,28 +4300,6 @@ static void wp_api_task_func (void * tdmapi_ptr, int arg) return; } - do { - wptdm_os_lock_irq(&card->wandev.lock,&smp_irq_flags); - skb = wan_skb_dequeue(&tdm_api->wp_event_bh_list); - wptdm_os_unlock_irq(&card->wandev.lock,&smp_irq_flags); - if (skb) { - - if (wan_test_bit(0,&tdmapi_ctrl.used)) { - wan_spin_lock(&tdmapi_ctrl.lock,&smp_flags); - wan_skb_push_to_ctrl_event(skb); - wan_spin_unlock(&tdmapi_ctrl.lock,&smp_flags); - } - - wptdm_os_lock_irq(&card->wandev.lock,&smp_irq_flags); - wan_skb_init(skb,sizeof(wp_api_hdr_t)); - wan_skb_trim(skb,0); - wan_skb_queue_tail(&tdm_api->wp_event_free_list,skb); - wptdm_os_unlock_irq(&card->wandev.lock,&smp_irq_flags); - continue; - } - - } while(skb); - return; } diff --git a/patches/kdrivers/src/net/wanpipe_timer_dev.c b/patches/kdrivers/src/net/wanpipe_timer_dev.c index b804592..0dd7ac3 100644 --- a/patches/kdrivers/src/net/wanpipe_timer_dev.c +++ b/patches/kdrivers/src/net/wanpipe_timer_dev.c @@ -34,7 +34,7 @@ #if defined(__WINDOWS__) # define DEBUG_TDEV DbgPrint #else -# define DEBUG_TDEV DEBUG_EVENT +# define DEBUG_TDEV DEBUG_TEST #endif #define MAX_WAN_TDEV_IDX_SZ 20 @@ -78,6 +78,8 @@ static wanpipe_cdev_ops_t wan_tdev_fops; static void wanpipe_wandev_timer_init_globals() { + DEBUG_TEST("%s:%d\n",__FUNCTION__,__LINE__); + memset(wan_tdev_idx, 0x00, sizeof(wan_tdev_idx)); wan_timer_card = NULL; @@ -98,8 +100,16 @@ int wanpipe_wandev_timer_create(void) wanpipe_tdev_t *wan_tdev; wanpipe_cdev_t *cdev; + DEBUG_TEST("%s:%d\n",__FUNCTION__,__LINE__); + wanpipe_wandev_timer_init_globals(); + if (wan_tdev_cnt >= MAX_WAN_TDEV_IDX_SZ) { + DEBUG_ERROR("%s:%d Error Invalid wan_tdev_cnt %i\n", + __FUNCTION__,__LINE__,wan_tdev_cnt); + return -EINVAL; + } + cdev = wan_kmalloc(sizeof(wanpipe_cdev_t)); if (!cdev) { return -ENOMEM; @@ -134,6 +144,7 @@ int wanpipe_wandev_timer_create(void) wan_timer_card=NULL; wan_set_bit(0,&wan_timer_initialized); + DEBUG_TDEV("%s: WAN TDEV CREATE (err:%d, wan_tdev_cnt:%d) \n", __FUNCTION__, err, wan_tdev_cnt); @@ -148,6 +159,13 @@ int wanpipe_wandev_timer_free(void) wanpipe_tdev_t *wan_tdev; netskb_t *skb; + DEBUG_TEST("%s:%d\n",__FUNCTION__,__LINE__); + + if (!wan_test_bit(0,&wan_timer_initialized)) { + DEBUG_EVENT("%s:%d Error wan_timer not initialized\n",__FUNCTION__,__LINE__); + return -1; + } + wan_clear_bit(0,&wan_timer_initialized); for (i=0;ievent) { /* Indicate an exception */ err |= POLLPRI; @@ -298,6 +328,8 @@ int wp_timer_device_reg_tick(sdla_t *card) wan_smp_flag_t flags; int init=0; + DEBUG_TEST("%s:%d\n",__FUNCTION__,__LINE__); + if (!wan_test_bit(0,&wan_timer_initialized)) { return -1; } @@ -354,6 +386,8 @@ int wp_timer_device_reg_tick(sdla_t *card) int wp_timer_device_unreg(sdla_t *card) { + DEBUG_TEST("%s:%d\n",__FUNCTION__,__LINE__); + if (!wan_test_bit(0,&wan_timer_initialized)) { return -1; } diff --git a/patches/kdrivers/src/net/wanpipe_usb.c b/patches/kdrivers/src/net/wanpipe_usb.c index 9b1ac82..605343b 100644 --- a/patches/kdrivers/src/net/wanpipe_usb.c +++ b/patches/kdrivers/src/net/wanpipe_usb.c @@ -20,8 +20,8 @@ /***************************************************************************** * INCLUDE FILES *****************************************************************************/ -#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) -#else + + # include "wanpipe_includes.h" # include "wanpipe_defines.h" # include "wanpipe.h" @@ -33,7 +33,6 @@ # include "wanpipe_iface.h" # include "wanpipe_usb.h" # include "sdla_usb_remora.h" -#endif #if defined(CONFIG_PRODUCT_WANPIPE_USB) @@ -55,8 +54,9 @@ enum { }; enum { - WP_USB_RXENABLE, - WP_USB_FE_POLL + WP_USB_TASK_UNKNOWN = 0x00, + WP_USB_TASK_RXENABLE, + WP_USB_TASK_FE_POLL }; /***************************************************************************** @@ -99,6 +99,8 @@ typedef struct wp_usb_softc { wp_usb_op_stats_t opstats; + wan_hwec_if_conf_t hwec; + struct wp_usb_softc *next; } wp_usb_softc_t; @@ -109,14 +111,11 @@ typedef struct wp_usb_softc { /* Function interface between WANPIPE layer and kernel */ extern wan_iface_t wan_iface; -extern sdladrv_callback_t sdladrv_callback; - extern sdla_t *card_list; /***************************************************************************** * FUNCTION PROTOTYPES *****************************************************************************/ - static int wp_usb_chip_config(sdla_t *card); static int wp_usb_add_device(char *devname, void*); @@ -173,11 +172,6 @@ static void wp_usb_isr(void *arg); int wp_usb_init(sdla_t *card, wandev_conf_t *conf) { -#if 0 - /* Hot-plug is not supported yet */ - sdladrv_callback.add_device = wp_usb_add_device; - sdladrv_callback.delete_device = wp_usb_delete_device; -#endif /* Verify configuration ID */ if (card->wandev.config_id != WANCONFIG_USB_ANALOG) { DEBUG_EVENT( "%s: invalid configuration ID %u!\n", @@ -189,6 +183,8 @@ int wp_usb_init(sdla_t *card, wandev_conf_t *conf) memcpy(&card->fe.fe_cfg, &conf->fe_cfg, sizeof(sdla_fe_cfg_t)); wp_usb_remora_iface_init(&card->fe, &card->wandev.fe_iface); memcpy(&card->tdmv_conf,&conf->tdmv_conf,sizeof(wan_tdmv_conf_t)); + memcpy(&card->hwec_conf,&conf->hwec_conf,sizeof(wan_hwec_conf_t)); + card->fe.name = card->devname; card->fe.card = card; card->fe.write_fe_reg = card->hw_iface.fe_write; @@ -235,6 +231,7 @@ static int wp_usb_chip_config(sdla_t *card) card->devname); return -EINVAL; } + /* Run rest of initialization not from lock */ err = -EINVAL; if (card->wandev.fe_iface.post_init){ @@ -268,6 +265,7 @@ wp_usb_new_if_private (wan_device_t* wandev, netdevice_t* dev, wanif_conf_t* con wp_usb_softc_t *chan; WP_USB_FUNC_DEBUG(); + chan = wan_kmalloc(sizeof(wp_usb_softc_t)); if(chan == NULL){ WAN_MEM_ASSERT(card->devname); @@ -323,7 +321,12 @@ wp_usb_new_if_private (wan_device_t* wandev, netdevice_t* dev, wanif_conf_t* con DEBUG_EVENT( "%s:%s: Running in TDM Voice Zaptel Mode (channel=%d:%08X).\n", card->devname,chan->if_name,channel, card->u.usb.tdm_logic_ch_map); card->hw_iface.usb_rxtx_data_init(card->hw, channel, &chan->rxdata, &chan->txdata); - //sdla_usb_rxtx_data_init(card->hw, channel, &chan->rxdata, &chan->txdata); + + memcpy(&chan->hwec, &conf->hwec, sizeof(wan_hwec_if_conf_t)); + if (conf->hwec.enable){ + card->wandev.ec_enable_map = 0x03; + } + #else DEBUG_ERROR("%s: Error: TDMV_VOICE Zaptel Option not compiled into the driver!\n", card->devname); @@ -399,6 +402,8 @@ wp_usb_new_if_private (wan_device_t* wandev, netdevice_t* dev, wanif_conf_t* con } #ifdef CONFIG_PRODUCT_WANPIPE_TDM_VOICE +extern int wp_usb_rm_tdmv_init(wan_tdmv_iface_t *iface); + static int wp_usb_if_tdmv_init(wan_device_t* wandev, netdevice_t* dev, wanif_conf_t* conf) { @@ -414,7 +419,7 @@ wp_usb_if_tdmv_init(wan_device_t* wandev, netdevice_t* dev, wanif_conf_t* conf) switch(card->wandev.config_id){ case WANCONFIG_USB_ANALOG: - err = wp_usb_tdmv_remora_init(&card->tdmv_iface); + err = wp_usb_rm_tdmv_init(&card->tdmv_iface); break; } if (err){ @@ -448,7 +453,7 @@ wp_usb_if_tdmv_init(wan_device_t* wandev, netdevice_t* dev, wanif_conf_t* conf) } WAN_TDMV_CALL(software_init, (&card->wan_tdmv), err); WAN_TDMV_CALL(state, (card, WAN_CONNECTED), err); - wan_set_bit(WP_USB_RXENABLE,&card->u.usb.port_task_cmd); + wan_set_bit(WP_USB_TASK_RXENABLE,&card->u.usb.port_task_cmd); WAN_TASKQ_SCHEDULE(&card->u.usb.port_task); } @@ -608,13 +613,12 @@ static int wp_usb_del_if_tdmv (wan_device_t* wandev, netdevice_t* dev) sdla_t *card=chan->card; card->hw_iface.usb_rxdata_enable(card->hw, 0); - //sdla_usb_rxdata_enable(card->hw, 0); while(chan){ + /* Disable fxo event from usbfxo device */ + card->hw_iface.usb_rxevent_enable(card->hw, chan->tdmv_chan, 0); chan->rxdata = NULL; chan->txdata = NULL; - card->hw_iface.usb_rxevent_enable(card->hw, chan->tdmv_chan, 0); - //sdla_usb_rxevent_enable(card->hw, chan->tdmv_chan, 0); card->u.usb.dev_to_ch_map[chan->tdmv_chan] = NULL; err = wp_usb_del_if_private(wandev,dev); if (err) { @@ -762,12 +766,12 @@ static void wp_usb_disable_comm (sdla_t *card) wan_set_bit(CARD_DOWN,&card->wandev.critical); /* Unconfiging, only on shutdown */ - if (card->wandev.fe_iface.pre_release){ - card->wandev.fe_iface.pre_release(&card->fe); - } if (card->wandev.fe_iface.unconfig){ card->wandev.fe_iface.unconfig(&card->fe); } + if (card->wandev.fe_iface.post_unconfig){ + card->wandev.fe_iface.post_unconfig(&card->fe); + } return; } @@ -915,7 +919,6 @@ static int wp_usb_if_send(netdevice_t *dev, netskb_t *skb, struct sockaddr *dst, return -EINVAL; } - static int wp_usb_if_do_ioctl(netdevice_t *dev, struct ifreq *ifr, wan_ioctl_cmd_t cmd) { @@ -948,8 +951,6 @@ wp_usb_if_do_ioctl(netdevice_t *dev, struct ifreq *ifr, wan_ioctl_cmd_t cmd) case SIOC_WANPIPE_PIPEMON: - NET_ADMIN_CHECK(); - if (wan_atomic_read(&chan->udp_pkt_len) != 0){ return -EBUSY; } @@ -1011,7 +1012,6 @@ wp_usb_if_do_ioctl(netdevice_t *dev, struct ifreq *ifr, wan_ioctl_cmd_t cmd) * is used to debug the WANPIPE product. * */ -#if 1 static int wp_usb_process_udp(sdla_t* card, netdevice_t* dev, wp_usb_softc_t *chan) { @@ -1026,22 +1026,16 @@ wp_usb_process_udp(sdla_t* card, netdevice_t* dev, wp_usb_softc_t *chan) return -ENODEV; } -// trace_info=&chan->trace_info; wan_udp_pkt = (wan_udp_pkt_t *)chan->udp_pkt_data; { -// netskb_t *skb; - wan_udp_pkt->wan_udp_opp_flag = 0; switch(wan_udp_pkt->wan_udp_command) { -#if 0 - case READ_CONFIGURATION: - wan_udp_pkt->wan_udp_return_code = 0; - wan_udp_pkt->wan_udp_data_len=0; - break; + /* Added during merge */ +#if 0 case READ_CODE_VERSION: wan_udp_pkt->wan_udp_return_code = 0; wan_udp_pkt->wan_udp_data[0]=card->u.usb.firm_ver; @@ -1196,7 +1190,7 @@ wp_usb_process_udp(sdla_t* card, netdevice_t* dev, wp_usb_softc_t *chan) wan_udp_pkt->wan_udp_return_code = WAN_CMD_OK; break; -#endif +#endif /* Added during merge */ case ROUTER_UP_TIME: wan_getcurrenttime(&chan->current_time, NULL); @@ -1234,9 +1228,8 @@ wp_usb_process_udp(sdla_t* card, netdevice_t* dev, wp_usb_softc_t *chan) wan_udp_pkt->wan_udp_data_len=0; break; - case WAN_GET_PROTOCOL: - wan_udp_pkt->wan_udp_aft_num_frames = card->wandev.config_id; + wan_udp_pkt->wan_udp_data[0] = (u8)card->wandev.config_id; wan_udp_pkt->wan_udp_return_code = CMD_OK; wan_udp_pkt->wan_udp_data_len = 1; break; @@ -1252,7 +1245,14 @@ wp_usb_process_udp(sdla_t* card, netdevice_t* dev, wp_usb_softc_t *chan) wan_udp_pkt->wan_udp_return_code = 0xCD; break; - + case AFT_HWEC_STATUS: + //*(u32*)&wan_udp_pkt->wan_udp_aft_num_frames = + // card->wandev.fe_ec_map; + *(u32*)&wan_udp_pkt->wan_udp_data[0] = card->wandev.fe_ec_map; + wan_udp_pkt->wan_udp_data_len = sizeof(u32); + wan_udp_pkt->wan_udp_return_code = CMD_OK; + break; + default: if ((wan_udp_pkt->wan_udp_command == WAN_GET_MEDIA_TYPE) || (wan_udp_pkt->wan_udp_command & 0xF0) == WAN_FE_UDP_CMD_START){ @@ -1286,10 +1286,9 @@ wp_usb_process_udp(sdla_t* card, netdevice_t* dev, wp_usb_softc_t *chan) wan_udp_pkt->wan_ip_ttl= card->wandev.ttl; wan_udp_pkt->wan_udp_request_reply = UDPMGMT_REPLY; - return 1; + return 0; } -#endif static int wp_usb_set_chan_state(sdla_t* card, netdevice_t* dev, int state) { @@ -1341,7 +1340,7 @@ static void wp_usb_enable_timer (void* card_id) } DEBUG_EVENT("%s: Enable USB-FXO FE POll...\n", card->devname); - wan_set_bit(WP_USB_FE_POLL,&card->u.usb.port_task_cmd); + wan_set_bit(WP_USB_TASK_FE_POLL,&card->u.usb.port_task_cmd); WAN_TASKQ_SCHEDULE(&card->u.usb.port_task); return; } @@ -1367,6 +1366,33 @@ static void wp_usb_bh (void *data, int pending) } +static int wp_usb_task_rxenable (sdla_t *card) +{ + wp_usb_softc_t *chan = NULL; + int i; + + for (i=0; iu.usb.num_of_time_slots;i++){ + + if (!wan_test_bit(i,&card->u.usb.tdm_logic_ch_map)){ + continue; + } + + chan=(wp_usb_softc_t*)card->u.usb.dev_to_ch_map[i]; + if (!chan){ + DEBUG_ERROR("%s: Error: No Dev for Rx logical ch=%d\n", + card->devname,i); + continue; + } + if (!wan_test_bit(0,&chan->up)){ + continue; + } + card->hw_iface.usb_rxevent(card->hw, chan->tdmv_chan, &chan->regs_mirror[0], 1); + card->hw_iface.usb_rxevent_enable(card->hw, chan->tdmv_chan, 1); + } + card->hw_iface.usb_rxdata_enable(card->hw, 1); + return 0; +} + #if defined(__LINUX__) # if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) @@ -1387,47 +1413,28 @@ static void wp_usb_task (void * data, int arg) #else sdla_t *card = (sdla_t*)data; #endif - wp_usb_softc_t *chan = NULL; - int i; - WAN_ASSERT_VOID(card == NULL); if (wan_test_bit(CARD_DOWN,&card->wandev.critical)){ return; } - if (wan_test_bit(WP_USB_FE_POLL,&card->u.usb.port_task_cmd)){ + if (wan_test_bit(WP_USB_TASK_FE_POLL,&card->u.usb.port_task_cmd)){ if (card->wandev.fe_iface.polling){ DEBUG_EVENT("%s: Calling USB-FXO FE Polling...\n", card->devname); card->wandev.fe_iface.polling(&card->fe); } - wan_clear_bit(WP_USB_FE_POLL,&card->u.usb.port_task_cmd); + wan_clear_bit(WP_USB_TASK_FE_POLL,&card->u.usb.port_task_cmd); } - if (wan_test_bit(WP_USB_RXENABLE,&card->u.usb.port_task_cmd)){ - /* Add code */ - for (i=0; iu.usb.num_of_time_slots;i++){ - - if (!wan_test_bit(i,&card->u.usb.tdm_logic_ch_map)){ - continue; - } - - chan=(wp_usb_softc_t*)card->u.usb.dev_to_ch_map[i]; - if (!chan){ - DEBUG_ERROR("%s: Error: No Dev for Rx logical ch=%d\n", - card->devname,i); - continue; - } - - if (!wan_test_bit(0,&chan->up)){ - continue; - } - - card->hw_iface.usb_rxevent(card->hw, chan->tdmv_chan, &chan->regs_mirror[0], 1); - card->hw_iface.usb_rxevent_enable(card->hw, chan->tdmv_chan, 1); - } - card->hw_iface.usb_rxdata_enable(card->hw, 1); - wan_clear_bit(WP_USB_RXENABLE,&card->u.usb.port_task_cmd); + if (wan_test_bit(WP_USB_TASK_RXENABLE,&card->u.usb.port_task_cmd)){ + wp_usb_task_rxenable(card); + wan_clear_bit(WP_USB_TASK_RXENABLE,&card->u.usb.port_task_cmd); } + + if (card->u.usb.port_task_cmd){ + WAN_TASKQ_SCHEDULE(&card->u.usb.port_task); + } + return; } @@ -1506,7 +1513,7 @@ static void wp_usb_isr(void *arg) /****************************************************************************** ** SIOC_WAN_DEVEL_IOCTL interface ******************************************************************************/ -static int wp_usb_write_reg(sdla_t *card, wan_cmd_api_t *api_cmd) +static int wp_usb_write_access(sdla_t *card, wan_cmd_api_t *api_cmd) { if (card->type != SDLA_USB){ @@ -1515,7 +1522,8 @@ static int wp_usb_write_reg(sdla_t *card, wan_cmd_api_t *api_cmd) return -EINVAL; } - if (api_cmd->ret == 1){ + switch(api_cmd->cmd){ + case SIOC_WAN_USB_CPU_WRITE_REG: DEBUG_EVENT("%s: Write USB-CPU CMD: Reg:%02X <- %02X\n", card->devname, (unsigned char)api_cmd->offset, @@ -1524,12 +1532,9 @@ static int wp_usb_write_reg(sdla_t *card, wan_cmd_api_t *api_cmd) card->hw, (u_int8_t)api_cmd->offset, (u_int8_t)api_cmd->data[0]); -#if defined(USB_WRITE_WAIT_ACK) - api_cmd->ret = -EBUSY; -#endif - - }else if (api_cmd->ret == 2){ + break; + case SIOC_WAN_USB_FE_WRITE_REG: DEBUG_EVENT("%s: Write USB-FXO CMD: Module:%d Reg:%02X <- %02X\n", card->devname, api_cmd->bar, (unsigned char)api_cmd->offset, @@ -1539,44 +1544,29 @@ static int wp_usb_write_reg(sdla_t *card, wan_cmd_api_t *api_cmd) card->hw, api_cmd->bar, (u_int8_t)api_cmd->offset, (u_int8_t)api_cmd->data[0]); -#if defined(USB_WRITE_WAIT_ACK) - api_cmd->ret = -EBUSY; -#endif + break; - }else if (api_cmd->ret == 0){ - - int err; - err = card->hw_iface.usb_write_poll(card->hw, (u_int8_t)api_cmd->offset, (u_int8_t)api_cmd->data[0]); - if (err){ - api_cmd->ret = -EBUSY; - return 0; - } - DEBUG_EVENT("%s: WRITE USB CMD: Reg:%02X -> %02X\n", - card->devname, - (unsigned char)api_cmd->offset, - (unsigned char)api_cmd->data[0]); - api_cmd->ret = 0; - - }else{ - DEBUG_EVENT("%s: Unknown SDLA-USB command %d\n", - card->devname, api_cmd->len); - api_cmd->ret = -EBUSY; - return 0; + default: + DEBUG_EVENT("%s: Invalid USB-FXO Write command (0x%08X)\n", + card->devname, api_cmd->cmd); + api_cmd->ret = -EINVAL; + break; } return 0; } -static int wp_usb_read_reg(sdla_t *card, wan_cmd_api_t *api_cmd) +static int wp_usb_read_access(sdla_t *card, wan_cmd_api_t *api_cmd) { int err = 0; if (card->type != SDLA_USB){ DEBUG_EVENT("%s: Unsupported command for current device!\n", card->devname); - return -EINVAL; + api_cmd->ret = -EINVAL; + return 0; } - if (api_cmd->ret == 1){ - + switch(api_cmd->cmd){ + case SIOC_WAN_USB_CPU_READ_REG: api_cmd->data[0] = 0xFF; /* Add function here */ err = card->hw_iface.usb_cpu_read( @@ -1593,9 +1583,9 @@ static int wp_usb_read_reg(sdla_t *card, wan_cmd_api_t *api_cmd) (unsigned char)api_cmd->data[0]); api_cmd->ret = 0; api_cmd->len = 1; + break; - }else if (api_cmd->ret == 2){ - + case SIOC_WAN_USB_FE_READ_REG: /* Add function here */ api_cmd->data[0] = card->hw_iface.fe_read( card->hw, @@ -1608,58 +1598,54 @@ static int wp_usb_read_reg(sdla_t *card, wan_cmd_api_t *api_cmd) (unsigned char)api_cmd->data[0]); api_cmd->ret = 0; api_cmd->len = 1; + break; - }else if (api_cmd->ret == 0){ - err = card->hw_iface.usb_read_poll(card->hw, (u_int8_t)api_cmd->offset, (u_int8_t*)&api_cmd->data[0]); - if (err){ - api_cmd->ret = -EBUSY; - return 0; - } - DEBUG_EVENT("%s: Read USB CMD: Reg:%02X -> %02X\n", - card->devname, - (unsigned char)api_cmd->offset, - (unsigned char)api_cmd->data[0]); - api_cmd->ret = 0; - api_cmd->len = 1; - - }else{ - DEBUG_EVENT("%s: Unknown SDLA-USB command %d\n", - card->devname, api_cmd->len); + default: + DEBUG_EVENT("%s: Invalid USB-FXO Read command (0x%08X)\n", + card->devname, api_cmd->cmd); api_cmd->ret = -EINVAL; - return 0; - } + break; + } return 0; } static int wp_usb_devel_ioctl(sdla_t *card, struct ifreq *ifr) { - wan_cmd_api_t api_cmd; + wan_cmd_api_t *api_cmd; int err = -EINVAL; if (!ifr || !ifr->ifr_data){ DEBUG_ERROR("%s: Error: No ifr or ifr_data\n",__FUNCTION__); return -EFAULT; } + api_cmd = wan_malloc(sizeof(wan_cmd_api_t)); + if (api_cmd == NULL) { + DEBUG_EVENT("Failed to allocate memory (%s)\n", __FUNCTION__); + return -EFAULT; + } + memset(api_cmd, 0, sizeof(wan_cmd_api_t)); - memset(&api_cmd,0,sizeof(wan_cmd_api_t)); - - if (WAN_COPY_FROM_USER(&api_cmd,ifr->ifr_data,sizeof(wan_cmd_api_t))){ + if (WAN_COPY_FROM_USER(api_cmd,ifr->ifr_data,sizeof(wan_cmd_api_t))){ return -EFAULT; } - switch(api_cmd.cmd){ - case SIOC_WAN_USB_READ_REG: - err = wp_usb_read_reg(card, &api_cmd); + switch(api_cmd->cmd){ + case SIOC_WAN_USB_CPU_WRITE_REG: + case SIOC_WAN_USB_FE_WRITE_REG: + err = wp_usb_write_access(card, api_cmd); break; - case SIOC_WAN_USB_WRITE_REG: - err = wp_usb_write_reg(card, &api_cmd); + + case SIOC_WAN_USB_CPU_READ_REG: + case SIOC_WAN_USB_FE_READ_REG: + err = wp_usb_read_access(card, api_cmd); break; } - - if (WAN_COPY_TO_USER(ifr->ifr_data,&api_cmd,sizeof(wan_cmd_api_t))){ + if (WAN_COPY_TO_USER(ifr->ifr_data,api_cmd,sizeof(wan_cmd_api_t))){ return -EFAULT; } - + if (api_cmd != NULL) { + wan_free(api_cmd); + } return err; } diff --git a/patches/kdrivers/src/net/wanpipe_utils.c b/patches/kdrivers/src/net/wanpipe_utils.c index c41218e..6760212 100644 --- a/patches/kdrivers/src/net/wanpipe_utils.c +++ b/patches/kdrivers/src/net/wanpipe_utils.c @@ -1035,6 +1035,11 @@ int wan_capture_trace_packet(sdla_t *card, wan_trace_t* trace_info, netskb_t *sk wan_smp_flag_t smp_flags; smp_flags=0; + + /* 8 is a spacial buffer trace */ + if (wan_test_bit(8,&trace_info->tracing_enabled)){ + return -EBUSY; + } if ((flag = wan_tracing_enabled(trace_info)) >= 0){ @@ -1074,7 +1079,13 @@ int wan_capture_trace_packet(sdla_t *card, wan_trace_t* trace_info, netskb_t *sk int wan_capture_trace_packet_offset(sdla_t *card, wan_trace_t* trace_info, netskb_t *skb, int off,char direction) { - int flag = 0; + int flag = 0; + + /* 8 is a spacial buffer trace */ + if (wan_test_bit(8,&trace_info->tracing_enabled)){ + return -EBUSY; + } + if ((flag = wan_tracing_enabled(trace_info)) >= 1){ int len = 0; diff --git a/patches/kdrivers/src/wan_aften/wan_aften.c b/patches/kdrivers/src/wan_aften/wan_aften.c index 3a23d3c..18f900d 100644 --- a/patches/kdrivers/src/wan_aften/wan_aften.c +++ b/patches/kdrivers/src/wan_aften/wan_aften.c @@ -17,7 +17,7 @@ static sdla_t* card_list = NULL; /* adapter data space */ extern wan_iface_t wan_iface; #if defined(CONFIG_PRODUCT_WANPIPE_USB) -static int wan_aften_callback_add_device(char *devname, void *phw); +static int wan_aften_callback_add_device(void); static int wan_aften_callback_delete_device(char *); extern sdladrv_callback_t sdladrv_callback; @@ -372,14 +372,14 @@ static int wan_aften_release(sdla_t *card) } #if defined(CONFIG_PRODUCT_WANPIPE_USB) -static int wan_aften_callback_add_device(char *devname, void *phw) +static int wan_aften_callback_add_device(void) { int err = 0; err = wan_aften_add_device(0); if (err){ DEBUG_EVENT("%s: ERROR: Failed to add new device!\n", - devname); + __FUNCTION__); return -EINVAL; } return 0; @@ -823,7 +823,8 @@ static int wan_aften_close(netdevice_t *dev) } #if defined(CONFIG_PRODUCT_WANPIPE_USB) -static int wan_aften_usb_write_reg(sdla_t *card, wan_cmd_api_t *api_cmd) + +static int wan_aften_usb_write_access(sdla_t *card, wan_cmd_api_t *api_cmd) { if (card->type != SDLA_USB){ @@ -832,8 +833,8 @@ static int wan_aften_usb_write_reg(sdla_t *card, wan_cmd_api_t *api_cmd) return -EINVAL; } - if (api_cmd->ret == 1){ - + switch(api_cmd->cmd){ + case SIOC_WAN_USB_CPU_WRITE_REG: DEBUG_TEST("%s: Write USB-CPU CMD: Reg:0x%02X <- 0x%02X\n", card->devname, (unsigned char)api_cmd->offset, @@ -842,9 +843,25 @@ static int wan_aften_usb_write_reg(sdla_t *card, wan_cmd_api_t *api_cmd) card->hw, (u_int8_t)api_cmd->offset, (u_int8_t)api_cmd->data[0]); + break; - }else if (api_cmd->ret == 2){ + case SIOC_WAN_USB_FW_DATA_WRITE: + if (api_cmd->len){ + DEBUG_TEST("%s: Write USB-FXO DATA: %d (%d) bytes\n", + card->devname, api_cmd->len, api_cmd->offset); + api_cmd->len = card->hw_iface.usb_txdata_raw( + card->hw, + &api_cmd->data[0], + api_cmd->len); + api_cmd->ret = 0; + }else{ + DEBUG_TEST("%s: Write USB-FXO DATA Ready?\n", + card->devname); + api_cmd->ret = card->hw_iface.usb_txdata_raw_ready(card->hw); + } + break; + case SIOC_WAN_USB_FE_WRITE_REG: DEBUG_TEST("%s: Write USB-FXO CMD: Module:%d Reg:%d <- 0x%02X\n", card->devname, api_cmd->bar, (unsigned char)api_cmd->offset, @@ -853,47 +870,18 @@ static int wan_aften_usb_write_reg(sdla_t *card, wan_cmd_api_t *api_cmd) api_cmd->bar, (u_int8_t)api_cmd->offset, (u_int8_t)api_cmd->data[0]); + break; - }else if (api_cmd->ret == 3){ - - if (api_cmd->len){ - DEBUG_TEST("%s: Write USB-FXO DATA: %d (%d) bytes\n", - card->devname, api_cmd->len, api_cmd->offset); - api_cmd->ret = card->hw_iface.usb_txdata( - card->hw, - &api_cmd->data[0], - api_cmd->len); - }else{ - DEBUG_TEST("%s: Write USB-FXO DATA Ready?\n", - card->devname); - api_cmd->ret = card->hw_iface.usb_txdata_ready(card->hw); - } - }else if (api_cmd->ret == 0){ - - api_cmd->ret = card->hw_iface.usb_write_poll( - card->hw, - (u_int8_t)api_cmd->offset, - (u_int8_t)api_cmd->data[0]); - if (api_cmd->ret){ - api_cmd->ret = -EBUSY; - return 0; - } - DEBUG_EVENT("%s: WRITE USB CMD: Reg:%d <- 0x%02X\n", - card->devname, - (unsigned char)api_cmd->offset, - (unsigned char)api_cmd->data[0]); - api_cmd->ret = 0; - - }else{ - DEBUG_EVENT("%s: Unknown SDLA-USB command %d\n", - card->devname, api_cmd->len); + default: + DEBUG_EVENT("%s: %s:%d: Invalid command\n", card->devname,__FUNCTION__,__LINE__); api_cmd->ret = -EBUSY; - return 0; - } + break; + } + return 0; } -static int wan_aften_usb_read_reg(sdla_t *card, wan_cmd_api_t *api_cmd) +static int wan_aften_usb_read_access(sdla_t *card, wan_cmd_api_t *api_cmd) { int err = 0; @@ -902,8 +890,9 @@ static int wan_aften_usb_read_reg(sdla_t *card, wan_cmd_api_t *api_cmd) card->devname); return -EINVAL; } - if (api_cmd->ret == 1){ + switch(api_cmd->cmd){ + case SIOC_WAN_USB_CPU_READ_REG: api_cmd->data[0] = 0xFF; /* Add function here */ err = card->hw_iface.usb_cpu_read( @@ -920,9 +909,19 @@ static int wan_aften_usb_read_reg(sdla_t *card, wan_cmd_api_t *api_cmd) (unsigned char)api_cmd->data[0]); api_cmd->ret = 0; api_cmd->len = 1; + break; - }else if (api_cmd->ret == 2){ + case SIOC_WAN_USB_FW_DATA_READ: + api_cmd->len = + card->hw_iface.usb_rxdata_raw( card->hw, + &api_cmd->data[0], + api_cmd->len); + DEBUG_TEST("%s: Read USB-FXO Data: %d (%d) bytes\n", + card->devname, api_cmd->ret, api_cmd->len); + api_cmd->ret = 0; + break; + case SIOC_WAN_USB_FE_READ_REG: /* Add function here */ api_cmd->data[0] = card->hw_iface.fe_read( card->hw, @@ -935,40 +934,26 @@ static int wan_aften_usb_read_reg(sdla_t *card, wan_cmd_api_t *api_cmd) (unsigned char)api_cmd->data[0]); api_cmd->ret = 0; api_cmd->len = 1; + break; - }else if (api_cmd->ret == 3){ - - /* Add function here */ - api_cmd->ret = - card->hw_iface.usb_rxdata(card->hw, &api_cmd->data[0], api_cmd->len); - - DEBUG_TEST("%s: Read USB-FXO Data: %d (%d) bytes\n", - card->devname, api_cmd->ret, api_cmd->len); - - }else if (api_cmd->ret == 0){ - - err = card->hw_iface.usb_read_poll( card->hw, - (u_int8_t)api_cmd->offset, - (u_int8_t*)&api_cmd->data[0]); - if (err){ - api_cmd->ret = -EBUSY; - return 0; - } - DEBUG_EVENT("%s: Read USB CMD: Reg:%d -> 0x%02X\n", - card->devname, - (unsigned char)api_cmd->offset, - (unsigned char)api_cmd->data[0]); - api_cmd->ret = 0; - api_cmd->len = 1; - - }else{ - DEBUG_EVENT("%s: Unknown SDLA-USB command %d\n", - card->devname, api_cmd->len); - api_cmd->ret = -EINVAL; - return 0; - } + default: + DEBUG_EVENT("%s: %s:%d: Invalid command\n", card->devname,__FUNCTION__,__LINE__); + api_cmd->ret = -EBUSY; + break; + } return 0; } + +static int wan_aften_usb_fwupdate_enable(sdla_t *card) +{ + if (card->type != SDLA_USB){ + DEBUG_EVENT("%s: Unsupported command for current device!\n", + card->devname); + return -EINVAL; + } + return card->hw_iface.usb_fwupdate_enable(card->hw); +} + #endif static int @@ -1084,13 +1069,20 @@ wan_aften_ioctl (netdevice_t *dev, struct ifreq *ifr, wan_ioctl_cmd_t cmd) err = wan_aften_all_write_pcibridge_reg(card, api_cmd); break; #if defined(CONFIG_PRODUCT_WANPIPE_USB) - case SIOC_WAN_USB_READ_REG: - err = wan_aften_usb_read_reg(card, api_cmd); + case SIOC_WAN_USB_CPU_READ_REG: + case SIOC_WAN_USB_FW_DATA_READ: + case SIOC_WAN_USB_FE_READ_REG: + err = wan_aften_usb_read_access(card, api_cmd); break; - case SIOC_WAN_USB_WRITE_REG: - err = wan_aften_usb_write_reg(card, api_cmd); + case SIOC_WAN_USB_CPU_WRITE_REG: + case SIOC_WAN_USB_FW_DATA_WRITE: + case SIOC_WAN_USB_FE_WRITE_REG: + err = wan_aften_usb_write_access(card, api_cmd); break; -#endif + case SIOC_WAN_USB_FWUPDATE_ENABLE: + err = wan_aften_usb_fwupdate_enable(card); + break; +#endif default: DEBUG_EVENT("%s: Unknown WAN_AFTEN command %X\n", card->devname, api_cmd->cmd); diff --git a/patches/kdrivers/src/wanrouter/wandev.c b/patches/kdrivers/src/wanrouter/wandev.c index c808ae1..d71e30d 100644 --- a/patches/kdrivers/src/wanrouter/wandev.c +++ b/patches/kdrivers/src/wanrouter/wandev.c @@ -54,6 +54,7 @@ static int wanpipe_port_management(wanpipe_wandev_t *wdev, void *data); static int wanpipe_mgmnt_get_hardware_info(wanpipe_wandev_t *wdev, wan_device_t *wandev, port_management_struct_t *usr_port_mgmnt); static int wanpipe_mgmnt_stop_port(wanpipe_wandev_t *wdev, wan_device_t *wandev, port_management_struct_t *usr_port_mgmnt); static int wanpipe_mgmnt_start_port(wanpipe_wandev_t *wdev, wan_device_t *wandev, port_management_struct_t *usr_port_mgmnt); +static int wanpipe_mgmnt_get_driver_version(wanpipe_wandev_t *wdev, wan_device_t *wandev, port_management_struct_t *usr_port_mgmnt); /*================================================= @@ -120,9 +121,9 @@ int wanpipe_wandev_free() static int wp_wandev_open(void *obj) { +#if 0 wanpipe_wandev_t *wdev=(wanpipe_wandev_t*)obj; -#if 0 if (wan_test_and_set_bit(0,&wdev->used)) { return -EBUSY; } @@ -136,10 +137,10 @@ static int wp_wandev_open(void *obj) static int wp_wandev_close(void *obj) { +#if 0 wanpipe_wandev_t *wdev=(wanpipe_wandev_t*)obj; -#if 0 wan_clear_bit(0,&wdev->used); #endif @@ -248,7 +249,7 @@ static int wanpipe_port_management(wanpipe_wandev_t *wdev, void *data) case GET_DRIVER_VERSION: /* Fill in "DRIVER_VERSION" structure. */ - + err = wanpipe_mgmnt_get_driver_version(wdev, wandev, usr_port_mgmnt); break; case GET_PORT_OPERATIONAL_STATS: @@ -295,7 +296,7 @@ static int wanpipe_port_cfg(wanpipe_wandev_t *wdev, void *data) char card_name[100]; if (!wdev || !data) { - DEBUG_EVENT("%s: Error: Invalid wdev or data ptrs \n",__FUNCTION__); + DEBUG_ERROR("%s: Error: Invalid wdev or data ptrs \n",__FUNCTION__); return -EFAULT; } @@ -312,6 +313,8 @@ static int wanpipe_port_cfg(wanpipe_wandev_t *wdev, void *data) if (err) { goto wanpipe_port_cfg_exit; } + + usr_port_cfg->operation_status = SANG_STATUS_INVALID_DEVICE; if (!usr_port_cfg->port_no) { goto wanpipe_port_cfg_exit; @@ -319,6 +322,7 @@ static int wanpipe_port_cfg(wanpipe_wandev_t *wdev, void *data) sprintf(card_name,"wanpipe%d",usr_port_cfg->port_no); + wandev=wan_find_wandev_device(card_name); if (!wandev) { err=-ENODEV; @@ -334,9 +338,9 @@ static int wanpipe_port_cfg(wanpipe_wandev_t *wdev, void *data) goto wanpipe_port_cfg_exit; } - err= WAN_COPY_TO_USER(data, - wandev->port_cfg, - sizeof(wanpipe_port_cfg_t)); + err=0; + memcpy(usr_port_cfg,wandev->port_cfg, sizeof(wanpipe_port_cfg_t)); + /* Get current Port configuration stored in a Port's Driver memory buffer */ break; @@ -355,20 +359,25 @@ static int wanpipe_port_cfg(wanpipe_wandev_t *wdev, void *data) } } - err=WAN_COPY_FROM_USER(wandev->port_cfg, - data, - sizeof(wanpipe_port_cfg_t)); - + err=0; + memcpy(wandev->port_cfg,usr_port_cfg,sizeof(wanpipe_port_cfg_t)); break; } + if (err == 0) { + usr_port_cfg->operation_status = SANG_STATUS_SUCCESS; + } wanpipe_port_cfg_exit: - if (usr_port_cfg) { + + err= WAN_COPY_TO_USER(data, + usr_port_cfg, + sizeof(wanpipe_port_cfg_t)); + wan_free(usr_port_cfg); usr_port_cfg=NULL; } @@ -379,6 +388,20 @@ wanpipe_port_cfg_exit: } +static int wanpipe_mgmnt_get_driver_version(wanpipe_wandev_t *wdev, wan_device_t *wandev, port_management_struct_t *usr_port_mgmnt) +{ + wan_driver_version_t *drv_ver = (wan_driver_version_t*)usr_port_mgmnt->data; + + drv_ver->major=WANPIPE_VERSION_MAJOR; + drv_ver->minor=WANPIPE_VERSION_MINOR; + drv_ver->minor1=WANPIPE_VERSION_MINOR1; + drv_ver->minor2=WANPIPE_VERSION_MINOR2; + + usr_port_mgmnt->operation_status = 0; + return 0; +} + + static int wanpipe_mgmnt_get_hardware_info(wanpipe_wandev_t *wdev, wan_device_t *wandev, port_management_struct_t *usr_port_mgmnt) { diff --git a/patches/kdrivers/src/xmtp2km/_xmtp2km.h b/patches/kdrivers/src/xmtp2km/_xmtp2km.h index 635935b..eea5b64 100644 --- a/patches/kdrivers/src/xmtp2km/_xmtp2km.h +++ b/patches/kdrivers/src/xmtp2km/_xmtp2km.h @@ -49,6 +49,7 @@ extern int xmtp2km_qset; extern int xmtp2km_p_buffer; /* pipe.c */ +extern int xmtp2km_ratelimit(void); /* * Prototypes for shared functions diff --git a/patches/kdrivers/src/xmtp2km/bin/xmtp2km.gcc3.i386.o b/patches/kdrivers/src/xmtp2km/bin/xmtp2km.gcc3.i386.o index 97444b1..4d87710 100644 Binary files a/patches/kdrivers/src/xmtp2km/bin/xmtp2km.gcc3.i386.o and b/patches/kdrivers/src/xmtp2km/bin/xmtp2km.gcc3.i386.o differ diff --git a/patches/kdrivers/src/xmtp2km/bin/xmtp2km.gcc3.i386.regparm.o b/patches/kdrivers/src/xmtp2km/bin/xmtp2km.gcc3.i386.regparm.o index 385bf16..4e69707 100644 Binary files a/patches/kdrivers/src/xmtp2km/bin/xmtp2km.gcc3.i386.regparm.o and b/patches/kdrivers/src/xmtp2km/bin/xmtp2km.gcc3.i386.regparm.o differ diff --git a/patches/kdrivers/src/xmtp2km/bin/xmtp2km.gcc3.i686.o b/patches/kdrivers/src/xmtp2km/bin/xmtp2km.gcc3.i686.o index 123573e..bdb99d0 100644 Binary files a/patches/kdrivers/src/xmtp2km/bin/xmtp2km.gcc3.i686.o and b/patches/kdrivers/src/xmtp2km/bin/xmtp2km.gcc3.i686.o differ diff --git a/patches/kdrivers/src/xmtp2km/bin/xmtp2km.gcc3.i686.regparm.o b/patches/kdrivers/src/xmtp2km/bin/xmtp2km.gcc3.i686.regparm.o index 1575164..a86e988 100644 Binary files a/patches/kdrivers/src/xmtp2km/bin/xmtp2km.gcc3.i686.regparm.o and b/patches/kdrivers/src/xmtp2km/bin/xmtp2km.gcc3.i686.regparm.o differ diff --git a/patches/kdrivers/src/xmtp2km/kern_if.h b/patches/kdrivers/src/xmtp2km/kern_if.h index 744a0e1..7f6cd40 100644 --- a/patches/kdrivers/src/xmtp2km/kern_if.h +++ b/patches/kdrivers/src/xmtp2km/kern_if.h @@ -22,7 +22,8 @@ enum { XMTP2_VERIFY_WRITE }; - +void * xmtp2km_kmalloc (const unsigned int bsize); +void xmtp2km_kfree (void * p_buffer); int xmtp2km_access_ok (int type, const void *p_addr, unsigned long n); unsigned long xmtp2km_copy_to_user (void *p_to, const void *p_from, unsigned long n); unsigned long xmtp2km_copy_from_user (void *p_to, const void *p_from, unsigned long n); @@ -32,26 +33,4 @@ void * xmtp2km_memcpy(void * p_to, const void * p_from, const unsigned int n); void xmtp2_printk(const char * fmt, ...); void* xmtp2_memset(void *b, int c, int len); -void xmtp2km_spin_lock_init(void); -void xmtp2km_spin_lock_irq(unsigned long *flag); -void xmtp2km_spin_unlock_irq(unsigned long *flag); -void xmtp2km_spin_lock(void); -void xmtp2km_spin_unlock(void); - -int xmtp2km_rate_limit(void); -void xmtp2_mdelay(int ms); -int xmtp2km_ioctl_close(void); - -#ifdef XMTP2_MEM_DEBUG -void * __xmtp2km_kmalloc (const unsigned int bsize, char *func, int line); -void __xmtp2km_kfree (void * p_buffer, char *func, int line); -#define xmtp2km_kmalloc(size) __xmtp2km_kmalloc(size,(char*)__FUNCTION__,(int)__LINE__) -#define xmtp2km_kfree(ptr) __xmtp2km_kfree(ptr,(char*)__FUNCTION__,(int)__LINE__) -#else -void * __xmtp2km_kmalloc (const unsigned int bsize); -void __xmtp2km_kfree (void * p_buffer); -#define xmtp2km_kmalloc(a) __xmtp2km_kmalloc(a) -#define xmtp2km_kfree(a) __xmtp2km_kfree(a) -#endif - #endif diff --git a/patches/kdrivers/src/xmtp2km/main2_6.c b/patches/kdrivers/src/xmtp2km/main2_6.c index b5c846c..5a260ab 100644 --- a/patches/kdrivers/src/xmtp2km/main2_6.c +++ b/patches/kdrivers/src/xmtp2km/main2_6.c @@ -33,7 +33,6 @@ #include #include #include -#include #include /* cli(), *_flags */ #include /* copy_*_user */ @@ -44,9 +43,6 @@ /* parameters which can be set at load time */ -#undef XMTP2KM_DEBUG_MEM -#undef XMTP2KM_SPIN - int xmtp2km_major = XMTP2KM_MAJOR; int xmtp2km_minor = 0; int xmtp2km_nr_devs = XMTP2KM_NR_DEVS; /* number of bare xmtp2km devices */ @@ -58,12 +54,14 @@ MODULE_AUTHOR("Michael Mueller/Xygnada Technology, Inc."); MODULE_LICENSE("Dual BSD/GPL"); struct xmtp2km_dev *xmtp2km_devices; /* allocated in xmtp2km_init_module */ -spinlock_t xmtp2km_lock; /* extern global vars */ extern int module_use_count; +static spinlock_t xmtp2km_spinlock; + /* prototypes for non-open parts of xmtp2km kernel modules */ /* prototypes for functions used by the Sangoma xmtp2 LIP device driver */ +#if 0 void xmtp2km_bs_handler (int fi, int len, uint8_t * p_rxbs, uint8_t * p_txbs); void xmtp2km_facility_state_change (int card_iface_id, int state); int xmtp2km_unregister (int fi); @@ -71,9 +69,16 @@ int xmtp2km_register ( void * p_instance_data, char * ps_ifname, int (*sangoma_drvr_cb)(void*, unsigned char*, int)); +int xmtp2km_tap_disable(int card_iface_id); +int xmtp2km_tap_enable( + int card_iface_id, + void *dev, + int (*frame)(void *ptr, int slot, int dir, unsigned char *data, int len)); +#else + #include "xmtp2km_kiface.h" +#endif /* prototypes for functions used by the xmtp2km kernel module ioctl function */ int xmtp2km_ioctl_binit (void); -int xmtp2km_ioctl_stop_fac (unsigned int cmd, unsigned long arg); int xmtp2km_ioctl_opsparms (unsigned int cmd, unsigned long arg); int xmtp2km_ioctl_pwr_on (unsigned int cmd, unsigned long arg); int xmtp2km_ioctl_emergency (unsigned int cmd, unsigned long arg); @@ -85,48 +90,13 @@ int xmtp2km_ioctl_getbsnt (unsigned int cmd, unsigned long arg); int xmtp2km_ioctl_gettbq (unsigned int cmd, unsigned long arg); int xmtp2km_ioctl_lnkrcvy (unsigned int cmd, unsigned long arg); int xmtp2km_ioctl_getopm (unsigned int cmd, unsigned long arg); +int xmtp2km_ioctl_close(void); +int xmtp2km_ioctl_stop_fac (unsigned int cmd, unsigned long arg); /* protoypes for functions used by the xmtp2km kernel module startup and shutdown functions */ void xmtp2km_init (void); void xmtp2km_shutdown (void); -int xmtp2km_rate_limit(void) -{ - return net_ratelimit(); -} -void xmtp2km_spin_lock_init(void) -{ - spin_lock_init(&xmtp2km_lock); -} - -void xmtp2km_spin_lock_irq(unsigned long *flag) -{ -#ifdef XMTP2KM_SPIN -... - spin_lock_irqsave(&xmtp2km_lock,*flag); -#endif -} - -void xmtp2km_spin_unlock_irq(unsigned long *flag) -{ -#ifdef XMTP2KM_SPIN - spin_unlock_irqrestore(&xmtp2km_lock,*flag); -#endif -} - -void xmtp2km_spin_lock(void) -{ -#ifdef XMTP2KM_SPIN - spin_lock(&xmtp2km_lock); -#endif -} - -void xmtp2km_spin_unlock(void) -{ -#ifdef XMTP2KM_SPIN - spin_unlock(&xmtp2km_lock); -#endif -} void* xmtp2_memset(void *b, int c, int len) { @@ -143,42 +113,33 @@ void xmtp2_printk(const char * fmt, ...) va_end(args); } -#ifdef XMTP2_MEM_DEBUG -extern int sdla_memdbg_push(void *mem, char *func_name, int line, int len); -void * __xmtp2km_kmalloc (const unsigned int bsize, char *func, int line) -#else -void * __xmtp2km_kmalloc (const unsigned int bsize) -#endif +void * xmtp2km_kmalloc (const unsigned int bsize) /***************************************************************************************/ { - void *ptr=kmalloc (bsize, GFP_ATOMIC); - -#ifdef XMTP2_MEM_DEBUG - if (ptr) { - sdla_memdbg_push(ptr,func,line,bsize); - } -#endif - - return ptr; + return kmalloc (bsize, GFP_ATOMIC); } - -#ifdef XMTP2_MEM_DEBUG -extern int sdla_memdbg_pull(void *mem, char *func_name, int line); -void __xmtp2km_kfree (void * p_buffer, char *func, int line) -#else -void __xmtp2km_kfree (void * p_buffer) -#endif +void xmtp2km_kfree (void * p_buffer) /***************************************************************************************/ { -#ifdef XMTP2_MEM_DEBUG - if (p_buffer) { - sdla_memdbg_pull(p_buffer,func,line); - } -#endif kfree (p_buffer); } +void xmtp2km_lock(unsigned long *flags) +{ + spin_lock_irqsave(&xmtp2km_spinlock,*flags); +} + +void xmtp2km_unlock(unsigned long *flags) +{ + spin_unlock_irqrestore(&xmtp2km_spinlock,*flags); +} + +int xmtp2km_ratelimit(void) +{ + return net_ratelimit(); +} + int xmtp2km_access_ok (int type, const void *p_addr, unsigned long n) /***************************************************************************************/ { @@ -196,21 +157,6 @@ int xmtp2km_access_ok (int type, const void *p_addr, unsigned long n) return 0; } -void xmtp2_mdelay(int s) -{ - /* wait for "milliseconds * 1/1000" of sec */ - unsigned long timeout=jiffies; - - if (s > 2) { - s=2; - } - - while (jiffies-timeout < (HZ/10) * s){ - udelay(100); - schedule(); - } -} - unsigned long xmtp2km_copy_to_user (void *p_to, const void *p_from, unsigned long n) /***************************************************************************************/ { @@ -258,9 +204,9 @@ int xmtp2km_release(struct inode *inode, struct file *filp) /***************************************************************************************/ { if (module_use_count > 0) module_use_count--; - + xmtp2km_ioctl_close(); - + return 0; } @@ -270,6 +216,7 @@ int xmtp2km_ioctl(struct inode *inode, struct file *filp, { int err = 0; int ret = 0; /* default is success */ + unsigned long flags; /* * extract the type and number bitfields, and don't decode @@ -291,6 +238,7 @@ int xmtp2km_ioctl(struct inode *inode, struct file *filp, if (err) return -EFAULT; + switch(cmd) { case XMTP2KM_IOCS_BINIT: @@ -300,7 +248,7 @@ int xmtp2km_ioctl(struct inode *inode, struct file *filp, ret = xmtp2km_ioctl_stop_fac (cmd, arg); break; case XMTP2KM_IOCS_OPSPARMS: - ret = xmtp2km_ioctl_opsparms (cmd, arg); + ret = xmtp2km_ioctl_opsparms (cmd, arg); break; case XMTP2KM_IOCS_PWR_ON: //printk ("%s ptr %u size %u\n", __FUNCTION__, (unsigned int)((void __user *)arg), _IOC_SIZE(cmd)); @@ -338,8 +286,11 @@ int xmtp2km_ioctl(struct inode *inode, struct file *filp, ret = xmtp2km_ioctl_getopm (cmd, arg); break; default: /* redundant, as cmd was checked against MAXNR */ - return -ENOTTY; + ret = -ENOTTY; + break; } + + return ret; } @@ -406,13 +357,16 @@ int xmtp2km_init_module(void) int result, i; dev_t dev = 0; - printk ("MARK 0: Nenad 1.0\n"); + printk ("MARK 0\n"); info_u (__FILE__, __FUNCTION__, "MARK", 0); /* * Get a range of minor numbers to work with, asking for a dynamic * major unless directed otherwise at load time. */ + + spin_lock_init(&xmtp2km_spinlock); + if (xmtp2km_major) { dev = MKDEV(xmtp2km_major, xmtp2km_minor); @@ -429,8 +383,6 @@ int xmtp2km_init_module(void) return result; } - xmtp2km_spin_lock_init(); - /* * allocate the devices -- we can't have them static, as the number * can be specified at load time @@ -468,4 +420,6 @@ module_exit(xmtp2km_cleanup_module); EXPORT_SYMBOL (xmtp2km_register); EXPORT_SYMBOL (xmtp2km_unregister); EXPORT_SYMBOL (xmtp2km_bs_handler); +EXPORT_SYMBOL (xmtp2km_tap_enable); +EXPORT_SYMBOL (xmtp2km_tap_disable); EXPORT_SYMBOL (xmtp2km_facility_state_change); diff --git a/patches/kdrivers/src/xmtp2km/xmtp2km.h b/patches/kdrivers/src/xmtp2km/xmtp2km.h index 3c9364c..0217c99 100644 --- a/patches/kdrivers/src/xmtp2km/xmtp2km.h +++ b/patches/kdrivers/src/xmtp2km/xmtp2km.h @@ -55,7 +55,6 @@ #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. diff --git a/patches/kdrivers/src/xmtp2km/xmtp2km_kiface.h b/patches/kdrivers/src/xmtp2km/xmtp2km_kiface.h index c42eb6d..d084c8b 100644 --- a/patches/kdrivers/src/xmtp2km/xmtp2km_kiface.h +++ b/patches/kdrivers/src/xmtp2km/xmtp2km_kiface.h @@ -7,15 +7,12 @@ #ifndef _XMTP2KM_IFACE_H #define _XMTP2KM_IFACE_H -void xmtp2km_bs_handler (int fi, int len, unsigned char * p_rxbs, unsigned char * p_txbs); +void xmtp2km_bs_handler (int fi, int len, uint8_t * p_rxbs, uint8_t *p_txbs); int xmtp2km_register (void *, char *, int (*callback)(void*, unsigned char*, int)); int xmtp2km_unregister (int); -int xmtp2km_facility_state_change (int fi, int state); - -#if 0 +void xmtp2km_facility_state_change (int fi, int state); #define AFT_XMTP2_TAP int xmtp2km_tap_disable(int card_iface_id); int xmtp2km_tap_enable(int card_iface_id, void *dev, int (*frame)(void *ptr, int slot, int dir, unsigned char *data, int len)); -#endif #endif diff --git a/patches/kdrivers/wanec/wanec.mod.c b/patches/kdrivers/wanec/wanec.mod.c index d43aa5c..608a1da 100644 --- a/patches/kdrivers/wanec/wanec.mod.c +++ b/patches/kdrivers/wanec/wanec.mod.c @@ -58,4 +58,4 @@ __attribute__((section(".modinfo"))) = "depends=sdladrv,wanrouter"; -MODULE_INFO(srcversion, "76D1AB69F84D05B5AD36F13"); +MODULE_INFO(srcversion, "9C8B8A6EB863F7175F3623D"); diff --git a/patches/kdrivers/wanec/wanec_cmd.c b/patches/kdrivers/wanec/wanec_cmd.c index e7ee1fd..2a0dcde 100644 --- a/patches/kdrivers/wanec/wanec_cmd.c +++ b/patches/kdrivers/wanec/wanec_cmd.c @@ -694,6 +694,8 @@ int wanec_ChannelOpen(wan_ec_dev_t *ec_dev, INT ec_chan, int verbose) EchoChannelOpen.ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_NORMAL; #else + /* purposely fail the compile */ +#error "No supported mode" EchoChannelOpen.ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_POWER_DOWN; #endif @@ -720,9 +722,39 @@ int wanec_ChannelOpen(wan_ec_dev_t *ec_dev, INT ec_chan, int verbose) EchoChannelOpen.VqeConfig.fEnableNlp = TRUE; EchoChannelOpen.VqeConfig.fRinDcOffsetRemoval = TRUE; EchoChannelOpen.VqeConfig.fSinDcOffsetRemoval = TRUE; -#if defined(ENABLE_ACOUSTICECHO) - EchoChannelOpen.VqeConfig.fAcousticEcho = TRUE; -#endif + + if (card->hwec_conf.acustic_echo) { + EchoChannelOpen.VqeConfig.fAcousticEcho = TRUE; + } else { + EchoChannelOpen.VqeConfig.fAcousticEcho = FALSE; + } + + if (card->hwec_conf.nlp_disable) { + EchoChannelOpen.VqeConfig.fEnableNlp = FALSE; + } else { + EchoChannelOpen.VqeConfig.fEnableNlp = TRUE; + } + + if (card->hwec_conf.operation_mode) { + switch (card->hwec_conf.operation_mode) { + case WANOPT_OCT_CHAN_OPERMODE_SPEECH: + EchoChannelOpen.ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION; + break; + default: + EchoChannelOpen.ulEchoOperationMode=cOCT6100_ECHO_OP_MODE_NORMAL; + break; + } + } else { + EchoChannelOpen.ulEchoOperationMode=cOCT6100_ECHO_OP_MODE_NORMAL; + } + + + if (card->tdmv_conf.hw_dtmf && card->hwec_conf.dtmf_removal) { + EchoChannelOpen.VqeConfig.fDtmfToneRemoval = TRUE; + } else { + EchoChannelOpen.VqeConfig.fDtmfToneRemoval = FALSE; + } + if (card->hwec_conf.tone_disabler_delay) { UINT32 delay = card->hwec_conf.tone_disabler_delay; delay = ((delay / 512) + 1) * 512 + 300; @@ -735,19 +767,34 @@ int wanec_ChannelOpen(wan_ec_dev_t *ec_dev, INT ec_chan, int verbose) if (card->hwec_conf.noise_reduction) { EchoChannelOpen.VqeConfig.fSoutAdaptiveNoiseReduction = TRUE; - EchoChannelOpen.VqeConfig.fRinAutomaticLevelControl = TRUE; - EchoChannelOpen.VqeConfig.fSoutAutomaticLevelControl = TRUE; } else { EchoChannelOpen.VqeConfig.fSoutAdaptiveNoiseReduction = FALSE; - EchoChannelOpen.VqeConfig.fRinAutomaticLevelControl = FALSE; + } + + if (card->hwec_conf.rx_auto_gain) { + EchoChannelOpen.VqeConfig.fSoutAutomaticLevelControl = TRUE; + EchoChannelOpen.VqeConfig.lSoutAutomaticLevelControlTargetDb = card->hwec_conf.rx_auto_gain; + } else { EchoChannelOpen.VqeConfig.fSoutAutomaticLevelControl = FALSE; } + + if (card->hwec_conf.tx_auto_gain) { + EchoChannelOpen.VqeConfig.fRinAutomaticLevelControl = TRUE; + EchoChannelOpen.VqeConfig.lRinAutomaticLevelControlTargetDb = card->hwec_conf.tx_auto_gain; + } else { + EchoChannelOpen.VqeConfig.fRinAutomaticLevelControl = FALSE; + } EchoChannelOpen.VqeConfig.ulToneDisablerVqeActivationDelay = ((UINT16)(1500 / 512) + 1) * 512 + 300; /*300;*/ - DEBUG_EVENT("%s: Opening HW Echo Canceller (NoiseRed=%s VQE=%i)\n", - ec->name,(EchoChannelOpen.VqeConfig.fSoutAdaptiveNoiseReduction == TRUE)?"On":"Off", - EchoChannelOpen.VqeConfig.ulToneDisablerVqeActivationDelay); + DEBUG_EVENT("%s: Opening HW Echo: [Mode=%s NoiseRed=%s VQE=%i DtmfRmv=%s TxAGain=%i RxAGain=%i]\n", + ec->name, + EchoChannelOpen.ulEchoOperationMode==cOCT6100_ECHO_OP_MODE_NORMAL?"Normal":"Speech", + (EchoChannelOpen.VqeConfig.fSoutAdaptiveNoiseReduction == TRUE)?"On":"Off", + EchoChannelOpen.VqeConfig.ulToneDisablerVqeActivationDelay, + EchoChannelOpen.VqeConfig.fDtmfToneRemoval==TRUE?"On":"Off", + card->hwec_conf.tx_auto_gain, + card->hwec_conf.rx_auto_gain); EchoChannelOpen.VqeConfig.ulComfortNoiseMode = cOCT6100_COMFORT_NOISE_NORMAL; diff --git a/patches/kdrivers/wanec/wanec_iface.c b/patches/kdrivers/wanec/wanec_iface.c index ac0cd71..95bbb31 100644 --- a/patches/kdrivers/wanec/wanec_iface.c +++ b/patches/kdrivers/wanec/wanec_iface.c @@ -284,7 +284,7 @@ static int wanec_state(void *pcard, wan_hwec_dev_state_t *ecdev_state) WAN_ASSERT(ec_dev->ec == NULL); ec = ec_dev->ec; - if (ec->state == WAN_EC_STATE_CHIP_OPEN) { + if (ec->state == WAN_EC_STATE_CHIP_OPEN && ec_dev->state == WAN_EC_STATE_CHAN_READY) { ec_dev->ecdev_state.ec_state=1; } else { ec_dev->ecdev_state.ec_state=0; @@ -321,6 +321,9 @@ static int wanec_enable(void *pcard, int enable, int fe_chan) return -EINVAL; } + if (ec_dev->state != WAN_EC_STATE_CHAN_READY) { + return -EINVAL; + } #if defined(WANEC_BYDEFAULT_NORMAL) WAN_ASSERT(ec_dev->ec == NULL); @@ -333,7 +336,7 @@ static int wanec_enable(void *pcard, int enable, int fe_chan) return wanec_channel_opmode_modify( ec_dev, fe_chan, - (enable) ? cOCT6100_ECHO_OP_MODE_NORMAL : cOCT6100_ECHO_OP_MODE_POWER_DOWN, + (enable) ? cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION : cOCT6100_ECHO_OP_MODE_POWER_DOWN, 0); #endif } @@ -962,7 +965,7 @@ static int wanec_api_modify(wan_ec_dev_t *ec_dev, wan_ec_api_t *ec_api) if (cmd == WAN_EC_API_CMD_ENABLE){ err = wanec_channel_opmode_modify( ec_dev, fe_chan, - cOCT6100_ECHO_OP_MODE_NORMAL, + cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION, ec_api->verbose); if (err) { return WAN_EC_API_RC_FAILED; diff --git a/rpmspec/wanpipe-mod.spec b/rpmspec/wanpipe-mod.spec index dc6d730..380923a 100644 --- a/rpmspec/wanpipe-mod.spec +++ b/rpmspec/wanpipe-mod.spec @@ -1,6 +1,6 @@ %define WANPIPE_VER wanpipe-modules %define name %{WANPIPE_VER} -%define version 3.5.11 +%define version 3.5.12 %define release 0 %define serial 1 %define MODULES_DIR /lib/modules @@ -51,6 +51,42 @@ echo "Wanpipe Modules located in %{MODULES_DIR}/%{KVERSION}" %changelog +* Mon Jun 28 2010 Nenad Corbic - 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 - 3.5.11 =================================================================== diff --git a/rpmspec/wanpipe-util.spec b/rpmspec/wanpipe-util.spec index 388b358..6a139fd 100644 --- a/rpmspec/wanpipe-util.spec +++ b/rpmspec/wanpipe-util.spec @@ -1,7 +1,7 @@ %define KERNEL_VERSION %{?kern_ver} %define WANPIPE_VER wanpipe-util %define name %{WANPIPE_VER} -%define version 3.5.11 +%define version 3.5.12 %define release 0 %define serial 1 %define ETC_DIR /etc @@ -328,6 +328,42 @@ enable_smg_log; %changelog +* Mon Jun 28 2010 Nenad Corbic - 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 - 3.5.11 =================================================================== diff --git a/rpmspec/wanpipe.spec b/rpmspec/wanpipe.spec index b015240..a6a1c3f 100644 --- a/rpmspec/wanpipe.spec +++ b/rpmspec/wanpipe.spec @@ -1,7 +1,7 @@ %define KERNEL_VERSION %{?kern_ver} %define WANPIPE_VER wanpipe %define name %{WANPIPE_VER} -%define version 3.5.11 +%define version 3.5.12 %define release 0 %define serial 1 %define UTILS_DIR /usr/sbin @@ -255,6 +255,42 @@ install_init; %changelog +* Mon Jun 28 2010 Nenad Corbic - 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 - 3.5.11 =================================================================== diff --git a/samples/wanpipe1.new_ec_stuff b/samples/wanpipe1.new_ec_stuff new file mode 100644 index 0000000..f8c5182 --- /dev/null +++ b/samples/wanpipe1.new_ec_stuff @@ -0,0 +1,62 @@ +#================================================ +# WANPIPE1 Configuration File +#================================================ +# +# Date: Wed Dec 6 20:29:03 UTC 2006 +# +# Note: This file was generated automatically +# by /usr/local/sbin/setup-sangoma 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, ,TDM_CHAN_VOICE_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 = CRC4 +FE_LINE = 1 +TE_CLOCK = NORMAL +TE_REF_CLOCK = 0 +TE_SIG_MODE = CCS +TE_HIGHIMPEDANCE = NO +LBO = 120OH +FE_TXTRISTATE = NO +MTU = 1500 +UDPPORT = 9000 +TTL = 255 +IGNORE_FRONT_END = NO +TDMV_SPAN = 1 +TDMV_DCHAN = 16 +RX_CRC_BYTES=3 + +TDMV_HW_DTMF = NO # YES: receive dtmf events from hardware +TDMV_HW_FAX_DETECT = NO # YES: receive fax 1100hz events from hardware +HWEC_OPERATION_MODE = OCT_NORMAL # OCT_NORMAL: default OCT_SPEECH - improves software tone detection +HWEC_DTMF_REMOVAL = YES # 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 -20: default audio level +HWEC_RX_AUTO_GAIN = 0 # 0: disable -20: default audio level + + +[w1g1] +ACTIVE_CH = ALL +TDMV_HWEC = YES +MTU = 8 diff --git a/samples/wanrouter b/samples/wanrouter index d15ccf5..a8f63c4 100644 --- a/samples/wanrouter +++ b/samples/wanrouter @@ -2208,7 +2208,7 @@ init_global_params() { if [ $OSYSTEM = "Linux" ]; then - ROUTER_VERSION=3.5.11 + ROUTER_VERSION=3.5.12 IFCONFIG_LIST=ifconfig MODULE_STAT=lsmod WAN_DRIVERS="wanpipe" diff --git a/scripts/Compile.sh b/scripts/Compile.sh index 8061590..dca3221 100644 --- a/scripts/Compile.sh +++ b/scripts/Compile.sh @@ -1,5 +1,5 @@ #!/bin/sh -make CFLAGS=" -Wp,-MD,.wanpipe.o.d -nostdinc -iwithprefix include -D__LINUX__ -Dlinux -D__KERNEL__ -I/lib/modules/2.6.18-164.el5/build/include -DMODULE -DAF_WANPIPE_2612_FORCE_UPDATE -DWANPIPE_MOD_266_FORCE_UPDATE -m32 -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Wstrict-prototypes -Wundef -Werror-implicit-function-declaration -fno-delete-null-pointer-checks -fwrapv -Os -pipe -msoft-float -fno-builtin-sprintf -fno-builtin-log2 -fno-builtin-puts -mpreferred-stack-boundary=2 -march=i686 -mtune=generic -mtune=generic -mregparm=3 -ffreestanding -I/lib/modules/2.6.18-164.el5/build/include/asm-i386/mach-generic -I/lib/modules/2.6.18-164.el5/build/include/asm-i386/mach-default -fomit-frame-pointer -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -D__KERNEL__ -Iinclude -include include/linux/autoconf.h -I/usr/src/dahdi" PROTOCOL_DEFINES="-DCONFIG_PRODUCT_WANPIPE_BASE -DCONFIG_PRODUCT_WANPIPE_TDM_VOICE -DCONFIG_PRODUCT_WANPIPE_TDM_VOICE_DCHAN -DCONFIG_PRODUCT_WANPIPE_TDM_VOICE_DCHAN_ZAPTEL -DDAHDI_ISSUES -DCONFIG_PRODUCT_WANPIPE_FR -DCONFIG_PRODUCT_WANPIPE_CHDLC -DCONFIG_PRODUCT_WANPIPE_PPP -DCONFIG_PRODUCT_WANPIPE_X25 -DCONFIG_PRODUCT_WANPIPE_ADSL -DCONFIG_PRODUCT_WANPIPE_LIP_ATM -DCONFIG_PRODUCT_WANPIPE_ATM -DCONFIG_PRODUCT_WANPIPE_MULTPROT -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_A700 -DCONFIG_PRODUCT_WANPIPE_USB -DCONFIG_PRODUCT_WANPIPE_AFT_TE3 -DWANPIPE_USE_I_PRIVATE -DCONFIG_WANPIPE_HWEC " +make CFLAGS=" -Wp,-MD,.wanpipe.o.d -nostdinc -iwithprefix include -D__LINUX__ -Dlinux -D__KERNEL__ -I/lib/modules/2.6.18-164.el5/build/include -DMODULE -DAF_WANPIPE_2612_FORCE_UPDATE -DWANPIPE_MOD_266_FORCE_UPDATE -m32 -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Wstrict-prototypes -Wundef -Werror-implicit-function-declaration -fno-delete-null-pointer-checks -fwrapv -Os -pipe -msoft-float -fno-builtin-sprintf -fno-builtin-log2 -fno-builtin-puts -mpreferred-stack-boundary=2 -march=i686 -mtune=generic -mtune=generic -mregparm=3 -ffreestanding -I/lib/modules/2.6.18-164.el5/build/include/asm-i386/mach-generic -I/lib/modules/2.6.18-164.el5/build/include/asm-i386/mach-default -fomit-frame-pointer -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -D__KERNEL__ -Iinclude -include include/linux/autoconf.h " PROTOCOL_DEFINES="-DCONFIG_PRODUCT_WANPIPE_BASE -DCONFIG_PRODUCT_WANPIPE_XMTP2 -DAFT_XMTP2_API_SUPPORT -I/root/3.5/wanpipe/patches/kdrivers/src/xmtp2km -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_A700 -DCONFIG_PRODUCT_WANPIPE_USB -DWANPIPE_USE_I_PRIVATE -DCONFIG_WANPIPE_HWEC " diff --git a/ssmg/get_sangoma_prid.sh b/ssmg/get_sangoma_prid.sh new file mode 100755 index 0000000..2d736a1 --- /dev/null +++ b/ssmg/get_sangoma_prid.sh @@ -0,0 +1,69 @@ +#!/bin/bash -p +MY_ARCH="i386" +UPDATE="NO" +ARCH=`uname -m` +if [ $ARCH = "x86_64" ]; then + MY_ARCH="x86_64" +fi + +if [ $1 ] && [ "$1" == "--update" ]; then + UPDATE="YES" +fi + +#version format: wanpipe-... + +ROUTER_VERSION_MAIN="`cat ../.router_version | cut -d "-" -f2 | cut -d "." -f1`" +ROUTER_VERSION_MAJOR="`cat ../.router_version | cut -d "-" -f2 | cut -d "." -f2`" +ROUTER_VERSION_MINOR="`cat ../.router_version | cut -d "-" -f2 | cut -d "." -f3`" +ROUTER_VERSION_SUB="`cat ../.router_version | cut -d "-" -f2 | cut -d "." -f4`" + +ROUTER_VERSION=$ROUTER_VERSION_MAIN.$ROUTER_VERSION_MAJOR.$ROUTER_VERSION_MINOR.$ROUTER_VERSION_SUB +ROUTER_VERSION_MAIN_RELEASE=$ROUTER_VERSION_MAIN.$ROUTER_VERSION_MAJOR.$ROUTER_VERSION_MINOR + +if [ "$ROUTER_VERSION" = "" ]; then + echo "Failed to obtain wanrouter version" + exit 1 +fi + + +PRI_PACKAGE_FORMAT="sangoma_prid-*-$ROUTER_VERSION.$MY_ARCH.tgz" +PRI_PACKAGE_NAME="`find -name \"$PRI_PACKAGE_FORMAT\" | cut -d "/" -f2`" + +if [ "$PRI_PACKAGE_NAME" != "" ] && [ "$UPDATE" != "YES" ]; then + echo "Using $PRI_PACKAGE_NAME" + echo " " +else + #if a pri package was already downloaded + if [ "$PRI_PACKAGE_NAME" != "" ]; then + echo "Renaming $PRI_PACKAGE_NAME to $PRI_PACKAGE_NAME.old" + eval "mv -f $PRI_PACKAGE_NAME $PRI_PACKAGE_NAME.old" + if [ $? -ne 0 ]; then + echo "Failed to rename existing sangoma_prid package" + exit 1 + fi + fi + echo "Fetching PRI package from Sangoma FTP" + eval "wget ftp://ftp.sangoma.com/linux/sangoma_prid/wanpipe-$ROUTER_VERSION/sangoma_prid-*-$ROUTER_VERSION.$MY_ARCH.tgz" + if [ $? -ne 0 ]; then + echo "Looking for $ROUTER_VERSION_MAIN_RELEASE" + eval "wget ftp://ftp.sangoma.com/linux/sangoma_prid/wanpipe-$ROUTER_VERSION_MAIN_RELEASE/sangoma_prid-*-$ROUTER_VERSION_MAIN_RELEASE.$MY_ARCH.tgz" + PRI_PACKAGE_FORMAT="sangoma_prid-*-$ROUTER_VERSION_MAIN_RELEASE.$MY_ARCH.tgz" + if [ $? -ne 0 ]; then + echo "Failed to obtain PRI package for this release" + if [ "$PRI_PACKAGE_NAME" != "" ]; then + echo "Using old sangoma_pri package $PRI_PACKAGE_NAME" + eval "mv -f $PRI_PACKAGE_NAME.old $PRI_PACKAGE_NAME" + else + exit 1 + fi + fi + fi + PRI_PACKAGE_NAME="`find -name \"$PRI_PACKAGE_FORMAT\" | cut -d "/" -f2`" +fi +echo "Extracting $PRI_PACKAGE_NAME" +echo " " +eval "tar xfz $PRI_PACKAGE_NAME" +if [ $? -ne 0 ]; then + echo "Error: Invalid/Corrupt PRI package tarball" + exit 1 +fi diff --git a/ssmg/sangoma_bri/sangoma_brid.i686 b/ssmg/sangoma_bri/sangoma_brid.i686 index 415bf08..b076c2f 100755 Binary files a/ssmg/sangoma_bri/sangoma_brid.i686 and b/ssmg/sangoma_bri/sangoma_brid.i686 differ diff --git a/ssmg/sangoma_bri/sangoma_brid.x86_64 b/ssmg/sangoma_bri/sangoma_brid.x86_64 index 8d91e6a..2de8884 100755 Binary files a/ssmg/sangoma_bri/sangoma_brid.x86_64 and b/ssmg/sangoma_bri/sangoma_brid.x86_64 differ diff --git a/ssmg/sangoma_mgd.trunk/.svn/all-wcprops b/ssmg/sangoma_mgd.trunk/.svn/all-wcprops index 12ac7d8..3864986 100644 --- a/ssmg/sangoma_mgd.trunk/.svn/all-wcprops +++ b/ssmg/sangoma_mgd.trunk/.svn/all-wcprops @@ -1,7 +1,7 @@ K 25 svn:wc:ra_dav:version-url V 35 -/svn/sangoma_mgd/!svn/ver/276/trunk +/svn/sangoma_mgd/!svn/ver/282/trunk END sigboost.h K 25 @@ -73,7 +73,7 @@ sangoma_mgd.c K 25 svn:wc:ra_dav:version-url V 49 -/svn/sangoma_mgd/!svn/ver/277/trunk/sangoma_mgd.c +/svn/sangoma_mgd/!svn/ver/282/trunk/sangoma_mgd.c END woomera.conf K 25 @@ -103,13 +103,13 @@ Changelog.sangoma_mgd K 25 svn:wc:ra_dav:version-url V 57 -/svn/sangoma_mgd/!svn/ver/161/trunk/Changelog.sangoma_mgd +/svn/sangoma_mgd/!svn/ver/282/trunk/Changelog.sangoma_mgd END sangoma_mgd.h K 25 svn:wc:ra_dav:version-url V 49 -/svn/sangoma_mgd/!svn/ver/267/trunk/sangoma_mgd.h +/svn/sangoma_mgd/!svn/ver/280/trunk/sangoma_mgd.h END q931_cause.h K 25 @@ -145,7 +145,7 @@ smg_ctrl K 25 svn:wc:ra_dav:version-url V 44 -/svn/sangoma_mgd/!svn/ver/274/trunk/smg_ctrl +/svn/sangoma_mgd/!svn/ver/278/trunk/smg_ctrl END switch_buffer.c K 25 diff --git a/ssmg/sangoma_mgd.trunk/.svn/entries b/ssmg/sangoma_mgd.trunk/.svn/entries index 799b022..46beda7 100644 --- a/ssmg/sangoma_mgd.trunk/.svn/entries +++ b/ssmg/sangoma_mgd.trunk/.svn/entries @@ -1,14 +1,14 @@ 8 dir -276 +282 https://www.sangomapbx.com/svn/sangoma_mgd/trunk https://www.sangomapbx.com/svn/sangoma_mgd -2010-04-05T23:09:34.203565Z -276 +2010-06-21T23:50:05.691425Z +282 ncorbic @@ -161,10 +161,10 @@ file -2009-08-25T20:44:41.000000Z -9962aba3b7b24fcdadcaee80082fb7fd -2009-04-06T03:34:04.453946Z -161 +2010-06-21T23:24:26.000000Z +8ed0cd94a3fc4abb165ac64d59bf4fff +2010-06-21T23:50:05.691425Z +282 ncorbic rc @@ -285,14 +285,14 @@ davidy sangoma_mgd.c file -277 -2010-04-14T17:12:02.000000Z -0dec4f9ac97c468656e719b01a6fae68 -2010-04-14T19:19:19.339100Z -277 + +2010-06-21T23:24:26.000000Z +9d9037aece4637004d1d8ea95d1a50a7 +2010-06-21T23:50:05.691425Z +282 ncorbic woomera.conf @@ -325,11 +325,11 @@ file -2010-03-20T17:24:17.000000Z -75677e239c9eb1ee8aad8cd27724758c -2010-03-15T20:40:36.509244Z -267 -davidy +2010-05-07T20:06:46.000000Z +d36f5a23893b6f6bfcbc10bbac6469b4 +2010-05-07T22:32:17.579741Z +280 +ncorbic q931_cause.h file @@ -362,11 +362,11 @@ file -2010-03-31T15:59:24.000000Z -97c91d4b12eddb4678eb26e553bc32e9 -2010-03-25T16:29:21.097923Z -274 -jpatel +2010-05-06T20:04:33.000000Z +a14a29f5626818cd593954c5288e967d +2010-04-24T00:03:23.938859Z +278 +davidy has-props switch_buffer.c diff --git a/ssmg/sangoma_mgd.trunk/.svn/text-base/Changelog.sangoma_mgd.svn-base b/ssmg/sangoma_mgd.trunk/.svn/text-base/Changelog.sangoma_mgd.svn-base index 6c13ace..7e48298 100644 --- a/ssmg/sangoma_mgd.trunk/.svn/text-base/Changelog.sangoma_mgd.svn-base +++ b/ssmg/sangoma_mgd.trunk/.svn/text-base/Changelog.sangoma_mgd.svn-base @@ -1,6 +1,11 @@ sangoma_mgd.c ====================================== +Jun 21 2010 + * v1.71 Nenad Corbic + * Added a hwec_chan_status check instead of hwec check. + * This allows some ports to have hwec disabled and others enabled. + Mar 27 2009 * v1.46 Nenad Corbic * Major updates on socket handling. A bug was introducted diff --git a/ssmg/sangoma_mgd.trunk/.svn/text-base/sangoma_mgd.c.svn-base b/ssmg/sangoma_mgd.trunk/.svn/text-base/sangoma_mgd.c.svn-base index 852ec4a..4643480 100644 --- a/ssmg/sangoma_mgd.trunk/.svn/text-base/sangoma_mgd.c.svn-base +++ b/ssmg/sangoma_mgd.trunk/.svn/text-base/sangoma_mgd.c.svn-base @@ -1,7 +1,7 @@ /********************************************************************************* * sangoma_mgd.c -- Sangoma Media Gateway Daemon for Sangoma/Wanpipe Cards * - * Copyright 05-09, Nenad Corbic + * Copyright 05-10, Nenad Corbic * Anthony Minessale II * * This program is free software, distributed under the terms of @@ -9,27 +9,41 @@ * * ============================================= * - * v1.68 David Yat Sin - * Mar 18 2010 - * Media and RING bits implemented + * v1.71 Nenad Corbic + * Jun 21 2010 + * Added a hwec_chan_status check instead of hwec check. + * This allows some ports to have hwec disabled and others enabled. + * + * v1.70 Nenad Corbic + * May 07 2010 + * remove_end_of_digits_char was being run on custom_data. + * thus cutting off the custom isup parameters. + * + * v1.69 David Yat Sin + * May 03 2010 + * Added support for WOOMERA_CUSTOM variable on outgoing calls * - * v1.67 David Yat Sin - * Mar 16 2010 - * Added sanity check for span chan on call stopped and call answered - - * v1.66 David Yat Sin - * Mar 15 2010 - * Fix for WFLAG_SYSTEM_RESET being cleared if when - * no boost msg was received from signalling daemon + * v1.68 David Yat Sin + * Mar 18 2010 + * Media and RING bits implemented + * + * v1.67 David Yat Sin + * Mar 16 2010 + * Added sanity check for span chan on call stopped and call answered + * + * v1.66 David Yat Sin + * Mar 15 2010 + * Fix for WFLAG_SYSTEM_RESET being cleared if when + * no boost msg was received from signalling daemon * * v1.65 David Yat Sin * Mar 10 2010 - * Support for TON and NPI passthrough + * Support for TON and NPI passthrough * * v1.64 David Yat Sin * Feb 22 2010 - * Updated to sigboost 103 - * Added checks for hwec present + * Updated to sigboost 103 + * Added checks for hwec present * * v1.63 Nenad Corbic * Jan 27 2010 @@ -38,19 +52,19 @@ * * v1.62 Konrad Hammel * Jan 26 2010 - * Added rbs relay code + * Added rbs relay code * * v1.61 Konrad Hammel * Jan 19 2010 - * changed all_ckt_busy to be per trunk group. + * changed all_ckt_busy to be per trunk group. * * v1.60 Nenad Corbic * Jan 14 2010 - * Added media sequencing option. - * Check if server has it enabled. + * Added media sequencing option. + * Check if server has it enabled. * * v1.59 Nenad Corbic - * Changed w1g1 to s1c1 + * Changed w1g1 to s1c1 * * v1.58 Nenad Corbic * Added bridge tdm to ip functionality @@ -370,7 +384,7 @@ pthread_mutex_t g_smg_ip_bridge_lock; #endif -#define SMG_VERSION "v1.68" +#define SMG_VERSION "v1.71" /* enable early media */ #if 1 @@ -422,7 +436,7 @@ static int drop_seq=0; const char WELCOME_TEXT[] = "================================================================================\n" -"Sangoma Media Gateway Daemon v1.68 \n" +"Sangoma Media Gateway Daemon v1.71 \n" "\n" "TDM Signal Media Gateway for Sangoma/Wanpipe Cards\n" "Copyright 2005, 2006, 2007 \n" @@ -1460,9 +1474,15 @@ retry_loop: sangoma_frame_len = sangoma_tdm_get_usr_mtu_mru(ms->sangoma_sock,&tdm_api); #ifdef LIBSANGOMA_VERSION +#ifdef WP_API_FEATURE_EC_CHAN_STAT + ms->has_hwec = sangoma_tdm_get_hwec_chan_status(ms->sangoma_sock, &tdm_api); +#else ms->has_hwec = sangoma_tdm_get_hw_ec(ms->sangoma_sock, &tdm_api); - if (ms->has_hwec) { +#endif + if (ms->has_hwec > 0) { sangoma_tdm_disable_hwec(ms->sangoma_sock,&tdm_api); + } else { + ms->has_hwec=0; } #else ms->has_hwec=1; @@ -1708,7 +1728,14 @@ media_retry: } #ifdef LIBSANGOMA_VERSION +#ifdef WP_API_FEATURE_EC_CHAN_STAT + ms->has_hwec = sangoma_tdm_get_hwec_chan_status(ms->sangoma_sock, &tdm_api); +#else ms->has_hwec = sangoma_tdm_get_hw_ec(ms->sangoma_sock, &tdm_api); +#endif + if (ms->has_hwec < 0) { + ms->has_hwec=0; + } #else ms->has_hwec = 1; #endif @@ -3260,6 +3287,7 @@ static int handle_woomera_call_start (struct woomera_interface *woomera, char *rdnis = woomera_message_header(wmsg, "RDNIS"); char *bearer_cap = woomera_message_header(wmsg, "Bearer-Cap"); char *uil1p = woomera_message_header(wmsg, "uil1p"); + char *custom_data = woomera_message_header(wmsg, "xCustom"); char *called = wmsg->callid; char *grp = wmsg->callid; @@ -3396,19 +3424,26 @@ static int handle_woomera_call_start (struct woomera_interface *woomera, event.isup_in_rdnis[0]=0; if (rdnis && strlen(rdnis) ) { - - if (strlen(rdnis) > sizeof(event.isup_in_rdnis)){ + if (strlen(rdnis) > sizeof(event.rdnis.digits)){ log_printf(SMG_LOG_ALL,server.log,"Error: RDNIS Overflow (in size=%i max=%i)\n", - strlen(rdnis), sizeof(event.isup_in_rdnis)); + strlen(rdnis), sizeof(event.rdnis.digits)); } else { - - strncpy(event.isup_in_rdnis,rdnis, - sizeof(event.isup_in_rdnis)-1); - event.isup_in_rdnis_size=strlen(rdnis)+1; + strncpy(event.rdnis.digits,rdnis, sizeof(event.rdnis.digits)-1); + event.rdnis.digits_count=strlen(rdnis)+1; log_printf(SMG_LOG_DEBUG_MISC,server.log,"RDNIS %s\n", rdnis); } + } + if (custom_data && strlen(custom_data)) { + if (strlen(custom_data) > sizeof(event.custom_data)){ + log_printf(SMG_LOG_ALL,server.log,"Error: CUSTOM Overflow (in size=%i max=%i)\n", + strlen(custom_data), sizeof(event.custom_data)); + } else { + strncpy(event.custom_data, custom_data, sizeof(event.custom_data)-1); + event.custom_data_size=strlen(custom_data)+1; + log_printf(SMG_LOG_DEBUG_MISC, server.log, "CUSTOM %s\n", custom_data); + } } if (bearer_cap && strlen(bearer_cap)) { @@ -4379,7 +4414,6 @@ static void handle_call_start(call_signal_event_t *event) remove_end_of_digits_char((unsigned char*)event->called.digits); remove_end_of_digits_char((unsigned char*)event->calling.digits); remove_end_of_digits_char((unsigned char*)event->rdnis.digits); - remove_end_of_digits_char((unsigned char*)event->custom_data); if (server.strip_cid_non_digits) { validate_number((unsigned char*)event->called.digits); @@ -4600,6 +4634,9 @@ static void handle_restart(call_signal_connection_t *mcon, short_signal_event_t { if (!woomera_test_flag(&server.master_connection, WFLAG_MONITOR_RUNNING)) { log_printf(SMG_LOG_ALL, server.log,"ERROR! Monitor Thread not running!\n"); + } else if (woomera_test_flag(&server.master_connection, WFLAG_SYSTEM_NEED_RESET_ACK)){ + log_printf(SMG_LOG_ALL, server.log, + "RESTART Ignored: Outgoing RESTART ACK not received\n"); } else { /* Clear Reset */ /* Tell all threads to go down */ @@ -4611,8 +4648,10 @@ static void handle_restart(call_signal_connection_t *mcon, short_signal_event_t for ( i =0 ; i < SMG_MAX_TG ; i++ ){ smg_all_ckt_busy(i); } - woomera_set_flag(&server.master_connection, WFLAG_SYSTEM_RESET); + gettimeofday(&server.restart_timeout,NULL); + woomera_set_flag(&server.master_connection, WFLAG_SYSTEM_NEED_IN_RESET_ACK); + woomera_set_flag(&server.master_connection, WFLAG_SYSTEM_RESET); #if 0 sleep(5); @@ -4935,6 +4974,7 @@ static void *monitor_thread_run(void *obj) SIGBOOST_EVENT_SYSTEM_RESTART, 0); + gettimeofday(&server.restart_timeout,NULL); woomera_set_flag(&server.master_connection, WFLAG_SYSTEM_NEED_RESET_ACK); woomera_set_flag(&server.master_connection, WFLAG_SYSTEM_RESET); @@ -5003,8 +5043,7 @@ mcon_retry_priority: break; } - if (woomera_test_flag(&server.master_connection, WFLAG_SYSTEM_RESET) && - !woomera_test_flag(&server.master_connection, WFLAG_SYSTEM_NEED_RESET_ACK)) { + if (woomera_test_flag(&server.master_connection, WFLAG_SYSTEM_RESET)) { short_signal_event_t event; struct timeval current; int elapsed; @@ -5013,21 +5052,38 @@ mcon_retry_priority: elapsed=smg_calc_elapsed(&server.restart_timeout, ¤t); if (elapsed > 5000) { int err; - log_printf(SMG_LOG_ALL, server.log, "Reset Condition Cleared Elapsed=%i!\n",elapsed); - clear_all_holding_tank(); - memset(&event,0,sizeof(event)); - event.event_id = SIGBOOST_EVENT_SYSTEM_RESTART_ACK; - err=call_signal_connection_write(&server.mcon, (call_signal_event_t*)&event); - if (err < 0) { - log_printf(SMG_LOG_ALL, server.log, - "Critical System Error: Failed to tx on ISUP socket [%s]: %s\n", - strerror(errno)); + + if (woomera_test_flag(&server.master_connection, WFLAG_SYSTEM_NEED_RESET_ACK)) { + log_printf(SMG_LOG_ALL, server.log, "Reset Timeout: Tx RESTART Elapsed=%i!\n",elapsed); + gettimeofday(&server.restart_timeout,NULL); + woomera_clear_flag(&server.master_connection, WFLAG_SYSTEM_NEED_IN_RESET_ACK); + isup_exec_commandp(0, + 0, + -1, + SIGBOOST_EVENT_SYSTEM_RESTART, + 0); + + + } else if (woomera_test_flag(&server.master_connection, WFLAG_SYSTEM_NEED_IN_RESET_ACK)) { + + log_printf(SMG_LOG_ALL, server.log, "Reset Condition Cleared Elapsed=%i!\n",elapsed); + clear_all_holding_tank(); + memset(&event,0,sizeof(event)); + event.event_id = SIGBOOST_EVENT_SYSTEM_RESTART_ACK; + err=call_signal_connection_write(&server.mcon, (call_signal_event_t*)&event); + if (err < 0) { + log_printf(SMG_LOG_ALL, server.log, + "Critical System Error: Failed to tx on ISUP socket [%s]: %s\n", + strerror(errno)); + } + int i=0; + for ( i =0 ; i < SMG_MAX_TG ; i++ ){ + smg_all_ckt_busy(i); + } + woomera_clear_flag(&server.master_connection, WFLAG_SYSTEM_RESET); + } else { + gettimeofday(&server.restart_timeout,NULL); } - int i=0; - for ( i =0 ; i < SMG_MAX_TG ; i++ ){ - smg_all_ckt_busy(i); - } - woomera_clear_flag(&server.master_connection, WFLAG_SYSTEM_RESET); } } diff --git a/ssmg/sangoma_mgd.trunk/.svn/text-base/sangoma_mgd.h.svn-base b/ssmg/sangoma_mgd.trunk/.svn/text-base/sangoma_mgd.h.svn-base index cd4cc4c..1b24d2f 100644 --- a/ssmg/sangoma_mgd.trunk/.svn/text-base/sangoma_mgd.h.svn-base +++ b/ssmg/sangoma_mgd.trunk/.svn/text-base/sangoma_mgd.h.svn-base @@ -110,6 +110,7 @@ typedef enum { WFLAG_SYSTEM_RESET = (1 << 19), /* Initial System Reset Condition no calls allowed */ WFLAG_SYSTEM_NEED_RESET_ACK = (1 << 20), /* We sent a RESTART */ WFLAG_WAIT_FOR_ACK_TIMEOUT = (1 << 21), /* Timeout flag indicating that incoming ACK or NACK timedout */ + WFLAG_SYSTEM_NEED_IN_RESET_ACK = (1 << 22), /* We got a RESTART */ } WFLAGS; enum { diff --git a/ssmg/sangoma_mgd.trunk/.svn/text-base/smg_ctrl.svn-base b/ssmg/sangoma_mgd.trunk/.svn/text-base/smg_ctrl.svn-base index 96dab39..7f0fb4a 100644 --- a/ssmg/sangoma_mgd.trunk/.svn/text-base/smg_ctrl.svn-base +++ b/ssmg/sangoma_mgd.trunk/.svn/text-base/smg_ctrl.svn-base @@ -27,7 +27,7 @@ function usage() echo " stop :stop $sigd and sangoma media gateway" echo " restart :restart $sigd and sangoma media gateway" echo - echo " BRI Specific" + echo " BRI/PRI Specific" echo " test :test configuration only " echo " capture :enable protocol capture " echo " show_spans :show configured spans " @@ -458,9 +458,9 @@ function toggle_capture() eval "kill -SIGRTMIN+2 $(pidof $sigd)" rc=$? if [ $rc -eq 0 ]; then - logit "BRI: Protocol capture toggled" + logit "BRI/PRI: Protocol capture toggled" else - logit "BRI: Failed to send command" + logit "BRI/PRI: Failed to send command" fi return $rc @@ -475,9 +475,9 @@ function increase_verbose() eval "kill -SIGRTMIN $(pidof $sigd)" rc=$? if [ $rc -eq 0 ]; then - logit "BRI: Verbosity increased" + logit "BRI/PRI: Verbosity increased" else - logit "BRI: Failed to send command" + logit "BRI/PRI: Failed to send command" fi return $rc @@ -490,9 +490,9 @@ function decrease_verbose() eval "kill -SIGRTMIN+1 $(pidof $sigd)" rc=$? if [ $rc -eq 0 ]; then - logit "BRI: Verbosity decreased" + logit "BRI/PRI: Verbosity decreased" else - logit "BRI: Failed to send command" + logit "BRI/PRI: Failed to send command" fi return $rc @@ -505,9 +505,9 @@ function show_calls() eval "kill -SIGRTMIN+3 $(pidof $sigd) " rc=$? if [ $rc -eq 0 ]; then - logit "BRI: Show calls" + logit "BRI/PRI: Show calls" else - logit "BRI: Failed to send command" + logit "BRI/PRI: Failed to send command" fi return $rc diff --git a/ssmg/sangoma_mgd.trunk/Changelog.sangoma_mgd b/ssmg/sangoma_mgd.trunk/Changelog.sangoma_mgd index 6c13ace..7e48298 100644 --- a/ssmg/sangoma_mgd.trunk/Changelog.sangoma_mgd +++ b/ssmg/sangoma_mgd.trunk/Changelog.sangoma_mgd @@ -1,6 +1,11 @@ sangoma_mgd.c ====================================== +Jun 21 2010 + * v1.71 Nenad Corbic + * Added a hwec_chan_status check instead of hwec check. + * This allows some ports to have hwec disabled and others enabled. + Mar 27 2009 * v1.46 Nenad Corbic * Major updates on socket handling. A bug was introducted diff --git a/ssmg/sangoma_mgd.trunk/app/.svn/entries b/ssmg/sangoma_mgd.trunk/app/.svn/entries index d754f0d..f03ceee 100644 --- a/ssmg/sangoma_mgd.trunk/app/.svn/entries +++ b/ssmg/sangoma_mgd.trunk/app/.svn/entries @@ -1,7 +1,7 @@ 8 dir -276 +282 https://www.sangomapbx.com/svn/sangoma_mgd/trunk/app https://www.sangomapbx.com/svn/sangoma_mgd diff --git a/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.ast14_check b/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.ast14_check index 0cfbf08..573541a 100644 --- a/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.ast14_check +++ b/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.ast14_check @@ -1 +1 @@ -2 +0 diff --git a/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.ast16_check b/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.ast16_check index 573541a..0cfbf08 100644 --- a/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.ast16_check +++ b/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.ast16_check @@ -1 +1 @@ -0 +2 diff --git a/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.log b/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.log index 5e1335c..10b6e13 100644 --- a/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.log +++ b/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.log @@ -488,3 +488,73 @@ echo 0 .ast14_check grep -c 1.6 /usr/include/asterisk/version.h .ast16_check 1.4 /usr/include/asterisk/version.h .ast14_check grep -c 1.4 /usr/include/asterisk/version.h .ast14_check +AST_CONTROL_SRC /usr/include/asterisk/frame.h .ast_src_check +grep -c AST_CONTROL_SRC /usr/include/asterisk/frame.h .ast_src_check +opbx_cli_entry /usr/include/asterisk/cli.h .opbx_cli_entry_check +grep -c opbx_cli_entry /usr/include/asterisk/cli.h .opbx_cli_entry_check +cw_cli_entry /usr/include/asterisk/cli.h .cw_cli_entry_check +grep -c cw_cli_entry /usr/include/asterisk/cli.h .cw_cli_entry_check +1.6 /usr/include/asterisk/.version .ast16_check +echo 0 .ast16_check +1.4 /usr/include/asterisk/.version .ast14_check +echo 0 .ast14_check +1.6 /usr/include/asterisk/version.h .ast16_check +grep -c 1.6 /usr/include/asterisk/version.h .ast16_check +1.4 /usr/include/asterisk/version.h .ast14_check +grep -c 1.4 /usr/include/asterisk/version.h .ast14_check +AST_CONTROL_SRC /usr/include/asterisk/frame.h .ast_src_check +grep -c AST_CONTROL_SRC /usr/include/asterisk/frame.h .ast_src_check +opbx_cli_entry /usr/include/asterisk/cli.h .opbx_cli_entry_check +grep -c opbx_cli_entry /usr/include/asterisk/cli.h .opbx_cli_entry_check +cw_cli_entry /usr/include/asterisk/cli.h .cw_cli_entry_check +grep -c cw_cli_entry /usr/include/asterisk/cli.h .cw_cli_entry_check +1.6 /usr/include/asterisk/.version .ast16_check +echo 0 .ast16_check +1.4 /usr/include/asterisk/.version .ast14_check +echo 0 .ast14_check +1.6 /usr/include/asterisk/version.h .ast16_check +grep -c 1.6 /usr/include/asterisk/version.h .ast16_check +1.4 /usr/include/asterisk/version.h .ast14_check +grep -c 1.4 /usr/include/asterisk/version.h .ast14_check +AST_CONTROL_SRC /usr/include/asterisk/frame.h .ast_src_check +grep -c AST_CONTROL_SRC /usr/include/asterisk/frame.h .ast_src_check +opbx_cli_entry /usr/include/asterisk/cli.h .opbx_cli_entry_check +grep -c opbx_cli_entry /usr/include/asterisk/cli.h .opbx_cli_entry_check +cw_cli_entry /usr/include/asterisk/cli.h .cw_cli_entry_check +grep -c cw_cli_entry /usr/include/asterisk/cli.h .cw_cli_entry_check +1.6 /usr/include/asterisk/.version .ast16_check +echo 0 .ast16_check +1.4 /usr/include/asterisk/.version .ast14_check +echo 0 .ast14_check +1.6 /usr/include/asterisk/version.h .ast16_check +grep -c 1.6 /usr/include/asterisk/version.h .ast16_check +1.4 /usr/include/asterisk/version.h .ast14_check +grep -c 1.4 /usr/include/asterisk/version.h .ast14_check +AST_CONTROL_SRC /usr/include/asterisk/frame.h .ast_src_check +grep -c AST_CONTROL_SRC /usr/include/asterisk/frame.h .ast_src_check +opbx_cli_entry /usr/include/asterisk/cli.h .opbx_cli_entry_check +grep -c opbx_cli_entry /usr/include/asterisk/cli.h .opbx_cli_entry_check +cw_cli_entry /usr/include/asterisk/cli.h .cw_cli_entry_check +grep -c cw_cli_entry /usr/include/asterisk/cli.h .cw_cli_entry_check +1.6 /usr/include/asterisk/.version .ast16_check +echo 0 .ast16_check +1.4 /usr/include/asterisk/.version .ast14_check +echo 0 .ast14_check +1.6 /usr/include/asterisk/version.h .ast16_check +grep -c 1.6 /usr/include/asterisk/version.h .ast16_check +1.4 /usr/include/asterisk/version.h .ast14_check +grep -c 1.4 /usr/include/asterisk/version.h .ast14_check +AST_CONTROL_SRC /usr/include/asterisk/frame.h .ast_src_check +grep -c AST_CONTROL_SRC /usr/include/asterisk/frame.h .ast_src_check +opbx_cli_entry /usr/include/asterisk/cli.h .opbx_cli_entry_check +grep -c opbx_cli_entry /usr/include/asterisk/cli.h .opbx_cli_entry_check +cw_cli_entry /usr/include/asterisk/cli.h .cw_cli_entry_check +grep -c cw_cli_entry /usr/include/asterisk/cli.h .cw_cli_entry_check +1.6 /usr/include/asterisk/.version .ast16_check +echo 0 .ast16_check +1.4 /usr/include/asterisk/.version .ast14_check +echo 0 .ast14_check +1.6 /usr/include/asterisk/version.h .ast16_check +grep -c 1.6 /usr/include/asterisk/version.h .ast16_check +1.4 /usr/include/asterisk/version.h .ast14_check +grep -c 1.4 /usr/include/asterisk/version.h .ast14_check diff --git a/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.svn/all-wcprops b/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.svn/all-wcprops index f538316..0c2ddda 100644 --- a/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.svn/all-wcprops +++ b/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.svn/all-wcprops @@ -1,13 +1,13 @@ K 25 svn:wc:ra_dav:version-url V 36 -/svn/chan_woomera/!svn/ver/145/trunk +/svn/chan_woomera/!svn/ver/147/trunk END chan_woomera.c K 25 svn:wc:ra_dav:version-url V 51 -/svn/chan_woomera/!svn/ver/145/trunk/chan_woomera.c +/svn/chan_woomera/!svn/ver/147/trunk/chan_woomera.c END g711.h K 25 diff --git a/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.svn/entries b/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.svn/entries index 8dbe69c..92a1673 100644 --- a/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.svn/entries +++ b/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.svn/entries @@ -1,14 +1,14 @@ 8 dir -145 +147 https://www.sangomapbx.com/svn/chan_woomera/trunk https://www.sangomapbx.com/svn/chan_woomera -2010-03-19T17:36:36.398260Z -145 +2010-05-11T23:08:17.030652Z +147 davidy @@ -32,10 +32,10 @@ file -2010-03-23T16:12:54.000000Z -f8cd84d8d36b819badd469b59d1678c4 -2010-03-19T17:36:36.398260Z -145 +2010-05-11T20:54:30.000000Z +6a356a8ce1b62a235e791a00002ca6d0 +2010-05-11T23:08:17.030652Z +147 davidy g711.h diff --git a/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.svn/text-base/chan_woomera.c.svn-base b/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.svn/text-base/chan_woomera.c.svn-base index 6152c25..6efb810 100644 --- a/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.svn/text-base/chan_woomera.c.svn-base +++ b/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/.svn/text-base/chan_woomera.c.svn-base @@ -15,6 +15,14 @@ * the GNU General Public License * ============================================= * + * v1.70 David Yat Sin + * May 11 2010 + * Added check for invalid hangup causes + * + * v1.69 David Yat Sin + * May 03 2010 + * Added support for WOOMERA_CUSTOM variable on outgoing calls + * * v1.68 David Yat Sin * Mar 19 2010 * MEDIA and RING flags set on answer, based on tech_indicate @@ -364,7 +372,7 @@ #include "asterisk/musiconhold.h" #include "asterisk/transcap.h" -ASTERISK_FILE_VERSION(__FILE__, "$Revision: 1.68 $") +ASTERISK_FILE_VERSION(__FILE__, "$Revision: 1.70 $") #else @@ -415,7 +423,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision: 1.68 $") #define CALLWEAVER_19 1 #endif -CALLWEAVER_FILE_VERSION(__FILE__, "$Revision: 1.68 $") +CALLWEAVER_FILE_VERSION(__FILE__, "$Revision: 1.70 $") #if defined(DSP_FEATURE_FAX_CNG_DETECT) #undef DSP_FEATURE_FAX_DETECT @@ -722,7 +730,7 @@ CALLWEAVER_FILE_VERSION(__FILE__, "$Revision: 1.68 $") extern int option_verbose; -#define WOOMERA_VERSION "v1.68" +#define WOOMERA_VERSION "v1.69" #ifndef WOOMERA_CHAN_NAME #define WOOMERA_CHAN_NAME "SS7" #endif @@ -1046,6 +1054,18 @@ typedef struct woomera_event_queue woomera_event_queue; } while (0) #endif +static inline int validate_number(char *s) +{ + char *p; + for (p = s; *p; p++) { + if (*p < 48 || *p > 57) { + return -1; + } + } + return 0; +} + + static inline int woomera_profile_verbose(woomera_profile *profile) { @@ -1909,6 +1929,7 @@ static int tech_activate(private_object *tech_pvt) int retry_activate_call=0; woomera_message wmsg; char *callid; + char *rdnis = NULL; int err=0; tech_pvt->owner->hangupcause = 34; @@ -1949,8 +1970,17 @@ retry_activate_again: goto tech_activate_failed; } + if (tech_pvt->cid_rdnis) { + if (validate_number(tech_pvt->cid_rdnis) < 0) { + /* cid_rdnis should only contain digits */ + ast_log(LOG_ERROR, "Error, invalid RDNIS value %s - ignoring\n", tech_pvt->cid_rdnis); + } else { + rdnis = tech_pvt->cid_rdnis; + } + } retry_activate_call=0; + const char *custom = pbx_builtin_getvar_helper(tech_pvt->owner, "WOOMERA_CUSTOM"); if (ast_test_flag(tech_pvt, TFLAG_OUTBOUND)) { @@ -1966,12 +1996,13 @@ retry_activate_again: "Bearer-Cap:%s%s" "uil1p:%s%s" "RDNIS:%s%s" - "xCalledTon:%d:%s" - "xCalledNpi:%d:%s" - "xCallingTon:%d:%s" - "xCallingNpi:%d:%s" - "xRdnisTon:%d:%s" - "xRdnisNpi:%d:%s", + "xCalledTon:%d%s" + "xCalledNpi:%d%s" + "xCallingTon:%d%s" + "xCallingNpi:%d%s" + "xRdnisTon:%d%s" + "xRdnisNpi:%d%s" + "xCustom:%s%s", tech_pvt->proto, tech_pvt->dest, WOOMERA_LINE_SEPARATOR, @@ -1991,7 +2022,7 @@ retry_activate_again: WOOMERA_LINE_SEPARATOR, woomera_ast_coding_to_string(tech_pvt->coding), WOOMERA_LINE_SEPARATOR, - tech_pvt->cid_rdnis?tech_pvt->cid_rdnis:"", + rdnis?rdnis:"", WOOMERA_LINE_SEPARATOR, get_digits_val_from_pbx_var(tech_pvt->owner, "OUTBOUND_CALLED_TON", 255), WOOMERA_LINE_SEPARATOR, @@ -2004,6 +2035,8 @@ retry_activate_again: get_digits_val_from_pbx_var(tech_pvt->owner, "OUTBOUND_RDNIS_TON", 255), WOOMERA_LINE_SEPARATOR, get_digits_val_from_pbx_var(tech_pvt->owner, "OUTBOUND_RDNIS_NPI", 255), + WOOMERA_LINE_SEPARATOR, + custom?custom:"", WOOMERA_RECORD_SEPARATOR ); @@ -2019,12 +2052,13 @@ retry_activate_again: "Bearer-Cap:%s%s" "uil1p:%s%s" "RDNIS:%s%s" - "xCalledTon:%d:%s" - "xCalledNpi:%d:%s" - "xCallingTon:%d:%s" - "xCallingNpi:%d:%s" - "xRdnisTon:%d:%s" - "xRdnisNpi:%d:%s", + "xCalledTon:%d%s" + "xCalledNpi:%d%s" + "xCallingTon:%d%s" + "xCallingNpi:%d%s" + "xRdnisTon:%d%s" + "xRdnisNpi:%d%s" + "xCustom:%s%s", tech_pvt->dest, WOOMERA_LINE_SEPARATOR, tech_pvt->profile->audio_ip, @@ -2043,7 +2077,7 @@ retry_activate_again: WOOMERA_LINE_SEPARATOR, woomera_ast_coding_to_string(tech_pvt->coding), WOOMERA_LINE_SEPARATOR, - tech_pvt->cid_rdnis?tech_pvt->cid_rdnis:"", + rdnis?rdnis:"", WOOMERA_LINE_SEPARATOR, get_digits_val_from_pbx_var(tech_pvt->owner, "OUTBOUND_CALLED_TON", 255), WOOMERA_LINE_SEPARATOR, @@ -2056,6 +2090,8 @@ retry_activate_again: get_digits_val_from_pbx_var(tech_pvt->owner, "OUTBOUND_RDNIS_TON", 255), WOOMERA_LINE_SEPARATOR, get_digits_val_from_pbx_var(tech_pvt->owner, "OUTBOUND_RDNIS_NPI", 255), + WOOMERA_LINE_SEPARATOR, + custom?custom:"", WOOMERA_RECORD_SEPARATOR ); } @@ -2275,7 +2311,7 @@ static int tech_init(private_object *tech_pvt, woomera_profile *profile, int fla * tech_create_read_socket(tech_pvt); to setup a read socket * which, by the way, asterisk insists we have before going any furthur. * So, in short, we are between a rock and a hard place and asterisk wants us to open a socket here - * but it too impaitent to wait for us to make sure it's ready so in the case of outgoing calls + * but it too impatient to wait for us to make sure it's ready so in the case of outgoing calls * we will defer the rest of the socket establishment process to the monitor thread. This is, of course, common * knowledge since asterisk abounds in documentation right?, sorry to bother you with all this! */ @@ -4345,14 +4381,19 @@ static int tech_hangup(struct ast_channel *self) ast_copy_string(tech_pvt->ds, ds, sizeof(tech_pvt->ds)); ds=pbx_builtin_getvar_helper(self, "PRI_CAUSE"); - if (ds && atoi(ds)) { + if (ds && atoi(ds)) { tech_pvt->pri_cause=atoi(ds); } else if (self->hangupcause) { - tech_pvt->pri_cause=self->hangupcause; + tech_pvt->pri_cause=self->hangupcause; } else { tech_pvt->pri_cause=AST_CAUSE_NORMAL_CLEARING; } - + + if (tech_pvt->pri_cause > 127) { + ast_log(LOG_NOTICE, "Invalid HangUp Cause %i\n", tech_pvt->pri_cause); + tech_pvt->pri_cause = AST_CAUSE_NORMAL_UNSPECIFIED; + } + if (globals.debug > 2) { ast_log(LOG_NOTICE, "TECH HANGUP [%s] Cause=%i HangCause=%i ds=%s\n", self->name,tech_pvt->pri_cause, self->hangupcause, ds?ds:"N/A"); diff --git a/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/chan_woomera.c b/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/chan_woomera.c index 6152c25..6efb810 100644 --- a/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/chan_woomera.c +++ b/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/chan_woomera.c @@ -15,6 +15,14 @@ * the GNU General Public License * ============================================= * + * v1.70 David Yat Sin + * May 11 2010 + * Added check for invalid hangup causes + * + * v1.69 David Yat Sin + * May 03 2010 + * Added support for WOOMERA_CUSTOM variable on outgoing calls + * * v1.68 David Yat Sin * Mar 19 2010 * MEDIA and RING flags set on answer, based on tech_indicate @@ -364,7 +372,7 @@ #include "asterisk/musiconhold.h" #include "asterisk/transcap.h" -ASTERISK_FILE_VERSION(__FILE__, "$Revision: 1.68 $") +ASTERISK_FILE_VERSION(__FILE__, "$Revision: 1.70 $") #else @@ -415,7 +423,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision: 1.68 $") #define CALLWEAVER_19 1 #endif -CALLWEAVER_FILE_VERSION(__FILE__, "$Revision: 1.68 $") +CALLWEAVER_FILE_VERSION(__FILE__, "$Revision: 1.70 $") #if defined(DSP_FEATURE_FAX_CNG_DETECT) #undef DSP_FEATURE_FAX_DETECT @@ -722,7 +730,7 @@ CALLWEAVER_FILE_VERSION(__FILE__, "$Revision: 1.68 $") extern int option_verbose; -#define WOOMERA_VERSION "v1.68" +#define WOOMERA_VERSION "v1.69" #ifndef WOOMERA_CHAN_NAME #define WOOMERA_CHAN_NAME "SS7" #endif @@ -1046,6 +1054,18 @@ typedef struct woomera_event_queue woomera_event_queue; } while (0) #endif +static inline int validate_number(char *s) +{ + char *p; + for (p = s; *p; p++) { + if (*p < 48 || *p > 57) { + return -1; + } + } + return 0; +} + + static inline int woomera_profile_verbose(woomera_profile *profile) { @@ -1909,6 +1929,7 @@ static int tech_activate(private_object *tech_pvt) int retry_activate_call=0; woomera_message wmsg; char *callid; + char *rdnis = NULL; int err=0; tech_pvt->owner->hangupcause = 34; @@ -1949,8 +1970,17 @@ retry_activate_again: goto tech_activate_failed; } + if (tech_pvt->cid_rdnis) { + if (validate_number(tech_pvt->cid_rdnis) < 0) { + /* cid_rdnis should only contain digits */ + ast_log(LOG_ERROR, "Error, invalid RDNIS value %s - ignoring\n", tech_pvt->cid_rdnis); + } else { + rdnis = tech_pvt->cid_rdnis; + } + } retry_activate_call=0; + const char *custom = pbx_builtin_getvar_helper(tech_pvt->owner, "WOOMERA_CUSTOM"); if (ast_test_flag(tech_pvt, TFLAG_OUTBOUND)) { @@ -1966,12 +1996,13 @@ retry_activate_again: "Bearer-Cap:%s%s" "uil1p:%s%s" "RDNIS:%s%s" - "xCalledTon:%d:%s" - "xCalledNpi:%d:%s" - "xCallingTon:%d:%s" - "xCallingNpi:%d:%s" - "xRdnisTon:%d:%s" - "xRdnisNpi:%d:%s", + "xCalledTon:%d%s" + "xCalledNpi:%d%s" + "xCallingTon:%d%s" + "xCallingNpi:%d%s" + "xRdnisTon:%d%s" + "xRdnisNpi:%d%s" + "xCustom:%s%s", tech_pvt->proto, tech_pvt->dest, WOOMERA_LINE_SEPARATOR, @@ -1991,7 +2022,7 @@ retry_activate_again: WOOMERA_LINE_SEPARATOR, woomera_ast_coding_to_string(tech_pvt->coding), WOOMERA_LINE_SEPARATOR, - tech_pvt->cid_rdnis?tech_pvt->cid_rdnis:"", + rdnis?rdnis:"", WOOMERA_LINE_SEPARATOR, get_digits_val_from_pbx_var(tech_pvt->owner, "OUTBOUND_CALLED_TON", 255), WOOMERA_LINE_SEPARATOR, @@ -2004,6 +2035,8 @@ retry_activate_again: get_digits_val_from_pbx_var(tech_pvt->owner, "OUTBOUND_RDNIS_TON", 255), WOOMERA_LINE_SEPARATOR, get_digits_val_from_pbx_var(tech_pvt->owner, "OUTBOUND_RDNIS_NPI", 255), + WOOMERA_LINE_SEPARATOR, + custom?custom:"", WOOMERA_RECORD_SEPARATOR ); @@ -2019,12 +2052,13 @@ retry_activate_again: "Bearer-Cap:%s%s" "uil1p:%s%s" "RDNIS:%s%s" - "xCalledTon:%d:%s" - "xCalledNpi:%d:%s" - "xCallingTon:%d:%s" - "xCallingNpi:%d:%s" - "xRdnisTon:%d:%s" - "xRdnisNpi:%d:%s", + "xCalledTon:%d%s" + "xCalledNpi:%d%s" + "xCallingTon:%d%s" + "xCallingNpi:%d%s" + "xRdnisTon:%d%s" + "xRdnisNpi:%d%s" + "xCustom:%s%s", tech_pvt->dest, WOOMERA_LINE_SEPARATOR, tech_pvt->profile->audio_ip, @@ -2043,7 +2077,7 @@ retry_activate_again: WOOMERA_LINE_SEPARATOR, woomera_ast_coding_to_string(tech_pvt->coding), WOOMERA_LINE_SEPARATOR, - tech_pvt->cid_rdnis?tech_pvt->cid_rdnis:"", + rdnis?rdnis:"", WOOMERA_LINE_SEPARATOR, get_digits_val_from_pbx_var(tech_pvt->owner, "OUTBOUND_CALLED_TON", 255), WOOMERA_LINE_SEPARATOR, @@ -2056,6 +2090,8 @@ retry_activate_again: get_digits_val_from_pbx_var(tech_pvt->owner, "OUTBOUND_RDNIS_TON", 255), WOOMERA_LINE_SEPARATOR, get_digits_val_from_pbx_var(tech_pvt->owner, "OUTBOUND_RDNIS_NPI", 255), + WOOMERA_LINE_SEPARATOR, + custom?custom:"", WOOMERA_RECORD_SEPARATOR ); } @@ -2275,7 +2311,7 @@ static int tech_init(private_object *tech_pvt, woomera_profile *profile, int fla * tech_create_read_socket(tech_pvt); to setup a read socket * which, by the way, asterisk insists we have before going any furthur. * So, in short, we are between a rock and a hard place and asterisk wants us to open a socket here - * but it too impaitent to wait for us to make sure it's ready so in the case of outgoing calls + * but it too impatient to wait for us to make sure it's ready so in the case of outgoing calls * we will defer the rest of the socket establishment process to the monitor thread. This is, of course, common * knowledge since asterisk abounds in documentation right?, sorry to bother you with all this! */ @@ -4345,14 +4381,19 @@ static int tech_hangup(struct ast_channel *self) ast_copy_string(tech_pvt->ds, ds, sizeof(tech_pvt->ds)); ds=pbx_builtin_getvar_helper(self, "PRI_CAUSE"); - if (ds && atoi(ds)) { + if (ds && atoi(ds)) { tech_pvt->pri_cause=atoi(ds); } else if (self->hangupcause) { - tech_pvt->pri_cause=self->hangupcause; + tech_pvt->pri_cause=self->hangupcause; } else { tech_pvt->pri_cause=AST_CAUSE_NORMAL_CLEARING; } - + + if (tech_pvt->pri_cause > 127) { + ast_log(LOG_NOTICE, "Invalid HangUp Cause %i\n", tech_pvt->pri_cause); + tech_pvt->pri_cause = AST_CAUSE_NORMAL_UNSPECIFIED; + } + if (globals.debug > 2) { ast_log(LOG_NOTICE, "TECH HANGUP [%s] Cause=%i HangCause=%i ds=%s\n", self->name,tech_pvt->pri_cause, self->hangupcause, ds?ds:"N/A"); diff --git a/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/chan_woomera.so b/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/chan_woomera.so index 67aaf4a..b09df48 100755 Binary files a/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/chan_woomera.so and b/ssmg/sangoma_mgd.trunk/chan_woomera.trunk/chan_woomera.so differ diff --git a/ssmg/sangoma_mgd.trunk/conf/.svn/entries b/ssmg/sangoma_mgd.trunk/conf/.svn/entries index 8491901..5685e2a 100644 --- a/ssmg/sangoma_mgd.trunk/conf/.svn/entries +++ b/ssmg/sangoma_mgd.trunk/conf/.svn/entries @@ -1,7 +1,7 @@ 8 dir -276 +282 https://www.sangomapbx.com/svn/sangoma_mgd/trunk/conf https://www.sangomapbx.com/svn/sangoma_mgd diff --git a/ssmg/sangoma_mgd.trunk/conf_bri/.svn/entries b/ssmg/sangoma_mgd.trunk/conf_bri/.svn/entries index ab20df0..43ddfe5 100644 --- a/ssmg/sangoma_mgd.trunk/conf_bri/.svn/entries +++ b/ssmg/sangoma_mgd.trunk/conf_bri/.svn/entries @@ -1,7 +1,7 @@ 8 dir -276 +282 https://www.sangomapbx.com/svn/sangoma_mgd/trunk/conf_bri https://www.sangomapbx.com/svn/sangoma_mgd diff --git a/ssmg/sangoma_mgd.trunk/lib/.svn/entries b/ssmg/sangoma_mgd.trunk/lib/.svn/entries index 6c0d964..5950398 100644 --- a/ssmg/sangoma_mgd.trunk/lib/.svn/entries +++ b/ssmg/sangoma_mgd.trunk/lib/.svn/entries @@ -1,7 +1,7 @@ 8 dir -276 +282 https://www.sangomapbx.com/svn/sangoma_mgd/trunk/lib https://www.sangomapbx.com/svn/sangoma_mgd diff --git a/ssmg/sangoma_mgd.trunk/lib/libteletone/.svn/entries b/ssmg/sangoma_mgd.trunk/lib/libteletone/.svn/entries index cb082d0..5b88a07 100644 --- a/ssmg/sangoma_mgd.trunk/lib/libteletone/.svn/entries +++ b/ssmg/sangoma_mgd.trunk/lib/libteletone/.svn/entries @@ -1,7 +1,7 @@ 8 dir -276 +282 https://www.sangomapbx.com/svn/sangoma_mgd/trunk/lib/libteletone https://www.sangomapbx.com/svn/sangoma_mgd @@ -88,17 +88,8 @@ file root has-props -depcomp -file - - - - -2009-08-25T20:44:42.000000Z -7e26ecc61d5c27c50d334ebe19d5ef06 -2007-09-21T20:53:51.260136Z -1 -root +src +dir ChangeLog file @@ -112,8 +103,17 @@ d41d8cd98f00b204e9800998ecf8427e 1 root -src -dir +depcomp +file + + + + +2009-08-25T20:44:42.000000Z +7e26ecc61d5c27c50d334ebe19d5ef06 +2007-09-21T20:53:51.260136Z +1 +root compile file @@ -152,14 +152,14 @@ c2defdef8cd93c3d9e29628267699702 1 root -README +config.sub file 2009-08-25T20:44:42.000000Z -234c8df99750448a5b1c4709304a38e5 +74587542264e2bb761ee931ddb7d69f1 2007-09-21T20:53:51.260136Z 1 root @@ -176,14 +176,14 @@ file 1 root -config.sub +README file 2009-08-25T20:44:42.000000Z -74587542264e2bb761ee931ddb7d69f1 +234c8df99750448a5b1c4709304a38e5 2007-09-21T20:53:51.260136Z 1 root diff --git a/ssmg/sangoma_mgd.trunk/lib/libteletone/src/.svn/entries b/ssmg/sangoma_mgd.trunk/lib/libteletone/src/.svn/entries index 7dcc7ab..5806c02 100644 --- a/ssmg/sangoma_mgd.trunk/lib/libteletone/src/.svn/entries +++ b/ssmg/sangoma_mgd.trunk/lib/libteletone/src/.svn/entries @@ -1,7 +1,7 @@ 8 dir -276 +282 https://www.sangomapbx.com/svn/sangoma_mgd/trunk/lib/libteletone/src https://www.sangomapbx.com/svn/sangoma_mgd diff --git a/ssmg/sangoma_mgd.trunk/rc/.svn/entries b/ssmg/sangoma_mgd.trunk/rc/.svn/entries index d7e906c..95da7de 100644 --- a/ssmg/sangoma_mgd.trunk/rc/.svn/entries +++ b/ssmg/sangoma_mgd.trunk/rc/.svn/entries @@ -1,7 +1,7 @@ 8 dir -276 +282 https://www.sangomapbx.com/svn/sangoma_mgd/trunk/rc https://www.sangomapbx.com/svn/sangoma_mgd diff --git a/ssmg/sangoma_mgd.trunk/sangoma_mgd.c b/ssmg/sangoma_mgd.trunk/sangoma_mgd.c index 852ec4a..4643480 100644 --- a/ssmg/sangoma_mgd.trunk/sangoma_mgd.c +++ b/ssmg/sangoma_mgd.trunk/sangoma_mgd.c @@ -1,7 +1,7 @@ /********************************************************************************* * sangoma_mgd.c -- Sangoma Media Gateway Daemon for Sangoma/Wanpipe Cards * - * Copyright 05-09, Nenad Corbic + * Copyright 05-10, Nenad Corbic * Anthony Minessale II * * This program is free software, distributed under the terms of @@ -9,27 +9,41 @@ * * ============================================= * - * v1.68 David Yat Sin - * Mar 18 2010 - * Media and RING bits implemented + * v1.71 Nenad Corbic + * Jun 21 2010 + * Added a hwec_chan_status check instead of hwec check. + * This allows some ports to have hwec disabled and others enabled. + * + * v1.70 Nenad Corbic + * May 07 2010 + * remove_end_of_digits_char was being run on custom_data. + * thus cutting off the custom isup parameters. + * + * v1.69 David Yat Sin + * May 03 2010 + * Added support for WOOMERA_CUSTOM variable on outgoing calls * - * v1.67 David Yat Sin - * Mar 16 2010 - * Added sanity check for span chan on call stopped and call answered - - * v1.66 David Yat Sin - * Mar 15 2010 - * Fix for WFLAG_SYSTEM_RESET being cleared if when - * no boost msg was received from signalling daemon + * v1.68 David Yat Sin + * Mar 18 2010 + * Media and RING bits implemented + * + * v1.67 David Yat Sin + * Mar 16 2010 + * Added sanity check for span chan on call stopped and call answered + * + * v1.66 David Yat Sin + * Mar 15 2010 + * Fix for WFLAG_SYSTEM_RESET being cleared if when + * no boost msg was received from signalling daemon * * v1.65 David Yat Sin * Mar 10 2010 - * Support for TON and NPI passthrough + * Support for TON and NPI passthrough * * v1.64 David Yat Sin * Feb 22 2010 - * Updated to sigboost 103 - * Added checks for hwec present + * Updated to sigboost 103 + * Added checks for hwec present * * v1.63 Nenad Corbic * Jan 27 2010 @@ -38,19 +52,19 @@ * * v1.62 Konrad Hammel * Jan 26 2010 - * Added rbs relay code + * Added rbs relay code * * v1.61 Konrad Hammel * Jan 19 2010 - * changed all_ckt_busy to be per trunk group. + * changed all_ckt_busy to be per trunk group. * * v1.60 Nenad Corbic * Jan 14 2010 - * Added media sequencing option. - * Check if server has it enabled. + * Added media sequencing option. + * Check if server has it enabled. * * v1.59 Nenad Corbic - * Changed w1g1 to s1c1 + * Changed w1g1 to s1c1 * * v1.58 Nenad Corbic * Added bridge tdm to ip functionality @@ -370,7 +384,7 @@ pthread_mutex_t g_smg_ip_bridge_lock; #endif -#define SMG_VERSION "v1.68" +#define SMG_VERSION "v1.71" /* enable early media */ #if 1 @@ -422,7 +436,7 @@ static int drop_seq=0; const char WELCOME_TEXT[] = "================================================================================\n" -"Sangoma Media Gateway Daemon v1.68 \n" +"Sangoma Media Gateway Daemon v1.71 \n" "\n" "TDM Signal Media Gateway for Sangoma/Wanpipe Cards\n" "Copyright 2005, 2006, 2007 \n" @@ -1460,9 +1474,15 @@ retry_loop: sangoma_frame_len = sangoma_tdm_get_usr_mtu_mru(ms->sangoma_sock,&tdm_api); #ifdef LIBSANGOMA_VERSION +#ifdef WP_API_FEATURE_EC_CHAN_STAT + ms->has_hwec = sangoma_tdm_get_hwec_chan_status(ms->sangoma_sock, &tdm_api); +#else ms->has_hwec = sangoma_tdm_get_hw_ec(ms->sangoma_sock, &tdm_api); - if (ms->has_hwec) { +#endif + if (ms->has_hwec > 0) { sangoma_tdm_disable_hwec(ms->sangoma_sock,&tdm_api); + } else { + ms->has_hwec=0; } #else ms->has_hwec=1; @@ -1708,7 +1728,14 @@ media_retry: } #ifdef LIBSANGOMA_VERSION +#ifdef WP_API_FEATURE_EC_CHAN_STAT + ms->has_hwec = sangoma_tdm_get_hwec_chan_status(ms->sangoma_sock, &tdm_api); +#else ms->has_hwec = sangoma_tdm_get_hw_ec(ms->sangoma_sock, &tdm_api); +#endif + if (ms->has_hwec < 0) { + ms->has_hwec=0; + } #else ms->has_hwec = 1; #endif @@ -3260,6 +3287,7 @@ static int handle_woomera_call_start (struct woomera_interface *woomera, char *rdnis = woomera_message_header(wmsg, "RDNIS"); char *bearer_cap = woomera_message_header(wmsg, "Bearer-Cap"); char *uil1p = woomera_message_header(wmsg, "uil1p"); + char *custom_data = woomera_message_header(wmsg, "xCustom"); char *called = wmsg->callid; char *grp = wmsg->callid; @@ -3396,19 +3424,26 @@ static int handle_woomera_call_start (struct woomera_interface *woomera, event.isup_in_rdnis[0]=0; if (rdnis && strlen(rdnis) ) { - - if (strlen(rdnis) > sizeof(event.isup_in_rdnis)){ + if (strlen(rdnis) > sizeof(event.rdnis.digits)){ log_printf(SMG_LOG_ALL,server.log,"Error: RDNIS Overflow (in size=%i max=%i)\n", - strlen(rdnis), sizeof(event.isup_in_rdnis)); + strlen(rdnis), sizeof(event.rdnis.digits)); } else { - - strncpy(event.isup_in_rdnis,rdnis, - sizeof(event.isup_in_rdnis)-1); - event.isup_in_rdnis_size=strlen(rdnis)+1; + strncpy(event.rdnis.digits,rdnis, sizeof(event.rdnis.digits)-1); + event.rdnis.digits_count=strlen(rdnis)+1; log_printf(SMG_LOG_DEBUG_MISC,server.log,"RDNIS %s\n", rdnis); } + } + if (custom_data && strlen(custom_data)) { + if (strlen(custom_data) > sizeof(event.custom_data)){ + log_printf(SMG_LOG_ALL,server.log,"Error: CUSTOM Overflow (in size=%i max=%i)\n", + strlen(custom_data), sizeof(event.custom_data)); + } else { + strncpy(event.custom_data, custom_data, sizeof(event.custom_data)-1); + event.custom_data_size=strlen(custom_data)+1; + log_printf(SMG_LOG_DEBUG_MISC, server.log, "CUSTOM %s\n", custom_data); + } } if (bearer_cap && strlen(bearer_cap)) { @@ -4379,7 +4414,6 @@ static void handle_call_start(call_signal_event_t *event) remove_end_of_digits_char((unsigned char*)event->called.digits); remove_end_of_digits_char((unsigned char*)event->calling.digits); remove_end_of_digits_char((unsigned char*)event->rdnis.digits); - remove_end_of_digits_char((unsigned char*)event->custom_data); if (server.strip_cid_non_digits) { validate_number((unsigned char*)event->called.digits); @@ -4600,6 +4634,9 @@ static void handle_restart(call_signal_connection_t *mcon, short_signal_event_t { if (!woomera_test_flag(&server.master_connection, WFLAG_MONITOR_RUNNING)) { log_printf(SMG_LOG_ALL, server.log,"ERROR! Monitor Thread not running!\n"); + } else if (woomera_test_flag(&server.master_connection, WFLAG_SYSTEM_NEED_RESET_ACK)){ + log_printf(SMG_LOG_ALL, server.log, + "RESTART Ignored: Outgoing RESTART ACK not received\n"); } else { /* Clear Reset */ /* Tell all threads to go down */ @@ -4611,8 +4648,10 @@ static void handle_restart(call_signal_connection_t *mcon, short_signal_event_t for ( i =0 ; i < SMG_MAX_TG ; i++ ){ smg_all_ckt_busy(i); } - woomera_set_flag(&server.master_connection, WFLAG_SYSTEM_RESET); + gettimeofday(&server.restart_timeout,NULL); + woomera_set_flag(&server.master_connection, WFLAG_SYSTEM_NEED_IN_RESET_ACK); + woomera_set_flag(&server.master_connection, WFLAG_SYSTEM_RESET); #if 0 sleep(5); @@ -4935,6 +4974,7 @@ static void *monitor_thread_run(void *obj) SIGBOOST_EVENT_SYSTEM_RESTART, 0); + gettimeofday(&server.restart_timeout,NULL); woomera_set_flag(&server.master_connection, WFLAG_SYSTEM_NEED_RESET_ACK); woomera_set_flag(&server.master_connection, WFLAG_SYSTEM_RESET); @@ -5003,8 +5043,7 @@ mcon_retry_priority: break; } - if (woomera_test_flag(&server.master_connection, WFLAG_SYSTEM_RESET) && - !woomera_test_flag(&server.master_connection, WFLAG_SYSTEM_NEED_RESET_ACK)) { + if (woomera_test_flag(&server.master_connection, WFLAG_SYSTEM_RESET)) { short_signal_event_t event; struct timeval current; int elapsed; @@ -5013,21 +5052,38 @@ mcon_retry_priority: elapsed=smg_calc_elapsed(&server.restart_timeout, ¤t); if (elapsed > 5000) { int err; - log_printf(SMG_LOG_ALL, server.log, "Reset Condition Cleared Elapsed=%i!\n",elapsed); - clear_all_holding_tank(); - memset(&event,0,sizeof(event)); - event.event_id = SIGBOOST_EVENT_SYSTEM_RESTART_ACK; - err=call_signal_connection_write(&server.mcon, (call_signal_event_t*)&event); - if (err < 0) { - log_printf(SMG_LOG_ALL, server.log, - "Critical System Error: Failed to tx on ISUP socket [%s]: %s\n", - strerror(errno)); + + if (woomera_test_flag(&server.master_connection, WFLAG_SYSTEM_NEED_RESET_ACK)) { + log_printf(SMG_LOG_ALL, server.log, "Reset Timeout: Tx RESTART Elapsed=%i!\n",elapsed); + gettimeofday(&server.restart_timeout,NULL); + woomera_clear_flag(&server.master_connection, WFLAG_SYSTEM_NEED_IN_RESET_ACK); + isup_exec_commandp(0, + 0, + -1, + SIGBOOST_EVENT_SYSTEM_RESTART, + 0); + + + } else if (woomera_test_flag(&server.master_connection, WFLAG_SYSTEM_NEED_IN_RESET_ACK)) { + + log_printf(SMG_LOG_ALL, server.log, "Reset Condition Cleared Elapsed=%i!\n",elapsed); + clear_all_holding_tank(); + memset(&event,0,sizeof(event)); + event.event_id = SIGBOOST_EVENT_SYSTEM_RESTART_ACK; + err=call_signal_connection_write(&server.mcon, (call_signal_event_t*)&event); + if (err < 0) { + log_printf(SMG_LOG_ALL, server.log, + "Critical System Error: Failed to tx on ISUP socket [%s]: %s\n", + strerror(errno)); + } + int i=0; + for ( i =0 ; i < SMG_MAX_TG ; i++ ){ + smg_all_ckt_busy(i); + } + woomera_clear_flag(&server.master_connection, WFLAG_SYSTEM_RESET); + } else { + gettimeofday(&server.restart_timeout,NULL); } - int i=0; - for ( i =0 ; i < SMG_MAX_TG ; i++ ){ - smg_all_ckt_busy(i); - } - woomera_clear_flag(&server.master_connection, WFLAG_SYSTEM_RESET); } } diff --git a/ssmg/sangoma_mgd.trunk/sangoma_mgd.h b/ssmg/sangoma_mgd.trunk/sangoma_mgd.h index cd4cc4c..1b24d2f 100644 --- a/ssmg/sangoma_mgd.trunk/sangoma_mgd.h +++ b/ssmg/sangoma_mgd.trunk/sangoma_mgd.h @@ -110,6 +110,7 @@ typedef enum { WFLAG_SYSTEM_RESET = (1 << 19), /* Initial System Reset Condition no calls allowed */ WFLAG_SYSTEM_NEED_RESET_ACK = (1 << 20), /* We sent a RESTART */ WFLAG_WAIT_FOR_ACK_TIMEOUT = (1 << 21), /* Timeout flag indicating that incoming ACK or NACK timedout */ + WFLAG_SYSTEM_NEED_IN_RESET_ACK = (1 << 22), /* We got a RESTART */ } WFLAGS; enum { diff --git a/ssmg/sangoma_mgd.trunk/scripts/.svn/entries b/ssmg/sangoma_mgd.trunk/scripts/.svn/entries index de7650c..f43b5d7 100644 --- a/ssmg/sangoma_mgd.trunk/scripts/.svn/entries +++ b/ssmg/sangoma_mgd.trunk/scripts/.svn/entries @@ -1,7 +1,7 @@ 8 dir -276 +282 https://www.sangomapbx.com/svn/sangoma_mgd/trunk/scripts https://www.sangomapbx.com/svn/sangoma_mgd diff --git a/ssmg/sangoma_mgd.trunk/scripts/callgen/.svn/entries b/ssmg/sangoma_mgd.trunk/scripts/callgen/.svn/entries index 52b529a..e03b04c 100644 --- a/ssmg/sangoma_mgd.trunk/scripts/callgen/.svn/entries +++ b/ssmg/sangoma_mgd.trunk/scripts/callgen/.svn/entries @@ -1,7 +1,7 @@ 8 dir -276 +282 https://www.sangomapbx.com/svn/sangoma_mgd/trunk/scripts/callgen https://www.sangomapbx.com/svn/sangoma_mgd diff --git a/ssmg/sangoma_mgd.trunk/scripts/init.d/.svn/entries b/ssmg/sangoma_mgd.trunk/scripts/init.d/.svn/entries index 11c393f..9a8c078 100644 --- a/ssmg/sangoma_mgd.trunk/scripts/init.d/.svn/entries +++ b/ssmg/sangoma_mgd.trunk/scripts/init.d/.svn/entries @@ -1,7 +1,7 @@ 8 dir -276 +282 https://www.sangomapbx.com/svn/sangoma_mgd/trunk/scripts/init.d https://www.sangomapbx.com/svn/sangoma_mgd diff --git a/ssmg/sangoma_mgd.trunk/scripts/ss7/.svn/entries b/ssmg/sangoma_mgd.trunk/scripts/ss7/.svn/entries index a91b67b..9ba7cf9 100644 --- a/ssmg/sangoma_mgd.trunk/scripts/ss7/.svn/entries +++ b/ssmg/sangoma_mgd.trunk/scripts/ss7/.svn/entries @@ -1,7 +1,7 @@ 8 dir -276 +282 https://www.sangomapbx.com/svn/sangoma_mgd/trunk/scripts/ss7 https://www.sangomapbx.com/svn/sangoma_mgd diff --git a/ssmg/sangoma_mgd.trunk/smg_ctrl b/ssmg/sangoma_mgd.trunk/smg_ctrl index 96dab39..6d1ed8d 100755 --- a/ssmg/sangoma_mgd.trunk/smg_ctrl +++ b/ssmg/sangoma_mgd.trunk/smg_ctrl @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -p cmd=$1; sigd=$2; xtraargs=''; @@ -27,7 +27,7 @@ function usage() echo " stop :stop $sigd and sangoma media gateway" echo " restart :restart $sigd and sangoma media gateway" echo - echo " BRI Specific" + echo " BRI/PRI Specific" echo " test :test configuration only " echo " capture :enable protocol capture " echo " show_spans :show configured spans " @@ -458,9 +458,9 @@ function toggle_capture() eval "kill -SIGRTMIN+2 $(pidof $sigd)" rc=$? if [ $rc -eq 0 ]; then - logit "BRI: Protocol capture toggled" + logit "BRI/PRI: Protocol capture toggled" else - logit "BRI: Failed to send command" + logit "BRI/PRI: Failed to send command" fi return $rc @@ -475,9 +475,9 @@ function increase_verbose() eval "kill -SIGRTMIN $(pidof $sigd)" rc=$? if [ $rc -eq 0 ]; then - logit "BRI: Verbosity increased" + logit "BRI/PRI: Verbosity increased" else - logit "BRI: Failed to send command" + logit "BRI/PRI: Failed to send command" fi return $rc @@ -490,9 +490,9 @@ function decrease_verbose() eval "kill -SIGRTMIN+1 $(pidof $sigd)" rc=$? if [ $rc -eq 0 ]; then - logit "BRI: Verbosity decreased" + logit "BRI/PRI: Verbosity decreased" else - logit "BRI: Failed to send command" + logit "BRI/PRI: Failed to send command" fi return $rc @@ -505,9 +505,9 @@ function show_calls() eval "kill -SIGRTMIN+3 $(pidof $sigd) " rc=$? if [ $rc -eq 0 ]; then - logit "BRI: Show calls" + logit "BRI/PRI: Show calls" else - logit "BRI: Failed to send command" + logit "BRI/PRI: Failed to send command" fi return $rc diff --git a/ssmg/sangoma_mgd.trunk/unit/.svn/entries b/ssmg/sangoma_mgd.trunk/unit/.svn/entries index 873578d..9ac2c1f 100644 --- a/ssmg/sangoma_mgd.trunk/unit/.svn/entries +++ b/ssmg/sangoma_mgd.trunk/unit/.svn/entries @@ -1,7 +1,7 @@ 8 dir -276 +282 https://www.sangomapbx.com/svn/sangoma_mgd/trunk/unit https://www.sangomapbx.com/svn/sangoma_mgd diff --git a/ssmg/sangoma_mgd.trunk/unit/core/.svn/entries b/ssmg/sangoma_mgd.trunk/unit/core/.svn/entries index 7db3c66..1f8b484 100644 --- a/ssmg/sangoma_mgd.trunk/unit/core/.svn/entries +++ b/ssmg/sangoma_mgd.trunk/unit/core/.svn/entries @@ -1,7 +1,7 @@ 8 dir -276 +282 https://www.sangomapbx.com/svn/sangoma_mgd/trunk/unit/core https://www.sangomapbx.com/svn/sangoma_mgd diff --git a/ssmg/sangoma_mgd.trunk/unit/tests/.svn/entries b/ssmg/sangoma_mgd.trunk/unit/tests/.svn/entries index 48a8adc..b6f4dbe 100644 --- a/ssmg/sangoma_mgd.trunk/unit/tests/.svn/entries +++ b/ssmg/sangoma_mgd.trunk/unit/tests/.svn/entries @@ -1,7 +1,7 @@ 8 dir -276 +282 https://www.sangomapbx.com/svn/sangoma_mgd/trunk/unit/tests https://www.sangomapbx.com/svn/sangoma_mgd diff --git a/ssmg/sangoma_mgd.trunk/unit/tests/1_loop/.svn/entries b/ssmg/sangoma_mgd.trunk/unit/tests/1_loop/.svn/entries index 97ee66d..5babeab 100644 --- a/ssmg/sangoma_mgd.trunk/unit/tests/1_loop/.svn/entries +++ b/ssmg/sangoma_mgd.trunk/unit/tests/1_loop/.svn/entries @@ -1,7 +1,7 @@ 8 dir -276 +282 https://www.sangomapbx.com/svn/sangoma_mgd/trunk/unit/tests/1_loop https://www.sangomapbx.com/svn/sangoma_mgd diff --git a/ssmg/sangoma_mgd.trunk/unit/tests/1_loop/tmp/.svn/entries b/ssmg/sangoma_mgd.trunk/unit/tests/1_loop/tmp/.svn/entries index 75588a0..8e29a31 100644 --- a/ssmg/sangoma_mgd.trunk/unit/tests/1_loop/tmp/.svn/entries +++ b/ssmg/sangoma_mgd.trunk/unit/tests/1_loop/tmp/.svn/entries @@ -1,7 +1,7 @@ 8 dir -276 +282 https://www.sangomapbx.com/svn/sangoma_mgd/trunk/unit/tests/1_loop/tmp https://www.sangomapbx.com/svn/sangoma_mgd diff --git a/ssmg/sangoma_mgd.trunk/unit/tests/2_loop_call/.svn/entries b/ssmg/sangoma_mgd.trunk/unit/tests/2_loop_call/.svn/entries index 2a35f89..50c510b 100644 --- a/ssmg/sangoma_mgd.trunk/unit/tests/2_loop_call/.svn/entries +++ b/ssmg/sangoma_mgd.trunk/unit/tests/2_loop_call/.svn/entries @@ -1,7 +1,7 @@ 8 dir -276 +282 https://www.sangomapbx.com/svn/sangoma_mgd/trunk/unit/tests/2_loop_call https://www.sangomapbx.com/svn/sangoma_mgd diff --git a/ssmg/sangoma_mgd.trunk/unit/tests/2_loop_call/tmp/.svn/entries b/ssmg/sangoma_mgd.trunk/unit/tests/2_loop_call/tmp/.svn/entries index e2fc206..d621895 100644 --- a/ssmg/sangoma_mgd.trunk/unit/tests/2_loop_call/tmp/.svn/entries +++ b/ssmg/sangoma_mgd.trunk/unit/tests/2_loop_call/tmp/.svn/entries @@ -1,7 +1,7 @@ 8 dir -276 +282 https://www.sangomapbx.com/svn/sangoma_mgd/trunk/unit/tests/2_loop_call/tmp https://www.sangomapbx.com/svn/sangoma_mgd diff --git a/util/Makefile b/util/Makefile index 7898998..8b58391 100644 --- a/util/Makefile +++ b/util/Makefile @@ -66,3 +66,6 @@ clean: make -C wancfg clean WAN_VIRTUAL=$(WAN_VIRTUAL) make -C wan_aftup clean WAN_VIRTUAL=$(WAN_VIRTUAL) make -C bwm clean WAN_VIRTUAL=$(WAN_VIRTUAL) + make -C misc clean WAN_VIRTUAL=$(WAN_VIRTUAL) + make -C wanctrl clean WAN_VIRTUAL=$(WAN_VIRTUAL) + make -C bwm-ng clean WAN_VIRTUAL=$(WAN_VIRTUAL) diff --git a/util/bwm-ng/src/bwm-ng b/util/bwm-ng/src/bwm-ng deleted file mode 100755 index 9166add..0000000 Binary files a/util/bwm-ng/src/bwm-ng and /dev/null differ diff --git a/util/bwm/Makefile b/util/bwm/Makefile index 2c745ce..a33ab7a 100644 --- a/util/bwm/Makefile +++ b/util/bwm/Makefile @@ -1,5 +1,8 @@ +CC=gcc +CFLAGS= -O2 -Wall + all: bwm.c - $(CC) $(CFLAGS) -O2 -Wall bwm.c -o wpbwm + $(CC) $(CFLAGS) bwm.c -o wpbwm clean: rm -f wpbwm diff --git a/util/misc/wanconfig_client b/util/misc/wanconfig_client deleted file mode 100755 index 22b33e7..0000000 Binary files a/util/misc/wanconfig_client and /dev/null differ diff --git a/util/misc/wp_x25_event_read b/util/misc/wp_x25_event_read deleted file mode 100755 index 56488e8..0000000 Binary files a/util/misc/wp_x25_event_read and /dev/null differ diff --git a/util/misc/wpkbdmon b/util/misc/wpkbdmon deleted file mode 100755 index 96aa72e..0000000 Binary files a/util/misc/wpkbdmon and /dev/null differ diff --git a/util/wan_aftup/wan_aft_prg.c b/util/wan_aftup/wan_aft_prg.c index 82fb1e0..a4b7c1b 100644 --- a/util/wan_aftup/wan_aft_prg.c +++ b/util/wan_aftup/wan_aft_prg.c @@ -617,6 +617,7 @@ int board_reset(wan_aft_cpld_t *cpld, int clear) break; case A200_REMORA_SHARK_SUBSYS_VENDOR: case A400_REMORA_SHARK_SUBSYS_VENDOR: + case AFT_B800_SUBSYS_VENDOR: if (clear) data &= ~0x06; else data |= 0x06; break; diff --git a/util/wan_aftup/wan_aftup.c b/util/wan_aftup/wan_aftup.c index e2f9d37..fc74bfe 100644 --- a/util/wan_aftup/wan_aftup.c +++ b/util/wan_aftup/wan_aftup.c @@ -159,6 +159,8 @@ aft_core_info_t aft_core_table[] = { "A108dm_0100_V", "A108dm_0100_V*.BIN", AFT_CORE_X1000_SIZE }, { A200_REMORA_SHARK_SUBSYS_VENDOR, AFT_CHIP_X400, AFT_ANALOG_FE_CORE_ID, 0x01, 0x4F, "A200_0040_V", "A200_0040_V*.BIN", AFT_CORE_X400_SIZE }, + { AFT_B800_SUBSYS_VENDOR, AFT_CHIP_X400, AFT_ANALOG_FE_CORE_ID, 0x01, 0x4F, + "B800_0040_V", "B800_0040_V*.BIN", AFT_CORE_X400_SIZE }, { A400_REMORA_SHARK_SUBSYS_VENDOR, AFT_CHIP_X400, AFT_ANALOG_FE_CORE_ID, 0x01, 0x4F, "A400_0040_V", "A400_0040_V*.BIN", AFT_CORE_X400_SIZE }, { A200_REMORA_SHARK_SUBSYS_VENDOR, AFT_CHIP_X200, AFT_ANALOG_FE_CORE_ID, 0x20, 0x5B, @@ -418,6 +420,7 @@ static int wan_aftup_gettype(wan_aftup_t *aft, char *type) aft->cpld.iface = &aftup_flash_iface; break; case A200_ADPTR_ANALOG: + case AFT_ADPTR_B800: case A400_ADPTR_ANALOG: case A305_ADPTR_C_1TE3: case AFT_ADPTR_56K: @@ -460,6 +463,9 @@ static int wan_aftup_gettype(wan_aftup_t *aft, char *type) //strcpy(aft->prefix_fw, "AFT_RM"); aft->cpld.adptr_type = A200_ADPTR_ANALOG; aft->cpld.iface = &aftup_shark_flash_iface; + }else if (strncmp(type,"AFT-B800",8) == 0){ + aft->cpld.adptr_type = AFT_ADPTR_B800; + aft->cpld.iface = &aftup_shark_flash_iface; }else if (strncmp(type,"AFT-A400",8) == 0){ //strcpy(aft->prefix_fw, "AFT_RM"); aft->cpld.adptr_type = A400_ADPTR_ANALOG; @@ -948,6 +954,9 @@ static int wan_aftup_update_card(wan_aftup_t *aft) case A200_REMORA_SHARK_SUBSYS_VENDOR: aft->cpld.iface = &aftup_shark_flash_iface; break; + case AFT_B800_SUBSYS_VENDOR: + aft->cpld.iface = &aftup_shark_flash_iface; + break; case A400_REMORA_SHARK_SUBSYS_VENDOR: aft->cpld.iface = &aftup_shark_flash_iface; break; @@ -1011,6 +1020,7 @@ static int wan_aftup_update_card(wan_aftup_t *aft) break; case A200_REMORA_SHARK_SUBSYS_VENDOR: case A400_REMORA_SHARK_SUBSYS_VENDOR: + case AFT_B800_SUBSYS_VENDOR: aft->cpld.chip_id = AFT_CHIP_X1000; aft->cpld.flash = &aft_shark_flash; break; @@ -1088,6 +1098,7 @@ static int wan_pcie_ctrl(struct wan_aftup_head_t *head) break; case A200_REMORA_SHARK_SUBSYS_VENDOR: case A400_REMORA_SHARK_SUBSYS_VENDOR: + case AFT_B800_SUBSYS_VENDOR: case AFT_A600_SUBSYS_VENDOR: case AFT_B601_SUBSYS_VENDOR: break; diff --git a/util/wancfg_zaptel/install.sh b/util/wancfg_zaptel/install.sh index 634c143..d3ae63b 100755 --- a/util/wancfg_zaptel/install.sh +++ b/util/wancfg_zaptel/install.sh @@ -24,6 +24,7 @@ install -D -m 755 wancfg_tdmapi $WAN_VIRTUAL/usr/sbin/wancfg_tdmapi install -D -m 755 wancfg_hp_tdmapi $WAN_VIRTUAL/usr/sbin/wancfg_hp_tdmapi install -D -m 755 wancfg_fs $WAN_VIRTUAL/usr/sbin/wancfg_fs install -D -m 755 wancfg_openzap $WAN_VIRTUAL/usr/sbin/wancfg_openzap +install -D -m 755 wancfg_ftdm $WAN_VIRTUAL/usr/sbin/wancfg_ftdm #cp -rf setup-sangoma $WAN_VIRTUAL/usr/local/sbin #chmod 755 $WAN_VIRTUAL/usr/local/sbin/setup-sangoma diff --git a/util/wancfg_zaptel/templates/freetdm.conf b/util/wancfg_zaptel/templates/freetdm.conf new file mode 100644 index 0000000..e69de29 diff --git a/util/wancfg_zaptel/templates/freetdm.conf.xml b/util/wancfg_zaptel/templates/freetdm.conf.xml new file mode 100644 index 0000000..953bbdd --- /dev/null +++ b/util/wancfg_zaptel/templates/freetdm.conf.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/util/wancfg_zaptel/templates/wanpipe.tdm.a100 b/util/wancfg_zaptel/templates/wanpipe.tdm.a100 index 649337d..732352b 100644 --- a/util/wancfg_zaptel/templates/wanpipe.tdm.a100 +++ b/util/wancfg_zaptel/templates/wanpipe.tdm.a100 @@ -39,13 +39,27 @@ TE_RX_SLEVEL = RXSLEVEL LBO = FELBO FE_TXTRISTATE = NO MTU = 1500 -UDPPORT = 9000 +UDPPORT = 9000 TTL = 255 -IGNORE_FRONT_END = NO -TDMV_SPAN = TDMVSPANNO -TDMV_DCHAN = TDMVDCHAN -TDMV_HW_DTMF = HWDTMF -TDMV_HW_FAX_DETECT = HWFAX +IGNORE_FRONT_END = NO +TDMV_SPAN = TDMVSPANNO +TDMV_DCHAN = TDMVDCHAN +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 +TDMV_HW_DTMF = HWDTMF # YES: receive dtmf events from hardware +TDMV_HW_FAX_DETECT = HWFAX # YES: receive fax 1100hz events from hardware +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 tx 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 [wIFNUMg1] ACTIVE_CH = ALL diff --git a/util/wancfg_zaptel/templates/wanpipe.tdm.a10u b/util/wancfg_zaptel/templates/wanpipe.tdm.a10u index 8053c6a..7e9ec56 100644 --- a/util/wancfg_zaptel/templates/wanpipe.tdm.a10u +++ b/util/wancfg_zaptel/templates/wanpipe.tdm.a10u @@ -44,6 +44,22 @@ TTL = 255 IGNORE_FRONT_END = NO TDMV_SPAN = TDMVSPANNO TDMV_DCHAN = TDMVDCHAN +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 +TDMV_HW_DTMF = HWDTMF # YES: receive dtmf events from hardware +TDMV_HW_FAX_DETECT = HWFAX # YES: receive fax 1100hz events from hardware +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 tx 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 [wIFNUMg1] ACTIVE_CH = ALL diff --git a/util/wancfg_zaptel/templates/wanpipe.tdm.a200 b/util/wancfg_zaptel/templates/wanpipe.tdm.a200 index b4f6d65..bc1b8ca 100644 --- a/util/wancfg_zaptel/templates/wanpipe.tdm.a200 +++ b/util/wancfg_zaptel/templates/wanpipe.tdm.a200 @@ -38,8 +38,22 @@ UDPPORT = 9000 TTL = 255 IGNORE_FRONT_END = NO TDMV_SPAN = TDMVSPANNO -TDMV_HW_DTMF = HWDTMF -TDMV_HW_FAX_DETECT = HWFAX +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 +TDMV_HW_DTMF = HWDTMF # YES: receive dtmf events from hardware +TDMV_HW_FAX_DETECT = HWFAX # YES: receive fax 1100hz events from hardware +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 tx 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 [wIFNUMg1] ACTIVE_CH = ALL diff --git a/util/wancfg_zaptel/templates/wanpipe.tdm_api.a100 b/util/wancfg_zaptel/templates/wanpipe.tdm_api.a100 index 41bb3ad..3dac5d4 100644 --- a/util/wancfg_zaptel/templates/wanpipe.tdm_api.a100 +++ b/util/wancfg_zaptel/templates/wanpipe.tdm_api.a100 @@ -43,8 +43,22 @@ TTL = 255 IGNORE_FRONT_END = NO TDMV_SPAN = TDMVSPANNO TDMV_DCHAN = TDMVDCHAN -TDMV_HW_DTMF = HWDTMF -TDMV_HW_FAX_DETECT = HWFAX +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 +TDMV_HW_DTMF = HWDTMF # YES: receive dtmf events from hardware +TDMV_HW_FAX_DETECT = HWFAX # YES: receive fax 1100hz events from hardware +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 tx 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 [wDEVNUMg1] ACTIVE_CH = ALL diff --git a/util/wancfg_zaptel/templates/wanpipe.tdm_api.a500 b/util/wancfg_zaptel/templates/wanpipe.tdm_api.a500 index c31e9b0..51f3248 100755 --- a/util/wancfg_zaptel/templates/wanpipe.tdm_api.a500 +++ b/util/wancfg_zaptel/templates/wanpipe.tdm_api.a500 @@ -37,8 +37,22 @@ UDPPORT = 9000 TTL = 255 IGNORE_FRONT_END = NO TDMV_SPAN = TDMVSPANNO -TDMV_HW_DTMF = HWDTMF -TDMV_HW_FAX_DETECT = HWFAX +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 +TDMV_HW_DTMF = HWDTMF # YES: receive dtmf events from hardware +TDMV_HW_FAX_DETECT = HWFAX # YES: receive fax 1100hz events from hardware +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 tx 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 [wIFNUMg1] ACTIVE_CH = ALL diff --git a/util/wancfg_zaptel/wancfg_ftdm b/util/wancfg_zaptel/wancfg_ftdm new file mode 100755 index 0000000..22ccf66 --- /dev/null +++ b/util/wancfg_zaptel/wancfg_ftdm @@ -0,0 +1,52 @@ +#!/bin/sh +home=`pwd` +cd $home + +read_meta_conf () +{ + + if [ $ostype = "Linux" ]; then + WAN_BASE=/etc + WAN_HOME=$WAN_BASE/wanpipe + META_CONF=$WAN_BASE/wanpipe/wanrouter.rc + elif [ $ostype = "FreeBSD" -o $ostype = "OpenBSD" ]; then + WAN_BASE=/usr/local/etc + WAN_HOME=$WAN_BASE/wanpipe + wanrouter_rc_file="" + if [ -r /etc/rc.conf ]; then + . /etc/rc.conf + fi + if [ -n "$wanrouter_rc_file" ]; then + WAN_HOME=${wanrouter_rc_file%/*} + fi + META_CONF=$wanrouter_rc_file + fi + + # Read meta-configuration file. + if [ -f $META_CONF ] + then . $META_CONF + else + return 1 + fi + return 0 +} + +ostype=`sysctl -a |grep ostype` +ostype=`echo $ostype | sed 's/.* //'` + +while [ ! -z "$1" ]; +do + ARGS=$ARGS"$1 " + shift +done + + +read_meta_conf +if [ $? -ne 0 ]; then + echo "ERROR: Failed to find Wanpipe meta config file!" + exit 1 +fi + +cd ${WAN_HOME}/wancfg_zaptel +./wancfg_zaptel.pl --ftdm_api --conf_dir=$WAN_BASE $ARGS +cd $home diff --git a/util/wancfg_zaptel/wancfg_zaptel.pl b/util/wancfg_zaptel/wancfg_zaptel.pl index aea0fb6..a959798 100755 --- a/util/wancfg_zaptel/wancfg_zaptel.pl +++ b/util/wancfg_zaptel/wancfg_zaptel.pl @@ -9,6 +9,8 @@ # as published by the Free Software Foundation; either version # 2 of the License, or (at your option) any later version. # ---------------------------------------------------------------------------- +# May 14 2010 2.41 Yannick Lam Added wancfg_ftdm (script for freetdm) +# May 04 2010 2.40 Yannick Lam Fix smg_pri.conf for wancfg_fs # Nov 26 2009 2.39 Jignesh Patel Fix woomera.conf for sangoma_pri & openzap.conf for E1 # Oct 29 2009 2.38 Jignesh Patel Minor changes to signalling order dahdi start script update # Sep 07 2009 2.37 Jignesh Patel Added B601 support @@ -184,12 +186,17 @@ my $is_hp_tdm_api=$FALSE; my $is_fs=$FALSE; my $is_openzap=$FALSE; +my $is_ftdm=$FALSE; +my $config_freetdm = $FALSE; +my $config_freetdm_xml = $FALSE; + my $def_femedia=''; my $def_feclock=''; my $def_bri_option=''; my $def_bri_default_tei=''; my $def_bri_default_tei_opt=$FALSE; my $def_signalling=''; +my $ftdm_signalling='pri_cpe'; my $def_sigmode=''; my $def_switchtype=''; my $def_zapata_context=''; @@ -347,8 +354,16 @@ if ($is_fs== $TRUE) { $config_zapata = $FALSE; $config_openzap= $TRUE; $config_openzap_xml=$TRUE; + $def_sigmode='pri_cpe'; } +if ($is_ftdm== $TRUE) { + $config_woomera=$FALSE; + $config_zapata = $FALSE; + $config_freetdm= $TRUE; + $config_freetdm_xml=$TRUE; +} + my $bri_conf_template="$current_dir/templates/smg_bri.conf"; @@ -371,6 +386,13 @@ my $openzap_conf_xml_template="$current_dir/templates/openzap.conf.xml"; my $openzap_conf_xml_file="$current_dir/$cfg_dir/openzap.conf.xml"; my $openzap_conf_xml_file_t="$fs_conf_dir/autoload_configs/openzap.conf.xml"; +my $freetdm_conf_template="$current_dir/templates/freetdm.conf"; +my $freetdm_conf_file="$current_dir/$cfg_dir/freetdm.conf"; +my $freetdm_conf_file_t="$fs_conf_dir/freetdm.conf"; + +my $freetdm_conf_xml_template="$current_dir/templates/freetdm.conf.xml"; +my $freetdm_conf_xml_file="$current_dir/$cfg_dir/freetdm.conf.xml"; +my $freetdm_conf_xml_file_t="$fs_conf_dir/autoload_configs/freetdm.conf.xml"; my $date=`date +%F`; my $mdate= `date +"%a-%d-%b-%Y-%I-%M:%S-%p"`; @@ -939,16 +961,27 @@ sub apply_changes{ exec_command("cp -f $smg_rc_file $smg_rc_file_t"); } - if($config_openzap == $TRUE){ + if($config_openzap == $TRUE && $is_ftdm == $FALSE){ print "\nCopying new openzap configuration files ($openzap_conf_file_t)...\n"; exec_command("cp -f $openzap_conf_file $openzap_conf_file_t"); } - if($config_openzap_xml == $TRUE && $is_openzap == $FALSE){ + #if($config_openzap_xml == $TRUE && $is_openzap == $FALSE){ + if($config_openzap_xml == $TRUE && $is_openzap == $TRUE){ print "\nCopying new openzap configuration files ($openzap_conf_xml_file_t)...\n"; exec_command("cp -f $openzap_conf_xml_file $openzap_conf_xml_file_t"); } + if($config_freetdm == $TRUE){ + print "\nCopying new freetdm configuration files ($freetdm_conf_file_t)...\n"; + exec_command("cp -f $freetdm_conf_file $freetdm_conf_file_t"); + + } + if($config_freetdm_xml == $TRUE && $is_ftdm == $TRUE){ + print "\nCopying new freetdm configuration files ($freetdm_conf_xml_file_t)...\n"; + exec_command("cp -f $freetdm_conf_xml_file $freetdm_conf_xml_file_t"); + } + if( $asterisk_restart == $TRUE && $is_tdm_api==$FALSE && $is_hp_tdm_api==$FALSE ){ print "\nStarting Wanpipe...\n"; @@ -1219,12 +1252,13 @@ sub prepare_files{ $fs_conf_dir=&prompt_user("Enter FreeSwitch Conf Directory \n"); while(! -d $fs_conf_dir){ - print "Invalid FFreeSwitch Configuration Directory, Please Enter FreeSwitch Configuration Directory\n"; + print "Invalid FreeSwitch Configuration Directory, Please Enter FreeSwitch Configuration Directory\n"; $fs_conf_dir=&prompt_user("Input the FreeSwitch Conf Dir",$fs_conf_dir); } $openzap_conf_file_t="$fs_conf_dir/openzap.conf"; $openzap_conf_xml_file_t="$fs_conf_dir/autoload_configs/openzap.conf.xml"; - + $freetdm_conf_file_t="$fs_conf_dir/freetdm.conf"; + $freetdm_conf_xml_file_t="$fs_conf_dir/autoload_configs/freetdm.conf.xml" } } } @@ -1388,10 +1422,17 @@ sub summary{ if($num_digital_devices != 0){ write_pri_conf(); } - write_openzap_conf(); - if($is_openzap == $FALSE){ - write_openzap_conf_xml(); + if ($is_ftdm == $FALSE){ + write_openzap_conf(); + if($is_openzap == $FALSE){ + write_openzap_conf_xml(); + } } + if ($is_ftdm == $TRUE){ + write_freetdm_conf(); + write_freetdm_conf_xml(); + } + } save_debug_info(); @@ -1428,6 +1469,16 @@ sub summary{ print "\t$file_list. openzap_xml config file $fs_conf_dir/openzap.conf.xml\n"; $file_list++; } + + if($config_freetdm == $TRUE){ + print "\t$file_list. freetdm config file $fs_conf_dir/freetdm\n"; + $file_list++; + } + + if($config_freetdm_xml == $TRUE){ + print "\t$file_list. freetdm_xml config file $fs_conf_dir/freetdm.conf.xml\n"; + $file_list++; + } if ($num_zaptel_config != 0){ print "\t$file_list. $zaptel_string config file $zaptel_conf_file_t\n"; @@ -1576,6 +1627,10 @@ sub read_args { $is_openzap=$TRUE; $is_fs=$TRUE; $is_tdm_api=$TRUE;#fs use tdmapi mode + }elsif ( /^--ftdm_api$/){ + $is_ftdm=$TRUE; + $is_fs=$TRUE; + $is_tdm_api=$TRUE;#fs use tdmapi mode }elsif ( /^--no_hwdtmf$/){ $no_hwdtmf=$TRUE; }elsif ( /^--silent$/){ @@ -2907,7 +2962,7 @@ ENDSS7CONFIG: my $chan_set='s'.$openzapspan.'c1-s'.$openzapspan.'c23'; my $group_no='1'; my $cardname=''; - $def_sigmode='pri_cpe'; + #$def_sigmode='pri_cpe'; if($silent==$FALSE){ printf ("Select Switchtype for AFT-%s on port %s [slot:%s bus:%s span:$devnum]\n", get_card_name($card->card_model), $port, $card->pci_slot, $card->pci_bus); @@ -2923,7 +2978,7 @@ ENDSS7CONFIG: } printf ("Select signalling type for AFT-%s on port %s [slot:%s bus:%s span:$devnum]\n", get_card_name($card->card_model), $port, $card->pci_slot, $card->pci_bus); - @options = ("PRI CPE", "PRI NET", ); + @options = ("PRI CPE", "PRI NET"); $def_sigmode=&prompt_user_list(@options,$def_sigmode); $group_no=get_woomera_group(); @@ -3702,6 +3757,102 @@ sub write_openzap_conf{ return ; } +sub write_freetdm_conf{ + + if($is_fs==$FALSE){ + return; + } + my $freetdm=''; + $freetdm.="\n"; + + if(@boostprispan){ + foreach my $span (@boostprispan){ + my $boostprispan=$span; + $freetdm.="[span wanpipe wp"; + $freetdm.=$boostprispan->span_no(); + $freetdm.="]\n"; + $freetdm.="number =>"; + $freetdm.=$boostprispan->span_no()."\n"; + $freetdm.="trunk_type =>"; + $freetdm.=$boostprispan->span_type()."\n"; + $freetdm.="group=>grp"; + $freetdm.=$boostprispan->group_no()."\n"; + $freetdm.="b-channel => "; + $freetdm.=$boostprispan->span_no(); + $freetdm.=":"; + $freetdm.=$boostprispan->chan_no(); + if($boostprispan->span_type() eq 'e1') + { + $freetdm.="\n"; + $freetdm.="b-channel => "; + $freetdm.=$boostprispan->span_no(); + $freetdm.=":"; + $freetdm.="17-31"; + } + $freetdm.="\n\n"; + } + + } + $freetdm.="\n\n"; + +# if(@boostbrispan){ +# $openzap.="[span wanpipe smg_brid]\n"; +# $openzap.="name => smg_brid\n"; +# $openzap.="trunk_type => bri\n"; +# foreach my $span (@boostbrispan){ +# my $boostbrispan=$span; +# $openzap.="b-channel => "; +# $openzap.=$boostbrispan->span_no(); +# $openzap.=":"; +# $openzap.=$boostbrispan->chan_no(); +# $openzap.="\n"; +# } + +# } +# $openzap.="\n\n"; + + if(@fxsspan){ + $freetdm.="[span wanpipe FXS]\n"; + $freetdm.="name => freetdm\n"; + foreach my $span (@fxsspan){ + my $fxsspan=$span; + $freetdm.="fxs-channel => "; + $freetdm.=$fxsspan->span_no(); + $freetdm.=":"; + $freetdm.=$fxsspan->chan_no(); + $freetdm.="\n"; + } + $freetdm.="\n\n"; + } + if(@fxospan){ + $freetdm.="[span wanpipe FXO]\n"; + $freetdm.="name => freetdm\n"; + foreach my $span (@fxospan){ + my $fxospan=$span; + $freetdm.="fxo-channel => "; + $freetdm.=$fxospan->span_no(); + $freetdm.=":"; + $freetdm.=$fxospan->chan_no(); + $freetdm.="\n"; + } + + } + $freetdm.="\n\n"; + + #need to fix properly + my $freetdm_file=""; + open(FH, "$freetdm_conf_template") or die "cannot open $freetdm_conf_template"; + while () { + $freetdm_file .= $_; + } + close (FH); + $freetdm_file=$freetdm_file.$freetdm; + open(FH, ">$freetdm_conf_file") or die "cannot open $freetdm_conf_file"; + print FH $freetdm_file; + close(FH); + return ; +} + sub config_smg_ctrl_boot { #smg_ctrl must start after network my $network_start_level=10; @@ -3922,6 +4073,92 @@ sub write_openzap_conf_xml{ return ; } +sub write_freetdm_conf_xml{ + my $freetdm_boostpri=''; + #$freetdm_boostpri.="\n"; + my $freetdm_boostbri=''; + my $freetdm_fxs=''; + my $freetdm_fxo=''; + + if(@boostprispan){ + #add boost pri conf + #$freetdm_boostpri.=''."\n\t"; + foreach my $span (@boostprispan){ + my $boostprispan=$span; + #print "YANNCIK IN WRITE_FREETDM_CONF_XML function\n"; + $freetdm_boostpri.='span_no(); + $freetdm_boostpri.='" sigmod="sangoma_prid">'."\n\t"; + $freetdm_boostpri.='sig_mode() eq "PRI NET"){ + $ftdm_signalling = "pri_net"; + } + $freetdm_boostpri.=$ftdm_signalling;#$boostprispan->sig_mode(); + $freetdm_boostpri.='"/>'."\n\t"; + $freetdm_boostpri.=''."\n\t"; + $freetdm_boostpri.=''."\n\t"; + } + } + +# if(@boostbrispan){ + #add boost bri conf + #$openzap_boostbri.=''."\n\t"; + #$openzap_boostbri.=''."\n\t"; + #$openzap_boostbri.=''."\n\t"; + #$openzap_boostbri.=''."\n\t";; + #$openzap_boostbri.=' '."\n\t"; + #$openzap_boostbri.=''."\n\t"; + #$openzap_boostbri.=''."\n\t"; + #$openzap_boostbri.=''."\n"; + #$openzap_boostbri.=''."\n"; + #} + + if(@fxsspan){ + $freetdm_fxs.=''."\n\t"; + $freetdm_fxs.=''."\n\t"; + $freetdm_fxs.=''."\n\t"; + $freetdm_fxs.=''."\n\t";; + $freetdm_fxs.=' '."\n\t"; + $freetdm_fxs.=''."\n\t"; + $freetdm_fxs.=''."\n\t"; + $freetdm_fxs.=''."\n"; + $freetdm_fxs.=''."\n"; + } + if(@fxospan){ + $freetdm_fxo.=''."\n\t"; + $freetdm_fxo.=''."\n\t"; + $freetdm_fxo.=''."\n\t"; + $freetdm_fxo.=''."\n\t";; + $freetdm_fxo.=' '."\n\t"; + $freetdm_fxo.=''."\n\t"; + $freetdm_fxo.=''."\n\t"; + $freetdm_fxo.=''."\n"; + $freetdm_fxo.=''."\n"; + } + + my $freetdm_xml_file=""; + open(FH, "$freetdm_conf_xml_template") or die "cannot open $freetdm_conf_xml_template"; + while () { + $freetdm_xml_file .= $_; + } + close (FH); + + #$freetdm_xml_file=$freetdm_file.$freetdm; + $freetdm_xml_file=~ s//$freetdm_boostpri/g; + #$openzap_xml_file=~ s//$freetdm_boostbri/g; + $freetdm_xml_file=~ s//$freetdm_fxs/g; + $freetdm_xml_file=~ s//$freetdm_fxo/g; + open(FH, ">$freetdm_conf_xml_file") or die "cannot open $freetdm_conf_xml_file"; + print FH $freetdm_xml_file; + close(FH); + return ; +} + sub gen_smg_rc{ #update smg rc printf("Generating smg.cr \n"); diff --git a/util/wanconfig/wanconfig.c b/util/wanconfig/wanconfig.c index 5f1c228..40f99f3 100644 --- a/util/wanconfig/wanconfig.c +++ b/util/wanconfig/wanconfig.c @@ -10,13 +10,13 @@ * 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. -* ---------------------------------------------------------------------------- -* Jan 11, 2010 David Rokhvarg Moved data type declarations and lookup tables -* to wanconfig.h. -* Moved code for configuration of hardware echo -* canceller to wanconfig_hwec.c. -* Both changes needed for code re-use in -* cross-platform software (Linux:wanconfig; +* ---------------------------------------------------------------------------- +* Jan 11, 2010 David Rokhvarg Moved data type declarations and lookup tables +* to wanconfig.h. +* Moved code for configuration of hardware echo +* canceller to wanconfig_hwec.c. +* Both changes needed for code re-use in +* cross-platform software (Linux:wanconfig; * Windows:wanrouter.exe). * Sep 25, 2007 Alex Feldman Verify return code from wanec client. * Jun 25, 2007 David Rokhvarg Added support for AFT-ISDN BRI (A500) card. @@ -95,7 +95,7 @@ #include "wanpipe_events.h" #include "wanec_api.h" -#include "wanpipe.h" +#include "wanpipe.h" #include "wanconfig.h" #define smemof(TYPE, MEMBER) offsetof(TYPE,MEMBER),(sizeof(((TYPE *)0)->MEMBER)) @@ -190,18 +190,18 @@ int exec_command(char *rx_data); void catch_signal(int signum,int nomask); /****** Global Data *********************************************************/ - -char master_lapb_dev[WAN_DRVNAME_SZ+1]; -char master_x25_dev[WAN_DRVNAME_SZ+1]; -char master_dsp_dev[WAN_DRVNAME_SZ+1]; -char master_lip_dev[WAN_DRVNAME_SZ+1]; - -#define MAX_WAKEUI_WAIT 2 -static char wakeup_ui=0; -static time_t time_ui=0; - -#define MAX_FIRMW_SIZE 40000 -static unsigned char firmware_file_buffer[MAX_FIRMW_SIZE]; + +char master_lapb_dev[WAN_DRVNAME_SZ+1]; +char master_x25_dev[WAN_DRVNAME_SZ+1]; +char master_dsp_dev[WAN_DRVNAME_SZ+1]; +char master_lip_dev[WAN_DRVNAME_SZ+1]; + +#define MAX_WAKEUI_WAIT 2 +static char wakeup_ui=0; +static time_t time_ui=0; + +#define MAX_FIRMW_SIZE 40000 +static unsigned char firmware_file_buffer[MAX_FIRMW_SIZE]; char prognamed[20] = "wanconfig"; char progname_sp[] = " "; @@ -3931,7 +3931,7 @@ unsigned int parse_active_channel(char* val) return 0; while(*ptr != '\0') { - printf("\nMAP DIGIT %c\n", *ptr); + //printf("\nMAP DIGIT %c\n", *ptr); if (isdigit(*ptr)) { channel = strtoul(ptr, &ptr, 10); channel_flag |= SINGLE_CHANNEL; diff --git a/util/wanconfig/wanconfig.h b/util/wanconfig/wanconfig.h index 97c01b6..84de826 100755 --- a/util/wanconfig/wanconfig.h +++ b/util/wanconfig/wanconfig.h @@ -282,6 +282,7 @@ static key_word_t common_conftab[] = /* Common configuration parameters */ { "TE_REF_CLOCK", offsetof(wandev_conf_t, fe_cfg)+offsetof(sdla_fe_cfg_t, cfg) + smemof(sdla_te_cfg_t, te_ref_clock), DTYPE_UCHAR }, { "TE_SIG_MODE", offsetof(wandev_conf_t, fe_cfg)+offsetof(sdla_fe_cfg_t, cfg) + smemof(sdla_te_cfg_t, sig_mode), DTYPE_UCHAR }, { "TE_IGNORE_YEL", offsetof(wandev_conf_t, fe_cfg)+offsetof(sdla_fe_cfg_t, cfg) + smemof(sdla_te_cfg_t, ignore_yel_alarm), DTYPE_UCHAR }, + { "TE_AIS_MAINTENANCE", offsetof(wandev_conf_t, fe_cfg)+offsetof(sdla_fe_cfg_t, cfg) + smemof(sdla_te_cfg_t, ais_maintenance), DTYPE_UCHAR }, /* T1/E1 Front-End parameters (old style) */ { "LBO", offsetof(wandev_conf_t, fe_cfg)+offsetof(sdla_fe_cfg_t, cfg) + smemof(sdla_te_cfg_t, lbo), DTYPE_UCHAR }, { "ACTIVE_CH", offsetof(wandev_conf_t, fe_cfg)+offsetof(sdla_fe_cfg_t, cfg) + smemof(sdla_te_cfg_t, active_ch), DTYPE_UINT }, @@ -336,9 +337,19 @@ static key_word_t common_conftab[] = /* Common configuration parameters */ { "HWEC_PERSIST", offsetof(wandev_conf_t, hwec_conf)+smemof(wan_hwec_conf_t, persist_disable), DTYPE_UINT}, /* Keep backward compatibility */ { "TDMV_HWEC_PERSIST_DISABLE", offsetof(wandev_conf_t, hwec_conf)+smemof(wan_hwec_conf_t, persist_disable), DTYPE_UINT}, + + /* hwec parameters */ { "HWEC_NOISE_REDUCTION", offsetof(wandev_conf_t, hwec_conf)+smemof(wan_hwec_conf_t, noise_reduction), DTYPE_UCHAR}, { "HWEC_NOISE_REDUCTION_DISABLE", offsetof(wandev_conf_t, hwec_conf)+smemof(wan_hwec_conf_t, noise_reduction_disable), DTYPE_UCHAR}, { "HWEC_TONEDISABLERDELAY", offsetof(wandev_conf_t, hwec_conf)+smemof(wan_hwec_conf_t, tone_disabler_delay), DTYPE_UINT}, + { "HWEC_DTMF_REMOVAL", offsetof(wandev_conf_t, hwec_conf)+smemof(wan_hwec_conf_t, dtmf_removal), DTYPE_UCHAR}, + { "HWEC_OPERATION_MODE", offsetof(wandev_conf_t, hwec_conf)+smemof(wan_hwec_conf_t, operation_mode), DTYPE_UCHAR}, + { "HWEC_ACUSTIC_ECHO", offsetof(wandev_conf_t, hwec_conf)+smemof(wan_hwec_conf_t, acustic_echo), DTYPE_UCHAR}, + { "HWEC_NLP_DISABLE", offsetof(wandev_conf_t, hwec_conf)+smemof(wan_hwec_conf_t, nlp_disable), DTYPE_UCHAR}, + { "HWEC_TX_AUTO_GAIN", offsetof(wandev_conf_t, hwec_conf)+smemof(wan_hwec_conf_t, tx_auto_gain), DTYPE_INT}, + { "HWEC_RX_AUTO_GAIN", offsetof(wandev_conf_t, hwec_conf)+smemof(wan_hwec_conf_t, rx_auto_gain), DTYPE_INT}, + { "HWEC_TX_GAIN", offsetof(wandev_conf_t, hwec_conf)+smemof(wan_hwec_conf_t, tx_gain), DTYPE_INT}, + { "HWEC_RX_GAIN", offsetof(wandev_conf_t, hwec_conf)+smemof(wan_hwec_conf_t, rx_gain), DTYPE_INT}, { "OCT_CHIP_CONF", smemof(wandev_conf_t, oct_conf), DTYPE_OCT_FILENAME }, { "OCT_ECHOOPERATIONMODE", smemof(wandev_conf_t, oct_conf), DTYPE_OCT_CHAN_CONF}, @@ -1329,6 +1340,10 @@ static look_up_t sym_table[] = { WAN_TDMV_MULAW, "MULAW" }, { WANOPT_SIM, "SIMULATE" }, + + { WANOPT_OCT_CHAN_OPERMODE_NORMAL, "OCT_NORMAL" }, + { WANOPT_OCT_CHAN_OPERMODE_SPEECH, "OCT_SPEECH" }, + { WANOPT_OCT_CHAN_OPERMODE_NO_ECHO, "OCT_NO_ECHO" }, /*----- End ---------------------------*/ { 0, NULL }, diff --git a/util/wanconfig/wanconfig_hwec.c b/util/wanconfig/wanconfig_hwec.c index 18d603c..eea2197 100755 --- a/util/wanconfig/wanconfig_hwec.c +++ b/util/wanconfig/wanconfig_hwec.c @@ -62,7 +62,7 @@ unsigned int wancfglib_parse_active_channel(char *val); #if defined(WAN_HWEC) static int wanconfig_hwec_config(char *devname); static int wanconfig_hwec_release(char *devname); -static int wanconfig_hwec_enable(char *devname, char *); +static int wanconfig_hwec_enable(char *devname, char *, uint8_t); static int wanconfig_hwec_modify(char *devname, chan_def_t *def); static int wanconfig_hwec_bypass(char *devname, chan_def_t *def, int enable); static int wanconfig_hwec_tone(char *devname, int, int, char *); @@ -76,13 +76,30 @@ int wanconfig_hwec(chan_def_t *def) struct link_def *linkdef = def->link; int err; char devname[100]; + + /* We never want to enable dsp for non voice apps */ + if (strcmp(def->usedby, "XMTP2_API") == 0 || + strcmp(def->usedby, "STACK") == 0 || + strcmp(def->usedby, "DATA_API") == 0) { + def->chanconf->hwec.enable = WANOPT_NO; + return 0; + } - if ((linkdef->config_id != WANCONFIG_AFT_TE1 && + if (linkdef->config_id != WANCONFIG_AFT_TE1 && linkdef->config_id != WANCONFIG_AFT_ANALOG && - linkdef->config_id != WANCONFIG_AFT_ISDN_BRI) || - (def->chanconf->hwec.enable != WANOPT_YES && - linkdef->linkconf->tdmv_conf.hw_dtmf != WANOPT_YES)){ + linkdef->config_id != WANCONFIG_AFT_ISDN_BRI) { + + /* Do not enalbe hwec for non TE1/ANALOG/BRI cards */ + def->chanconf->hwec.enable = WANOPT_NO; linkdef->linkconf->tdmv_conf.hw_dtmf = WANOPT_NO; + linkdef->linkconf->tdmv_conf.hw_fax_detect = WANOPT_NO; + return 0; + } + + /* If both hwec and global dtmf are set to no then + nothing for us to do here */ + if (def->chanconf->hwec.enable != WANOPT_YES && + linkdef->linkconf->tdmv_conf.hw_dtmf != WANOPT_YES) { return 0; } @@ -97,11 +114,13 @@ int wanconfig_hwec(chan_def_t *def) return err; } - if ((err = wanconfig_hwec_enable(devname, def->active_ch))){ + + if ((err = wanconfig_hwec_enable(devname, def->active_ch, linkdef->linkconf->hwec_conf.operation_mode))){ wanconfig_hwec_release(devname); return err; } + if (linkdef->config_id == WANCONFIG_AFT_ISDN_BRI || linkdef->linkconf->hwec_conf.persist_disable) { @@ -110,32 +129,61 @@ int wanconfig_hwec(chan_def_t *def) return err; } } else { + if ((err = wanconfig_hwec_bypass(devname, def, 1))){ wanconfig_hwec_release(devname); return err; } } - + if ((err = wanconfig_hwec_modify(devname, def))){ wanconfig_hwec_release(devname); return err; } if (linkdef->linkconf->tdmv_conf.hw_dtmf == WANOPT_YES){ + err = wanconfig_hwec_tone(devname, 1, WP_API_EVENT_TONE_DTMF, def->active_ch); if (err){ wanconfig_hwec_release(devname); return err; } - if (linkdef->linkconf->tdmv_conf.hw_fax_detect){ + if (linkdef->linkconf->tdmv_conf.hw_fax_detect == WANOPT_YES){ + err = wanconfig_hwec_tone(devname, 1, WP_API_EVENT_TONE_FAXCALLING, def->active_ch); if (err){ wanconfig_hwec_release(devname); return err; } } + } + + /* In this case the hwec was not selected yes in interface + section, but dtmf or fax detection was still requested globaly. + Therefore, had to proceed to configure the hwec */ + if (def->chanconf->hwec.enable != WANOPT_YES) { + + if (linkdef->linkconf->tdmv_conf.hw_dtmf == WANOPT_YES && + linkdef->linkconf->hwec_conf.dtmf_removal == WANOPT_YES) { + /* If dtmf_removal has been set then customer wants us to + remove dtmf from the media but does not want us to peform + echo cancelation. In this case keep the bypass enabled, but + set the operation mode to NO_ECHO. This way media will still + flow through the chip but no echo cancelation will occour */ + err=wanconfig_hwec_enable(devname, def->active_ch, WANOPT_OCT_CHAN_OPERMODE_NO_ECHO); + if (err) { + wanconfig_hwec_release(devname); + return err; + } + } else { + /* In this case no media processing is needed, dtmf can + still be obtained via event. Thus we can proceed to do + a full bypass fo the echo canceler */ + wanconfig_hwec_bypass(devname, def, 0); + } } + return 0; } @@ -202,6 +250,7 @@ static int wanconfig_hwec_modify(char *devname, chan_def_t *def) wp_snprintf(cmd, sizeof(cmd), "%s %s modify %s %s", WANEC_CLIENT_NAME, devname, def->active_ch, conf_string); } + status = system(cmd); if (WEXITSTATUS(status) != 0){ fprintf(stderr,"--> Error: system command: %s\n",cmd); @@ -222,7 +271,7 @@ static int wanconfig_hwec_bypass(char *devname, chan_def_t *def, int enable) char cmd[500]; - if (wp_strcasecmp(def->active_ch, "all") == 0){ + if (wp_strcasecmp(def->active_ch, "all") == 0) { char chan_str [20]; unsigned int tdmv_dchan_map = def->link->linkconf->tdmv_conf.dchan; memset(chan_str, 0, sizeof(chan_str)); @@ -252,6 +301,7 @@ static int wanconfig_hwec_bypass(char *devname, chan_def_t *def, int enable) (enable)?"be":"bd", def->active_ch); } + status = system(cmd); if (WEXITSTATUS(status) != 0){ @@ -265,15 +315,32 @@ static int wanconfig_hwec_bypass(char *devname, chan_def_t *def, int enable) } static int -wanconfig_hwec_enable(char *devname, char *channel_list) +wanconfig_hwec_enable(char *devname, char *channel_list, uint8_t op_mode) { # if 1 wanec_api_opmode_t opmode; unsigned int fe_chan_map; + fe_chan_map = parse_active_channel(channel_list); memset(&opmode, 0, sizeof(wanec_api_opmode_t)); - opmode.mode = WANEC_API_OPMODE_NORMAL; + + switch (op_mode) { + + case WANOPT_OCT_CHAN_OPERMODE_NORMAL: + opmode.mode=WANEC_API_OPMODE_NORMAL; + break; + case WANOPT_OCT_CHAN_OPERMODE_SPEECH: + opmode.mode=WANEC_API_OPMODE_SPEECH_RECOGNITION; + break; + case WANOPT_OCT_CHAN_OPERMODE_NO_ECHO: + opmode.mode=WANEC_API_OPMODE_NO_ECHO; + break; + default: + opmode.mode=WANEC_API_OPMODE_NORMAL; + break; + } + opmode.fe_chan_map = fe_chan_map; return wanec_api_opmode(devname, 0, &opmode); # else @@ -295,7 +362,7 @@ wanconfig_hwec_tone(char *devname, int enable, int id, char *channel_list) wanec_api_tone_t tone; unsigned int fe_chan_map; int err; - + fe_chan_map = parse_active_channel(channel_list); memset(&tone, 0, sizeof(wanec_api_tone_t)); tone.id = id; diff --git a/util/wanctl/wanctl b/util/wanctl/wanctl deleted file mode 100755 index e1ac2ba..0000000 Binary files a/util/wanctl/wanctl and /dev/null differ diff --git a/util/wanec_apilib/wanec_api.c b/util/wanec_apilib/wanec_api.c index 1473782..9391c6d 100644 --- a/util/wanec_apilib/wanec_api.c +++ b/util/wanec_apilib/wanec_api.c @@ -1,11 +1,12 @@ /****************************************************************************** -** Copyright (c) 2005 -** Alex Feldman . All rights reserved. +** Copyright (c) 2005 Sangoma Technologies. All rights reserved. ** ** ============================================================================ -** Oct 13, 2005 Alex Feldman Initial version. +** May 12, 2010 David Rokhvarg added verbosity control (WANEC_API_PRINT()). ** ** Jul 26, 2006 David Rokhvarg Ported to Windows. +** +** Oct 13, 2005 Alex Feldman Initial version. ******************************************************************************/ /****************************************************************************** @@ -56,9 +57,15 @@ #include "wanec_api.h" + /****************************************************************************** ** DEFINES AND MACROS ******************************************************************************/ +#ifdef __WINDOWS__ +#define WANEC_API_PRINT(...) if(ec_library_verbose)printf(## __VA_ARGS__) +#else +#define WANEC_API_PRINT(...) if(ec_library_verbose)printf(__VA_ARGS__) +#endif /****************************************************************************** ** STRUCTURES AND TYPEDEFS @@ -69,6 +76,8 @@ ******************************************************************************/ wan_ec_api_t ec_api; +int ec_library_verbose = 1; /* by default, the library will print to stdout */ + /****************************************************************************** ** FUNCTION PROTOTYPES ******************************************************************************/ @@ -88,48 +97,48 @@ static int wanec_api_print_chip_stats(wan_ec_api_t *ec_api) tPOCT6100_CHIP_STATS pChipStats; pChipStats = &ec_api->u_chip_stats.f_ChipStats; - printf("****** Echo Canceller Chip Get Stats %s ******\n", + WANEC_API_PRINT("****** Echo Canceller Chip Get Stats %s ******\n", ec_api->devname); - printf("%10s: Number of channels currently open\t\t\t%d\n", + WANEC_API_PRINT("%10s: Number of channels currently open\t\t\t%d\n", ec_api->devname, pChipStats->ulNumberChannels); - printf("%10s: Number of conference bridges currently open\t\t%d\n", + WANEC_API_PRINT("%10s: Number of conference bridges currently open\t\t%d\n", ec_api->devname, pChipStats->ulNumberConfBridges); - printf("%10s: Number of playout buffers currently loaded\t\t%d\n", + WANEC_API_PRINT("%10s: Number of playout buffers currently loaded\t\t%d\n", ec_api->devname, pChipStats->ulNumberPlayoutBuffers); - printf("%10s: Number of framing error on H.100 bus\t\t%d\n", + WANEC_API_PRINT("%10s: Number of framing error on H.100 bus\t\t%d\n", ec_api->devname, pChipStats->ulH100OutOfSynchCount); - printf("%10s: Number of errors on H.100 clock CT_C8_A\t\t%d\n", + WANEC_API_PRINT("%10s: Number of errors on H.100 clock CT_C8_A\t\t%d\n", ec_api->devname, pChipStats->ulH100ClockABadCount); - printf("%10s: Number of errors on H.100 frame CT_FRAME_A\t\t%d\n", + WANEC_API_PRINT("%10s: Number of errors on H.100 frame CT_FRAME_A\t\t%d\n", ec_api->devname, pChipStats->ulH100FrameABadCount); - printf("%10s: Number of errors on H.100 clock CT_C8_B\t\t%d\n", + WANEC_API_PRINT("%10s: Number of errors on H.100 clock CT_C8_B\t\t%d\n", ec_api->devname, pChipStats->ulH100ClockBBadCount); - printf("%10s: Number of internal read timeout errors\t\t%d\n", + WANEC_API_PRINT("%10s: Number of internal read timeout errors\t\t%d\n", ec_api->devname, pChipStats->ulInternalReadTimeoutCount); - printf("%10s: Number of SDRAM refresh too late errors\t\t%d\n", + WANEC_API_PRINT("%10s: Number of SDRAM refresh too late errors\t\t%d\n", ec_api->devname, pChipStats->ulSdramRefreshTooLateCount); - printf("%10s: Number of PLL jitter errors\t\t\t\t%d\n", + WANEC_API_PRINT("%10s: Number of PLL jitter errors\t\t\t\t%d\n", ec_api->devname, pChipStats->ulPllJitterErrorCount); - printf("%10s: Number of HW tone event buffer has overflowed\t%d\n", + WANEC_API_PRINT("%10s: Number of HW tone event buffer has overflowed\t%d\n", ec_api->devname, pChipStats->ulOverflowToneEventsCount); - printf("%10s: Number of SW tone event buffer has overflowed\t%d\n", + WANEC_API_PRINT("%10s: Number of SW tone event buffer has overflowed\t%d\n", ec_api->devname, pChipStats->ulSoftOverflowToneEventsCount); - printf("%10s: Number of SW Playout event buffer has overflowed\t%d\n", + WANEC_API_PRINT("%10s: Number of SW Playout event buffer has overflowed\t%d\n", ec_api->devname, pChipStats->ulSoftOverflowBufferPlayoutEventsCount); - printf("\n"); + WANEC_API_PRINT("\n"); return 0; } @@ -139,52 +148,52 @@ static int wanec_api_print_full_chip_stats(wan_ec_api_t *ec_api) tPOCT6100_CHIP_STATS pChipStats; pChipStats = &ec_api->u_chip_stats.f_ChipStats; - printf("****** Echo Canceller Chip Get Stats %s ******\n", + WANEC_API_PRINT("****** Echo Canceller Chip Get Stats %s ******\n", ec_api->devname); - printf("%10s: Number of channels currently open\t\t\t%d\n", + WANEC_API_PRINT("%10s: Number of channels currently open\t\t\t%d\n", ec_api->devname, pChipStats->ulNumberChannels); - printf("%10s: Number of TSI connections currently open\t\t%d\n", + WANEC_API_PRINT("%10s: Number of TSI connections currently open\t\t%d\n", ec_api->devname, pChipStats->ulNumberTsiCncts); - printf("%10s: Number of conference bridges currently open\t\t%d\n", + WANEC_API_PRINT("%10s: Number of conference bridges currently open\t\t%d\n", ec_api->devname, pChipStats->ulNumberConfBridges); - printf("%10s: Number of playout buffers currently loaded\t\t%d\n", + WANEC_API_PRINT("%10s: Number of playout buffers currently loaded\t\t%d\n", ec_api->devname, pChipStats->ulNumberPlayoutBuffers); - printf("%10s: Number of framing error on H.100 bus\t\t%d\n", + WANEC_API_PRINT("%10s: Number of framing error on H.100 bus\t\t%d\n", ec_api->devname, pChipStats->ulH100OutOfSynchCount); - printf("%10s: Number of errors on H.100 clock CT_C8_A\t\t%d\n", + WANEC_API_PRINT("%10s: Number of errors on H.100 clock CT_C8_A\t\t%d\n", ec_api->devname, pChipStats->ulH100ClockABadCount); - printf("%10s: Number of errors on H.100 frame CT_FRAME_A\t\t%d\n", + WANEC_API_PRINT("%10s: Number of errors on H.100 frame CT_FRAME_A\t\t%d\n", ec_api->devname, pChipStats->ulH100FrameABadCount); - printf("%10s: Number of errors on H.100 clock CT_C8_B\t\t%d\n", + WANEC_API_PRINT("%10s: Number of errors on H.100 clock CT_C8_B\t\t%d\n", ec_api->devname, pChipStats->ulH100ClockBBadCount); - printf("%10s: Number of internal read timeout errors\t\t%d\n", + WANEC_API_PRINT("%10s: Number of internal read timeout errors\t\t%d\n", ec_api->devname, pChipStats->ulInternalReadTimeoutCount); - printf("%10s: Number of SDRAM refresh too late errors\t\t%d\n", + WANEC_API_PRINT("%10s: Number of SDRAM refresh too late errors\t\t%d\n", ec_api->devname, pChipStats->ulSdramRefreshTooLateCount); - printf("%10s: Number of PLL jitter errors\t\t\t\t%d\n", + WANEC_API_PRINT("%10s: Number of PLL jitter errors\t\t\t\t%d\n", ec_api->devname, pChipStats->ulPllJitterErrorCount); - printf("%10s: Number of HW tone event buffer has overflowed\t%d\n", + WANEC_API_PRINT("%10s: Number of HW tone event buffer has overflowed\t%d\n", ec_api->devname, pChipStats->ulOverflowToneEventsCount); - printf("%10s: Number of SW tone event buffer has overflowed\t%d\n", + WANEC_API_PRINT("%10s: Number of SW tone event buffer has overflowed\t%d\n", ec_api->devname, pChipStats->ulSoftOverflowToneEventsCount); - printf("%10s: Number of SW Playout event buffer has overflowed\t%d\n", + WANEC_API_PRINT("%10s: Number of SW Playout event buffer has overflowed\t%d\n", ec_api->devname, pChipStats->ulSoftOverflowBufferPlayoutEventsCount); - printf("\n"); + WANEC_API_PRINT("\n"); return 0; } @@ -197,50 +206,50 @@ static int wanec_api_print_chip_image(wan_ec_api_t *ec_api, int full) if (ec_api->u_chip_image.f_ChipImageInfo){ pChipImageInfo = ec_api->u_chip_image.f_ChipImageInfo; - printf("****** Echo Canceller Chip Image Info %s ******\n", + WANEC_API_PRINT("****** Echo Canceller Chip Image Info %s ******\n", ec_api->devname); - printf("%10s: Echo Canceller chip image build description:\n%s\n", + WANEC_API_PRINT("%10s: Echo Canceller chip image build description:\n%s\n", ec_api->devname, pChipImageInfo->szVersionNumber); - printf("%10s: Echo Canceller chip build ID\t\t\t%d\n", + WANEC_API_PRINT("%10s: Echo Canceller chip build ID\t\t\t%d\n", ec_api->devname, pChipImageInfo->ulBuildId); - printf("%10s: Echo Canceller image type\t\t\t\t%d\n", + WANEC_API_PRINT("%10s: Echo Canceller image type\t\t\t\t%d\n", ec_api->devname, pChipImageInfo->ulImageType); - printf("%10s: Maximum number of channels supported by the image\t%d\n", + WANEC_API_PRINT("%10s: Maximum number of channels supported by the image\t%d\n", ec_api->devname, pChipImageInfo->ulMaxChannels); - if (full) printf("%10s: Support Acoustic echo cancellation\t%s\n", + if (full) WANEC_API_PRINT("%10s: Support Acoustic echo cancellation\t%s\n", ec_api->devname, (pChipImageInfo->fAcousticEcho == TRUE) ? "TRUE" : "FALSE"); - if (full) printf("%10s: Support configurable tail length for Aec\t%s\n", + if (full) WANEC_API_PRINT("%10s: Support configurable tail length for Aec\t%s\n", ec_api->devname, (pChipImageInfo->fAecTailLength == TRUE) ? "TRUE" : "FALSE"); - if (full) printf("%10s: Support configurable default ERL\t%s\n", + if (full) WANEC_API_PRINT("%10s: Support configurable default ERL\t%s\n", ec_api->devname, (pChipImageInfo->fDefaultErl == TRUE) ? "TRUE" : "FALSE"); - if (full) printf("%10s: Support configurable non-linearity A\t%s\n", + if (full) WANEC_API_PRINT("%10s: Support configurable non-linearity A\t%s\n", ec_api->devname, (pChipImageInfo->fNonLinearityBehaviorA == TRUE) ? "TRUE" : "FALSE"); - if (full) printf("%10s: Support configurable non-linearity B\t%s\n", + if (full) WANEC_API_PRINT("%10s: Support configurable non-linearity B\t%s\n", ec_api->devname, (pChipImageInfo->fNonLinearityBehaviorB == TRUE) ? "TRUE" : "FALSE"); - if (full) printf("%10s: Tone profile number built in the image\t%d\n", + if (full) WANEC_API_PRINT("%10s: Tone profile number built in the image\t%d\n", ec_api->devname, pChipImageInfo->ulToneProfileNumber); - if (full) printf("%10s: Number of tone available in the image\t%d\n", + if (full) WANEC_API_PRINT("%10s: Number of tone available in the image\t%d\n", ec_api->devname, pChipImageInfo->ulNumTonesAvailable); if (full) { for(i = 0; i < pChipImageInfo->ulNumTonesAvailable; i++){ pChipToneInfo = &pChipImageInfo->aToneInfo[i]; - printf("%10s: \tDetection Port: %s\tToneId: 0x%X\n", + WANEC_API_PRINT("%10s: \tDetection Port: %s\tToneId: 0x%X\n", ec_api->devname, (pChipToneInfo->ulDetectionPort == cOCT6100_CHANNEL_PORT_SIN)?"SIN": (pChipToneInfo->ulDetectionPort == cOCT6100_CHANNEL_PORT_ROUT)?"ROUT": @@ -249,7 +258,7 @@ static int wanec_api_print_chip_image(wan_ec_api_t *ec_api, int full) "INV", pChipToneInfo->ulToneID); } - printf("\n"); + WANEC_API_PRINT("\n"); } } return 0; @@ -263,7 +272,7 @@ static int wanec_api_print_chan_stats(wan_ec_api_t *ec_api, int fe_chan) tPOCT6100_CHANNEL_STATS_VQE pChannelStatsVqe; pChannelStats = (tPOCT6100_CHANNEL_STATS)&ec_api->u_chan_stats.f_ChannelStats; - printf("%10s:%2d: Echo Channel Operation Mode\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: Echo Channel Operation Mode\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStats->ulEchoOperationMode==cOCT6100_ECHO_OP_MODE_NORMAL)? @@ -279,10 +288,10 @@ static int wanec_api_print_chan_stats(wan_ec_api_t *ec_api, int fe_chan) (pChannelStats->ulEchoOperationMode==cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION)? "SPEECH RECOGNITION": "Unknown"); - printf("%10s:%2d: Enable Tone Disabler\t\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: Enable Tone Disabler\t\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStats->fEnableToneDisabler==TRUE) ? "TRUE" : "FALSE"); - printf("%10s:%2d: Mute Ports\t\t\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: Mute Ports\t\t\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStats->ulMutePortsMask==cOCT6100_CHANNEL_MUTE_PORT_RIN) ? "RIN" : @@ -294,152 +303,152 @@ static int wanec_api_print_chan_stats(wan_ec_api_t *ec_api, int fe_chan) "SOUT" : (pChannelStats->ulMutePortsMask==cOCT6100_CHANNEL_MUTE_PORT_NONE) ? "NONE" : "Unknown"); - printf("%10s:%2d: Enable Extended Tone Detection\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: Enable Extended Tone Detection\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStats->fEnableExtToneDetection==TRUE) ? "TRUE" : "FALSE"); if (pChannelStats->ulToneDisablerStatus == cOCT6100_INVALID_STAT){ - printf("%10s:%2d: Tone Disabler Status\t\t\t\t: Invalid\n", + WANEC_API_PRINT("%10s:%2d: Tone Disabler Status\t\t\t\t: Invalid\n", ec_api->devname, fe_chan); }else{ - printf("%10s:%2d: Tone Disabler Status\t\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: Tone Disabler Status\t\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStats->ulToneDisablerStatus==cOCT6100_TONE_DISABLER_EC_DISABLED)? "Disabled":"Enabled"); } - printf("%10s:%2d: Voice activity is detected on SIN port\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: Voice activity is detected on SIN port\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStats->fSinVoiceDetected==TRUE)? "TRUE": (pChannelStats->fSinVoiceDetected==FALSE)? "FALSE": "Unknown"); - printf("%10s:%2d: Echo canceller has detected and converged\t: %s\n", + WANEC_API_PRINT("%10s:%2d: Echo canceller has detected and converged\t: %s\n", ec_api->devname, fe_chan, (pChannelStats->fEchoCancellerConverged==TRUE)? "TRUE": (pChannelStats->fEchoCancellerConverged==FALSE)? "FALSE": "Unknown"); if (pChannelStats->lRinLevel == cOCT6100_INVALID_SIGNED_STAT){ - printf("%10s:%2d: Average power of signal level on RIN\t\t: Invalid\n", + WANEC_API_PRINT("%10s:%2d: Average power of signal level on RIN\t\t: Invalid\n", ec_api->devname, fe_chan); }else{ - printf("%10s:%2d: Average power of signal level on RIN\t\t: %d dBm0\n", + WANEC_API_PRINT("%10s:%2d: Average power of signal level on RIN\t\t: %d dBm0\n", ec_api->devname, fe_chan, pChannelStats->lRinLevel); } if (pChannelStats->lSinLevel == cOCT6100_INVALID_SIGNED_STAT){ - printf("%10s:%2d: Average power of signal level on SIN\t\t: Invalid\n", + WANEC_API_PRINT("%10s:%2d: Average power of signal level on SIN\t\t: Invalid\n", ec_api->devname, fe_chan); }else{ - printf("%10s:%2d: Average power of signal level on SIN\t\t: %d dBm0\n", + WANEC_API_PRINT("%10s:%2d: Average power of signal level on SIN\t\t: %d dBm0\n", ec_api->devname, fe_chan, pChannelStats->lSinLevel); } if (pChannelStats->lRinAppliedGain == cOCT6100_INVALID_SIGNED_STAT){ - printf("%10s:%2d: Current gain applied to signal level on RIN\t: Invalid\n", + WANEC_API_PRINT("%10s:%2d: Current gain applied to signal level on RIN\t: Invalid\n", ec_api->devname, fe_chan); }else{ - printf("%10s:%2d: Current gain applied to signal level on RIN\t: %d dB\n", + WANEC_API_PRINT("%10s:%2d: Current gain applied to signal level on RIN\t: %d dB\n", ec_api->devname, fe_chan, pChannelStats->lRinAppliedGain); } if (pChannelStats->lSoutAppliedGain == cOCT6100_INVALID_SIGNED_STAT){ - printf("%10s:%2d: Current gain applied to signal level on SOUT\t: Invalid\n", + WANEC_API_PRINT("%10s:%2d: Current gain applied to signal level on SOUT\t: Invalid\n", ec_api->devname, fe_chan); }else{ - printf("%10s:%2d: Current gain applied to signal level on SOUT\t: %d dB\n", + WANEC_API_PRINT("%10s:%2d: Current gain applied to signal level on SOUT\t: %d dB\n", ec_api->devname, fe_chan, pChannelStats->lSoutAppliedGain); } if (pChannelStats->lComfortNoiseLevel == cOCT6100_INVALID_SIGNED_STAT){ - printf("%10s:%2d: Average power of the comfort noise injected\t: Invalid\n", + WANEC_API_PRINT("%10s:%2d: Average power of the comfort noise injected\t: Invalid\n", ec_api->devname, fe_chan); }else{ - printf("%10s:%2d: Average power of the comfort noise injected\t: %d dBm0\n", + WANEC_API_PRINT("%10s:%2d: Average power of the comfort noise injected\t: %d dBm0\n", ec_api->devname, fe_chan, pChannelStats->lComfortNoiseLevel); } pChannelStatsTdm = &pChannelStats->TdmConfig; - printf("%10s:%2d: (TDM) PCM Law type on SIN\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (TDM) PCM Law type on SIN\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsTdm->ulSinPcmLaw == cOCT6100_PCM_U_LAW) ? "ULAW" : "ALAW"); - printf("%10s:%2d: (TDM) TDM timeslot on SIN port\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (TDM) TDM timeslot on SIN port\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStatsTdm->ulSinTimeslot); - printf("%10s:%2d: (TDM) TDM stream on SIN port\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (TDM) TDM stream on SIN port\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStatsTdm->ulSinStream); - printf("%10s:%2d: (TDM) PCM Law type on RIN\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (TDM) PCM Law type on RIN\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsTdm->ulRinPcmLaw == cOCT6100_PCM_U_LAW) ? "ULAW" : "ALAW"); - printf("%10s:%2d: (TDM) TDM timeslot on RIN port\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (TDM) TDM timeslot on RIN port\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStatsTdm->ulRinTimeslot); - printf("%10s:%2d: (TDM) TDM stream on RIN port\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (TDM) TDM stream on RIN port\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStatsTdm->ulRinStream); - printf("%10s:%2d: (TDM) PCM Law type on SOUT\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (TDM) PCM Law type on SOUT\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsTdm->ulSoutPcmLaw == cOCT6100_PCM_U_LAW) ? "ULAW" : "ALAW"); - printf("%10s:%2d: (TDM) TDM timeslot on SOUT port\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (TDM) TDM timeslot on SOUT port\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStatsTdm->ulSoutTimeslot); - printf("%10s:%2d: (TDM) TDM stream on SOUT port\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (TDM) TDM stream on SOUT port\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStatsTdm->ulSoutStream); - printf("%10s:%2d: (TDM) PCM Law type on ROUT\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (TDM) PCM Law type on ROUT\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsTdm->ulRoutPcmLaw == cOCT6100_PCM_U_LAW) ? "ULAW" : "ALAW"); - printf("%10s:%2d: (TDM) TDM timeslot on ROUT port\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (TDM) TDM timeslot on ROUT port\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStatsTdm->ulRoutTimeslot); - printf("%10s:%2d: (TDM) TDM stream on ROUT port\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (TDM) TDM stream on ROUT port\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStatsTdm->ulRoutStream); pChannelStatsVqe = &pChannelStats->VqeConfig; - printf("%10s:%2d: (VQE) NLP status\t\t\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (VQE) NLP status\t\t\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsVqe->fEnableNlp == TRUE) ? "TRUE" : "FALSE"); - printf("%10s:%2d: (VQE) Tail Displacement Status\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Tail Displacement Status\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsVqe->fEnableTailDisplacement == TRUE) ? "TRUE" : "FALSE"); - printf("%10s:%2d: (VQE) Tail Displacement (ms)\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Tail Displacement (ms)\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStatsVqe->ulTailDisplacement); - printf("%10s:%2d: (VQE) Tail Length (ms)\t\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Tail Length (ms)\t\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStatsVqe->ulTailLength); - printf("%10s:%2d: (VQE) Comfort noise mode\t\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Comfort noise mode\t\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsVqe->ulComfortNoiseMode == cOCT6100_COMFORT_NOISE_NORMAL) ? "NORMAL" : (pChannelStatsVqe->ulComfortNoiseMode == cOCT6100_COMFORT_NOISE_FAST_LATCH) ? "FAST LATCH" : (pChannelStatsVqe->ulComfortNoiseMode == cOCT6100_COMFORT_NOISE_EXTENDED) ? "EXTENDED" : (pChannelStatsVqe->ulComfortNoiseMode == cOCT6100_COMFORT_NOISE_OFF) ? "OFF" : "UNKNOWN"); - printf("%10s:%2d: (VQE) Acoustic Echo\t\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Acoustic Echo\t\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsVqe->fAcousticEcho == TRUE) ? "TRUE" : "FALSE"); - printf("%10s:%2d: (VQE) Out Automatic Level Control\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Out Automatic Level Control\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsVqe->fRinAutomaticLevelControl == TRUE) ? "TRUE" : "FALSE"); - printf("%10s:%2d: (VQE) Out Automatic Level Control Target\t\t: %d dB\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Out Automatic Level Control Target\t\t: %d dB\n", ec_api->devname, fe_chan, pChannelStatsVqe->lRinAutomaticLevelControlTargetDb); - printf("%10s:%2d: (VQE) In Automatic Level Control\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (VQE) In Automatic Level Control\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsVqe->fSoutAutomaticLevelControl == TRUE) ? "TRUE" : "FALSE"); - printf("%10s:%2d: (VQE) In Automatic Level Control Target\t\t: %d dB\n", + WANEC_API_PRINT("%10s:%2d: (VQE) In Automatic Level Control Target\t\t: %d dB\n", ec_api->devname, fe_chan, pChannelStatsVqe->lSoutAutomaticLevelControlTargetDb); - printf("%10s:%2d: (VQE) Noise Reduction\t\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Noise Reduction\t\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsVqe->fSoutAdaptiveNoiseReduction == TRUE) ? "TRUE" : "FALSE"); - printf("%10s:%2d: (VQE) Tone Removal\t\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Tone Removal\t\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsVqe->fDtmfToneRemoval == TRUE) ? "TRUE" : "FALSE"); - printf("%10s:%2d: (VQE) Activation Delay (ms)\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Activation Delay (ms)\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStatsVqe->ulToneDisablerVqeActivationDelay); - printf("\n"); + WANEC_API_PRINT("\n"); return 0; } @@ -452,7 +461,7 @@ static int wanec_api_print_full_chan_stats(wan_ec_api_t *ec_api, int fe_chan) tPOCT6100_CHANNEL_STATS_CODEC pChannelStatsCodec; pChannelStats = (tPOCT6100_CHANNEL_STATS)&ec_api->u_chan_stats.f_ChannelStats; - printf("%10s:%2d: Echo Channel Operation Mode\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: Echo Channel Operation Mode\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStats->ulEchoOperationMode==cOCT6100_ECHO_OP_MODE_NORMAL)? @@ -468,10 +477,10 @@ static int wanec_api_print_full_chan_stats(wan_ec_api_t *ec_api, int fe_chan) (pChannelStats->ulEchoOperationMode==cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION)? "SPEECH RECOGNITION": "Unknown"); - printf("%10s:%2d: Enable Tone Disabler\t\t\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: Enable Tone Disabler\t\t\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStats->fEnableToneDisabler==TRUE) ? "TRUE" : "FALSE"); - printf("%10s:%2d: Mute Ports\t\t\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: Mute Ports\t\t\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStats->ulMutePortsMask==cOCT6100_CHANNEL_MUTE_PORT_RIN) ? "RIN" : @@ -483,243 +492,243 @@ static int wanec_api_print_full_chan_stats(wan_ec_api_t *ec_api, int fe_chan) "SOUT" : (pChannelStats->ulMutePortsMask==cOCT6100_CHANNEL_MUTE_PORT_NONE) ? "NONE" : "Unknown"); - printf("%10s:%2d: Enable Extended Tone Detection\t\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: Enable Extended Tone Detection\t\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStats->fEnableExtToneDetection==TRUE) ? "TRUE" : "FALSE"); if (pChannelStats->lCurrentERL == cOCT6100_INVALID_SIGNED_STAT){ - printf("%10s:%2d: Current Echo Return Loss\t\t\t\t: Invalid\n", + WANEC_API_PRINT("%10s:%2d: Current Echo Return Loss\t\t\t\t: Invalid\n", ec_api->devname, fe_chan); }else{ - printf("%10s:%2d: Current Echo Return Loss\t\t\t\t: %d dB\n", + WANEC_API_PRINT("%10s:%2d: Current Echo Return Loss\t\t\t\t: %d dB\n", ec_api->devname, fe_chan, pChannelStats->lCurrentERL); } if (pChannelStats->lCurrentERLE == cOCT6100_INVALID_SIGNED_STAT){ - printf("%10s:%2d: Current Echo Return Loss Enhancement\t\t: Invalid\n", + WANEC_API_PRINT("%10s:%2d: Current Echo Return Loss Enhancement\t\t: Invalid\n", ec_api->devname, fe_chan); }else{ - printf("%10s:%2d: Current Echo Return Loss Enhancement\t\t: %d dB\n", + WANEC_API_PRINT("%10s:%2d: Current Echo Return Loss Enhancement\t\t: %d dB\n", ec_api->devname, fe_chan, pChannelStats->lCurrentERLE); } if (pChannelStats->lMaxERL == cOCT6100_INVALID_SIGNED_STAT){ - printf("%10s:%2d: Maximum value of the ERL\t\t\t\t: Invalid\n", + WANEC_API_PRINT("%10s:%2d: Maximum value of the ERL\t\t\t\t: Invalid\n", ec_api->devname, fe_chan); }else{ - printf("%10s:%2d: Maximum value of the ERL\t\t\t\t: %d dB\n", + WANEC_API_PRINT("%10s:%2d: Maximum value of the ERL\t\t\t\t: %d dB\n", ec_api->devname, fe_chan, pChannelStats->lMaxERL); } if (pChannelStats->lMaxERLE == cOCT6100_INVALID_SIGNED_STAT){ - printf("%10s:%2d: Maximum value of the ERLE\t\t\t: Invalid\n", + WANEC_API_PRINT("%10s:%2d: Maximum value of the ERLE\t\t\t: Invalid\n", ec_api->devname, fe_chan); }else{ - printf("%10s:%2d: Maximum value of the ERLE\t\t\t: %d dB\n", + WANEC_API_PRINT("%10s:%2d: Maximum value of the ERLE\t\t\t: %d dB\n", ec_api->devname, fe_chan, pChannelStats->lMaxERLE); } if (pChannelStats->ulNumEchoPathChanges == cOCT6100_INVALID_STAT){ - printf("%10s:%2d: Number of Echo Path changes\t\t\t: Invalid\n", + WANEC_API_PRINT("%10s:%2d: Number of Echo Path changes\t\t\t: Invalid\n", ec_api->devname, fe_chan); }else{ - printf("%10s:%2d: Number of Echo Path changes\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: Number of Echo Path changes\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStats->ulNumEchoPathChanges); } if (pChannelStats->ulCurrentEchoDelay == cOCT6100_INVALID_STAT){ - printf("%10s:%2d: Current Echo Delay\t\t\t\t: Invalid\n", + WANEC_API_PRINT("%10s:%2d: Current Echo Delay\t\t\t\t: Invalid\n", ec_api->devname, fe_chan); }else{ - printf("%10s:%2d: Current Echo Delay\t\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: Current Echo Delay\t\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStats->ulCurrentEchoDelay); } if (pChannelStats->ulMaxEchoDelay == cOCT6100_INVALID_STAT){ - printf("%10s:%2d: Maximum Echo Delay\t\t\t\t: Invalid\n", + WANEC_API_PRINT("%10s:%2d: Maximum Echo Delay\t\t\t\t: Invalid\n", ec_api->devname, fe_chan); }else{ - printf("%10s:%2d: Maximum Echo Delay\t\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: Maximum Echo Delay\t\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStats->ulMaxEchoDelay); } if (pChannelStats->ulToneDisablerStatus == cOCT6100_INVALID_STAT){ - printf("%10s:%2d: Tone Disabler Status\t\t\t\t: Invalid\n", + WANEC_API_PRINT("%10s:%2d: Tone Disabler Status\t\t\t\t: Invalid\n", ec_api->devname, fe_chan); }else{ - printf("%10s:%2d: Tone Disabler Status\t\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: Tone Disabler Status\t\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStats->ulToneDisablerStatus==cOCT6100_TONE_DISABLER_EC_DISABLED)? "Disabled":"Enabled"); } - printf("%10s:%2d: Voice activity is detected on SIN port\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: Voice activity is detected on SIN port\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStats->fSinVoiceDetected==TRUE)? "TRUE": (pChannelStats->fSinVoiceDetected==FALSE)? "FALSE": "Unknown"); - printf("%10s:%2d: Echo canceller has detected and converged\t: %s\n", + WANEC_API_PRINT("%10s:%2d: Echo canceller has detected and converged\t: %s\n", ec_api->devname, fe_chan, (pChannelStats->fEchoCancellerConverged==TRUE)? "TRUE": (pChannelStats->fEchoCancellerConverged==FALSE)? "FALSE": "Unknown"); if (pChannelStats->lRinLevel == cOCT6100_INVALID_SIGNED_STAT){ - printf("%10s:%2d: Average power of signal level on RIN\t\t: Invalid\n", + WANEC_API_PRINT("%10s:%2d: Average power of signal level on RIN\t\t: Invalid\n", ec_api->devname, fe_chan); }else{ - printf("%10s:%2d: Average power of signal level on RIN\t\t: %d dBm0\n", + WANEC_API_PRINT("%10s:%2d: Average power of signal level on RIN\t\t: %d dBm0\n", ec_api->devname, fe_chan, pChannelStats->lRinLevel); } if (pChannelStats->lSinLevel == cOCT6100_INVALID_SIGNED_STAT){ - printf("%10s:%2d: Average power of signal level on SIN\t\t: Invalid\n", + WANEC_API_PRINT("%10s:%2d: Average power of signal level on SIN\t\t: Invalid\n", ec_api->devname, fe_chan); }else{ - printf("%10s:%2d: Average power of signal level on SIN\t\t: %d dBm0\n", + WANEC_API_PRINT("%10s:%2d: Average power of signal level on SIN\t\t: %d dBm0\n", ec_api->devname, fe_chan, pChannelStats->lSinLevel); } if (pChannelStats->lRinAppliedGain == cOCT6100_INVALID_SIGNED_STAT){ - printf("%10s:%2d: Current gain applied to signal level on RIN\t: Invalid\n", + WANEC_API_PRINT("%10s:%2d: Current gain applied to signal level on RIN\t: Invalid\n", ec_api->devname, fe_chan); }else{ - printf("%10s:%2d: Current gain applied to signal level on RIN\t: %d dB\n", + WANEC_API_PRINT("%10s:%2d: Current gain applied to signal level on RIN\t: %d dB\n", ec_api->devname, fe_chan, pChannelStats->lRinAppliedGain); } if (pChannelStats->lSoutAppliedGain == cOCT6100_INVALID_SIGNED_STAT){ - printf("%10s:%2d: Current gain applied to signal level on SOUT\t: Invalid\n", + WANEC_API_PRINT("%10s:%2d: Current gain applied to signal level on SOUT\t: Invalid\n", ec_api->devname, fe_chan); }else{ - printf("%10s:%2d: Current gain applied to signal level on SOUT\t: %d dB\n", + WANEC_API_PRINT("%10s:%2d: Current gain applied to signal level on SOUT\t: %d dB\n", ec_api->devname, fe_chan, pChannelStats->lSoutAppliedGain); } if (pChannelStats->lComfortNoiseLevel == cOCT6100_INVALID_SIGNED_STAT){ - printf("%10s:%2d: Average power of the comfort noise injected\t: Invalid\n", + WANEC_API_PRINT("%10s:%2d: Average power of the comfort noise injected\t: Invalid\n", ec_api->devname, fe_chan); }else{ - printf("%10s:%2d: Average power of the comfort noise injected\t: %d dBm0\n", + WANEC_API_PRINT("%10s:%2d: Average power of the comfort noise injected\t: %d dBm0\n", ec_api->devname, fe_chan, pChannelStats->lComfortNoiseLevel); } pChannelStatsTdm = &pChannelStats->TdmConfig; - printf("%10s:%2d: (TDM) PCM Law type on SIN\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (TDM) PCM Law type on SIN\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsTdm->ulSinPcmLaw == cOCT6100_PCM_U_LAW) ? "ULAW" : "ALAW"); - printf("%10s:%2d: (TDM) TDM timeslot on SIN port\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (TDM) TDM timeslot on SIN port\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStatsTdm->ulSinTimeslot); - printf("%10s:%2d: (TDM) TDM stream on SIN port\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (TDM) TDM stream on SIN port\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStatsTdm->ulSinStream); - printf("%10s:%2d: (TDM) PCM Law type on RIN\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (TDM) PCM Law type on RIN\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsTdm->ulRinPcmLaw == cOCT6100_PCM_U_LAW) ? "ULAW" : "ALAW"); - printf("%10s:%2d: (TDM) TDM timeslot on RIN port\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (TDM) TDM timeslot on RIN port\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStatsTdm->ulRinTimeslot); - printf("%10s:%2d: (TDM) TDM stream on RIN port\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (TDM) TDM stream on RIN port\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStatsTdm->ulRinStream); - printf("%10s:%2d: (TDM) PCM Law type on SOUT\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (TDM) PCM Law type on SOUT\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsTdm->ulSoutPcmLaw == cOCT6100_PCM_U_LAW) ? "ULAW" : "ALAW"); - printf("%10s:%2d: (TDM) TDM timeslot on SOUT port\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (TDM) TDM timeslot on SOUT port\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStatsTdm->ulSoutTimeslot); - printf("%10s:%2d: (TDM) TDM stream on SOUT port\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (TDM) TDM stream on SOUT port\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStatsTdm->ulSoutStream); - printf("%10s:%2d: (TDM) PCM Law type on ROUT\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (TDM) PCM Law type on ROUT\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsTdm->ulRoutPcmLaw == cOCT6100_PCM_U_LAW) ? "ULAW" : "ALAW"); - printf("%10s:%2d: (TDM) TDM timeslot on ROUT port\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (TDM) TDM timeslot on ROUT port\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStatsTdm->ulRoutTimeslot); - printf("%10s:%2d: (TDM) TDM stream on ROUT port\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (TDM) TDM stream on ROUT port\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStatsTdm->ulRoutStream); pChannelStatsVqe = &pChannelStats->VqeConfig; - printf("%10s:%2d: (VQE) NLP status\t\t\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (VQE) NLP status\t\t\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsVqe->fEnableNlp == TRUE) ? "TRUE" : "FALSE"); - printf("%10s:%2d: (VQE) Enable Tail Displacement\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Enable Tail Displacement\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsVqe->fEnableTailDisplacement == TRUE) ? "TRUE" : "FALSE"); - printf("%10s:%2d: (VQE) Offset of the Echo Cancellation window (ms)\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Offset of the Echo Cancellation window (ms)\t: %d\n", ec_api->devname, fe_chan, pChannelStatsVqe->ulTailDisplacement); - printf("%10s:%2d: (VQE) Maximum tail length\t\t\t: %d ms\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Maximum tail length\t\t\t: %d ms\n", ec_api->devname, fe_chan, pChannelStatsVqe->ulTailLength); - printf("%10s:%2d: (VQE) Rin Level control mode\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Rin Level control mode\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsVqe->fRinLevelControl == TRUE) ? "Enable" : "TRUE"); - printf("%10s:%2d: (VQE) Rin Control Signal gain\t\t\t: %d dB\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Rin Control Signal gain\t\t\t: %d dB\n", ec_api->devname, fe_chan, pChannelStatsVqe->lRinLevelControlGainDb); - printf("%10s:%2d: (VQE) Sout Level control mode\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Sout Level control mode\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsVqe->fSoutLevelControl == TRUE) ? "Enable" : "TRUE"); - printf("%10s:%2d: (VQE) Sout Control Signal gain\t\t\t: %d dB\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Sout Control Signal gain\t\t\t: %d dB\n", ec_api->devname, fe_chan, pChannelStatsVqe->lSoutLevelControlGainDb); - printf("%10s:%2d: (VQE) RIN Automatic Level Control\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (VQE) RIN Automatic Level Control\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsVqe->fRinAutomaticLevelControl == TRUE) ? "TRUE" : "FALSE"); - printf("%10s:%2d: (VQE) RIN Target Level Control\t\t\t: %d dBm0\n", + WANEC_API_PRINT("%10s:%2d: (VQE) RIN Target Level Control\t\t\t: %d dBm0\n", ec_api->devname, fe_chan, pChannelStatsVqe->lRinAutomaticLevelControlTargetDb); - printf("%10s:%2d: (VQE) SOUT Automatic Level Control\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (VQE) SOUT Automatic Level Control\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsVqe->fSoutAutomaticLevelControl == TRUE) ? "TRUE" : "FALSE"); - printf("%10s:%2d: (VQE) SOUT Target Level Control\t\t\t: %d dBm0\n", + WANEC_API_PRINT("%10s:%2d: (VQE) SOUT Target Level Control\t\t\t: %d dBm0\n", ec_api->devname, fe_chan, pChannelStatsVqe->lSoutAutomaticLevelControlTargetDb); - printf("%10s:%2d: (VQE) Comfort noise mode\t\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Comfort noise mode\t\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsVqe->ulComfortNoiseMode == cOCT6100_COMFORT_NOISE_NORMAL) ? "NORMAL" : (pChannelStatsVqe->ulComfortNoiseMode == cOCT6100_COMFORT_NOISE_FAST_LATCH) ? "FAST LATCH" : (pChannelStatsVqe->ulComfortNoiseMode == cOCT6100_COMFORT_NOISE_EXTENDED) ? "EXTENDED" : (pChannelStatsVqe->ulComfortNoiseMode == cOCT6100_COMFORT_NOISE_OFF) ? "OFF" : "UNKNOWN"); - printf("%10s:%2d: (VQE) Remove any DTMF tone detection on SIN port\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Remove any DTMF tone detection on SIN port\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsVqe->fDtmfToneRemoval == TRUE) ? "TRUE" : "FALSE"); - printf("%10s:%2d: (VQE) Acoustic Echo\t\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Acoustic Echo\t\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsVqe->fAcousticEcho == TRUE) ? "TRUE" : "FALSE"); - printf("%10s:%2d: (VQE) Non Linearity Behavior A\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Non Linearity Behavior A\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStatsVqe->ulNonLinearityBehaviorA); - printf("%10s:%2d: (VQE) Non Linearity Behavior B\t\t\t: %d\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Non Linearity Behavior B\t\t\t: %d\n", ec_api->devname, fe_chan, pChannelStatsVqe->ulNonLinearityBehaviorB); - printf("%10s:%2d: (VQE) Double Talk algorithm\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Double Talk algorithm\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsVqe->ulDoubleTalkBehavior==cOCT6100_DOUBLE_TALK_BEH_NORMAL)?"NORMAL": "LESS AGGRESSIVE"); - printf("%10s:%2d: (VQE) Default ERL (not converged)\t\t: %d dB\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Default ERL (not converged)\t\t: %d dB\n", ec_api->devname, fe_chan, pChannelStatsVqe->lDefaultErlDb); - printf("%10s:%2d: (VQE) Acoustic Echo Cancellation default ERL\t: %d dB\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Acoustic Echo Cancellation default ERL\t: %d dB\n", ec_api->devname, fe_chan, pChannelStatsVqe->lAecDefaultErlDb); - printf("%10s:%2d: (VQE) Maximum Acoustic Echo tail length\t\t: %d ms\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Maximum Acoustic Echo tail length\t\t: %d ms\n", ec_api->devname, fe_chan, pChannelStatsVqe->ulAecTailLength); - printf("%10s:%2d: (VQE) Attenuation Level applied to the noise signal\t: %d dB\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Attenuation Level applied to the noise signal\t: %d dB\n", ec_api->devname, fe_chan, pChannelStatsVqe->lAnrSnrEnhancementDb); - printf("%10s:%2d: (VQE) Silence period before the re-activation of VQE features\t: %d ms\n", + WANEC_API_PRINT("%10s:%2d: (VQE) Silence period before the re-activation of VQE features\t: %d ms\n", ec_api->devname, fe_chan, pChannelStatsVqe->ulToneDisablerVqeActivationDelay); pChannelStatsCodec = &pChannelStats->CodecConfig; - printf("%10s:%2d: (CODEC) Encoder channel port\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (CODEC) Encoder channel port\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsCodec->ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT) ? "ROUT": (pChannelStatsCodec->ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT) ? "SOUT":"NO ENCODING"); - printf("%10s:%2d: (CODEC) Encoder rate\t\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (CODEC) Encoder rate\t\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsCodec->ulEncodingRate == cOCT6100_G711_64KBPS) ? "G.711 64 kBps": (pChannelStatsCodec->ulEncodingRate == cOCT6100_G726_40KBPS) ? "G.726 40 kBps": @@ -736,11 +745,11 @@ static int wanec_api_print_full_chan_stats(wan_ec_api_t *ec_api, int fe_chan) (pChannelStatsCodec->ulEncodingRate == cOCT6100_G727_24KBPS_2_1) ? "G.727 24 kBps (2:1)": (pChannelStatsCodec->ulEncodingRate == cOCT6100_G727_16KBPS_2_0) ? "G.727 16 kBps (2:0)": "UNKNOWN"); - printf("%10s:%2d: (CODEC) Decoder channel port\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (CODEC) Decoder channel port\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsCodec->ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN) ? "RIN": (pChannelStatsCodec->ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN) ? "SIN":"NO DECODING"); - printf("%10s:%2d: (CODEC) Decoder rate\t\t\t\t: %s\n", + WANEC_API_PRINT("%10s:%2d: (CODEC) Decoder rate\t\t\t\t: %s\n", ec_api->devname, fe_chan, (pChannelStatsCodec->ulDecodingRate == cOCT6100_G711_64KBPS) ? "G.711 64 kBps": (pChannelStatsCodec->ulDecodingRate == cOCT6100_G726_40KBPS) ? "G.726 40 kBps": @@ -755,20 +764,37 @@ static int wanec_api_print_full_chan_stats(wan_ec_api_t *ec_api, int fe_chan) (pChannelStatsCodec->ulDecodingRate == cOCT6100_G711_G727_3C_ENCODED) ? "G.727 3C Encoded": (pChannelStatsCodec->ulDecodingRate == cOCT6100_G711_G727_4C_ENCODED) ? "G.727 4C Encoded": "UNKNOWN"); - printf("\n"); + WANEC_API_PRINT("\n"); return 0; } static int wanec_api_verbose(int verbose) { - int ec_verbose; + int ec_driver_verbose; - ec_verbose = (verbose == 0) ? WAN_EC_VERBOSE_NONE : + ec_driver_verbose = (verbose == 0) ? WAN_EC_VERBOSE_NONE : (verbose == 1) ? WAN_EC_VERBOSE_EXTRA1 : (WAN_EC_VERBOSE_EXTRA1|WAN_EC_VERBOSE_EXTRA2); - return ec_verbose; + + return ec_driver_verbose; } +/*! + \fn void _WANEC_API_CALL wanec_api_set_lib_verbosity(int verbose) + + \brief Set Verbosity level of the Library. + The level controls amount of data printed to stdout + for diagnostic purposes. + + \param verbosity_level 0 - do NOT print to stdout, else - print to stdout. + + \return None +*/ +void _WANEC_API_CALL wanec_api_set_lib_verbosity(int verbosity_level) +{ + /* user can control output on per-function basis */ + ec_library_verbose = verbosity_level; +} int _WANEC_API_CALL wanec_api_init(void) { @@ -780,6 +806,9 @@ int _WANEC_API_CALL wanec_api_config( char *devname, int verbose, wanec_api_config_t *conf) { + wan_ec_api_t ec_api; + memset(&ec_api, 0, sizeof(ec_api)); + memcpy(ec_api.devname, devname, strlen(devname)); ec_api.verbose = wanec_api_verbose(verbose); ec_api.cmd = WAN_EC_API_CMD_CONFIG; @@ -795,6 +824,8 @@ int _WANEC_API_CALL wanec_api_release( char *devname, int verbose, wanec_api_release_t *release) { + wan_ec_api_t ec_api; + memset(&ec_api, 0, sizeof(ec_api)); memcpy(ec_api.devname, devname, strlen(devname)); ec_api.verbose = wanec_api_verbose(verbose); @@ -806,7 +837,8 @@ int _WANEC_API_CALL wanec_api_mode( char *devname, int verbose, wanec_api_mode_t *mode) { - + wan_ec_api_t ec_api; + memset(&ec_api, 0, sizeof(ec_api)); memcpy(ec_api.devname, devname, strlen(devname)); ec_api.verbose = wanec_api_verbose(verbose); ec_api.cmd = (mode->enable) ? @@ -820,7 +852,8 @@ int _WANEC_API_CALL wanec_api_bypass( char *devname, int verbose, wanec_api_bypass_t *bypass) { - + wan_ec_api_t ec_api; + memset(&ec_api, 0, sizeof(ec_api)); memcpy(ec_api.devname, devname, strlen(devname)); ec_api.verbose = wanec_api_verbose(verbose); ec_api.cmd = (bypass->enable) ? @@ -834,6 +867,8 @@ int _WANEC_API_CALL wanec_api_opmode( char *devname, int verbose, wanec_api_opmode_t *opmode) { + wan_ec_api_t ec_api; + memset(&ec_api, 0, sizeof(ec_api)); memcpy(ec_api.devname, devname, strlen(devname)); ec_api.verbose = wanec_api_verbose(verbose); @@ -868,7 +903,8 @@ int _WANEC_API_CALL wanec_api_modify( char *devname, int verbose, wanec_api_modify_t *modify) { - + wan_ec_api_t ec_api; + memset(&ec_api, 0, sizeof(ec_api)); memcpy(ec_api.devname, devname, strlen(devname)); ec_api.verbose = wanec_api_verbose(verbose); ec_api.cmd = WAN_EC_API_CMD_MODIFY_CHANNEL; @@ -885,7 +921,8 @@ int _WANEC_API_CALL wanec_api_mute( char *devname, int verbose, wanec_api_mute_t *mute) { - + wan_ec_api_t ec_api; + memset(&ec_api, 0, sizeof(ec_api)); memcpy(ec_api.devname, devname, strlen(devname)); ec_api.verbose = wanec_api_verbose(verbose); switch(mute->mode){ @@ -907,7 +944,8 @@ int _WANEC_API_CALL wanec_api_tone( char *devname, int verbose, wanec_api_tone_t *tone) { - + wan_ec_api_t ec_api; + memset(&ec_api, 0, sizeof(ec_api)); memcpy(ec_api.devname, devname, strlen(devname)); ec_api.verbose = wanec_api_verbose(verbose); ec_api.cmd = (tone->enable) ? @@ -925,6 +963,8 @@ int _WANEC_API_CALL wanec_api_stats( char *devname, wanec_api_stats_t *stats) { int err; + wan_ec_api_t ec_api; + memset(&ec_api, 0, sizeof(ec_api)); memcpy(ec_api.devname, devname, strlen(devname)); ec_api.verbose = wanec_api_verbose(verbose); @@ -976,6 +1016,8 @@ int _WANEC_API_CALL wanec_api_hwimage( char *devname, wanec_api_image_t *image) { int err; + wan_ec_api_t ec_api; + memset(&ec_api, 0, sizeof(ec_api)); memcpy(ec_api.devname, devname, strlen(devname)); ec_api.verbose = wanec_api_verbose(verbose); @@ -1000,6 +1042,8 @@ int _WANEC_API_CALL wanec_api_buffer_load(char *devname, wanec_api_bufferload_t *bufferload) { int err; + wan_ec_api_t ec_api; + memset(&ec_api, 0, sizeof(ec_api)); memcpy(ec_api.devname, devname, strlen(devname)); ec_api.verbose = wanec_api_verbose(verbose); @@ -1018,6 +1062,8 @@ int _WANEC_API_CALL wanec_api_buffer_unload( char *devname, wanec_api_bufferunload_t *bufferunload) { int err; + wan_ec_api_t ec_api; + memset(&ec_api, 0, sizeof(ec_api)); memcpy(ec_api.devname, devname, strlen(devname)); ec_api.verbose = wanec_api_verbose(verbose); @@ -1034,6 +1080,8 @@ int _WANEC_API_CALL wanec_api_playout( char *devname, wanec_api_playout_t *playout) { int err; + wan_ec_api_t ec_api; + memset(&ec_api, 0, sizeof(ec_api)); memcpy(ec_api.devname, devname, strlen(devname)); ec_api.verbose = wanec_api_verbose(verbose); @@ -1059,6 +1107,8 @@ int _WANEC_API_CALL wanec_api_monitor( char *devname, wanec_api_monitor_t *monitor) { int err; + wan_ec_api_t ec_api; + memset(&ec_api, 0, sizeof(ec_api)); memcpy(ec_api.devname, devname, strlen(devname)); ec_api.verbose = wanec_api_verbose(verbose); diff --git a/util/wanec_apilib/wanec_api.h b/util/wanec_apilib/wanec_api.h index 1de48c0..03087b9 100644 --- a/util/wanec_apilib/wanec_api.h +++ b/util/wanec_apilib/wanec_api.h @@ -110,6 +110,7 @@ extern int _WANEC_API_CALL wanec_api_buffer_load(char*,int,wanec_api_bufferload_ extern int _WANEC_API_CALL wanec_api_buffer_unload(char*,int,wanec_api_bufferunload_t*); extern int _WANEC_API_CALL wanec_api_playout(char*,int,wanec_api_playout_t*); extern int _WANEC_API_CALL wanec_api_monitor(char*,int,wanec_api_monitor_t*); +extern void _WANEC_API_CALL wanec_api_set_lib_verbosity(int verbosity_level); #ifdef __WINDOWS__ # ifdef __cplusplus diff --git a/util/wanec_apilib/wanec_api_lib.c b/util/wanec_apilib/wanec_api_lib.c index 4da45f4..eb558f7 100644 --- a/util/wanec_apilib/wanec_api_lib.c +++ b/util/wanec_apilib/wanec_api_lib.c @@ -1,8 +1,8 @@ /****************************************************************************** -** Copyright (c) 2005 -** Alex Feldman . All rights reserved. +** Copyright (c) 2005 Sangoma Technologies. All rights reserved. ** ** ============================================================================ +** May 12, 2010 David Rokhvarg added verbosity control (WANEC_API_PRINT()). ** May 29, 2008 Alex Feldman Merge two monitor function in one call. ** Jul 26, 2006 David Rokhvarg Ported to Windows. ** Oct 13, 2005 Alex Feldman Initial version. @@ -113,6 +113,13 @@ char OCT6116_256S_IMAGE_PATH[MAX_PATH]; #define MAX_OPEN_RETRY 10 +extern int ec_library_verbose; +#ifdef __WINDOWS__ +#define WANEC_API_PRINT(...) if(ec_library_verbose)printf(## __VA_ARGS__) +#else +#define WANEC_API_PRINT(...) if(ec_library_verbose)printf(__VA_ARGS__) +#endif + /****************************************************************************** ** STRUCTURES AND TYPEDEFS ******************************************************************************/ @@ -278,7 +285,7 @@ dev_open_again: sleep(1); goto dev_open_again; } - printf("ERROR: Failed to open device %s%s (err=%d,%s)\n", + WANEC_API_PRINT("ERROR: Failed to open device %s%s (err=%d,%s)\n", WANEC_DEV_DIR, WANEC_DEV_NAME, errno, strerror(errno)); return -EINVAL; @@ -302,13 +309,13 @@ static int wanec_api_lib_ioctl(int dev, wan_ec_api_t *ec_api, int verbose) ec_api->err = WAN_EC_API_RC_OK; err = ioctl(dev, ec_api->cmd, ec_api); if (err){ - printf("Failed (%s)!\n", strerror(errno)); + WANEC_API_PRINT("Failed (%s)!\n", strerror(errno)); return err; } if (ec_api->err){ switch(ec_api->err){ case WAN_EC_API_RC_INVALID_STATE: - printf("Failed (Invalid State:%s)!\n", + WANEC_API_PRINT("Failed (Invalid State:%s)!\n", WAN_EC_STATE_DECODE(ec_api->state)); break; case WAN_EC_API_RC_FAILED: @@ -318,7 +325,7 @@ static int wanec_api_lib_ioctl(int dev, wan_ec_api_t *ec_api, int verbose) case WAN_EC_API_RC_INVALID_CHANNELS: case WAN_EC_API_RC_INVALID_PORT: default: - printf("Failed (%s)!\n", + WANEC_API_PRINT("Failed (%s)!\n", WAN_EC_API_RC_DECODE(ec_api->err)); break; } @@ -335,7 +342,7 @@ HANDLE wanec_api_lib_open(wan_ec_api_t *ec_api) char device_name[200]; /* Open device for general commands */ - /*printf("Opening Device: %s\n", ec_api->devname);*/ + /*WANEC_API_PRINT("Opening Device: %s\n", ec_api->devname);*/ _snprintf(device_name , 200, "\\\\.\\%s", ec_api->devname); hGeneralCommands = CreateFile( @@ -348,7 +355,7 @@ HANDLE wanec_api_lib_open(wan_ec_api_t *ec_api) (HANDLE)NULL ); if (hGeneralCommands == INVALID_HANDLE_VALUE){ - printf("Unable to open %s for general commands!\n", device_name); + WANEC_API_PRINT("Unable to open %s for general commands!\n", device_name); return INVALID_HANDLE_VALUE; } @@ -390,7 +397,7 @@ int wanec_api_lib_ioctl(HANDLE dev, wan_ec_api_t *ec_api, int verbose) (LPDWORD)(&ln), (LPOVERLAPPED)NULL ) == FALSE){ - printf("%s(): IoctlManagementCommand failed!!\n", __FUNCTION__); + WANEC_API_PRINT("%s(): IoctlManagementCommand failed!!\n", __FUNCTION__); return 1; } @@ -400,7 +407,7 @@ int wanec_api_lib_ioctl(HANDLE dev, wan_ec_api_t *ec_api, int verbose) if (ec_api->err){ switch(ec_api->err){ case WAN_EC_API_RC_INVALID_STATE: - printf("Failed (Invalid State:%s)!\n", + WANEC_API_PRINT("Failed (Invalid State:%s)!\n", WAN_EC_STATE_DECODE(ec_api->state)); break; case WAN_EC_API_RC_FAILED: @@ -410,7 +417,7 @@ int wanec_api_lib_ioctl(HANDLE dev, wan_ec_api_t *ec_api, int verbose) case WAN_EC_API_RC_INVALID_CHANNELS: case WAN_EC_API_RC_INVALID_PORT: default: - printf("Failed (%s)!\n", + WANEC_API_PRINT("Failed (%s)!\n", WAN_EC_API_RC_DECODE(ec_api->err)); break; } @@ -430,8 +437,8 @@ static int //wan_ec_loadImageFile(wan_ec_api_t *ec_api, struct wan_ec_image *image_info) wanec_api_lib_loadImageFile( wan_ec_api_t *ec_api, char *path, - PUINT8 *pData, - UINT32 *size) + UINT8 **WP_POINTER_64 pData, + UINT32 *file_size) { UINT32 ulNumBytesRead; FILE* pFile; @@ -439,7 +446,7 @@ wanec_api_lib_loadImageFile( wan_ec_api_t *ec_api, /* Validate the parameters.*/ if (path == NULL){ - printf("ERROR: %s: Invalid image filename!\n", + WANEC_API_PRINT("ERROR: %s: Invalid image filename!\n", ec_api->devname); return -EINVAL; } @@ -449,7 +456,7 @@ wanec_api_lib_loadImageFile( wan_ec_api_t *ec_api, pFile = fopen(path, "rb" ); if ( pFile == NULL ){ - printf("ERROR: %s: Failed to open file (%s)!\n", + WANEC_API_PRINT("ERROR: %s: Failed to open file (%s)!\n", ec_api->devname, path); return -EINVAL; } @@ -458,12 +465,12 @@ wanec_api_lib_loadImageFile( wan_ec_api_t *ec_api, /* Extract the file length.*/ fseek( pFile, 0, SEEK_END ); - *size = (UINT32)ftell( pFile ); + *file_size = (UINT32)ftell( pFile ); fseek( pFile, 0, SEEK_SET ); - if (*size == 0 ){ + if (*file_size == 0 ){ fclose( pFile ); - printf("ERROR: %s: Image file is too short!\n", + WANEC_API_PRINT("ERROR: %s: Image file is too short!\n", ec_api->devname); return -EINVAL; } @@ -471,10 +478,10 @@ wanec_api_lib_loadImageFile( wan_ec_api_t *ec_api, /*==================================================================*/ /* Allocate enough memory to store the file content.*/ - ptr = (PUINT8)malloc(*size * sizeof(UINT8)); + ptr = (PUINT8)malloc(*file_size * sizeof(UINT8)); if (ptr == NULL ){ fclose( pFile ); - printf("ERROR: %s: Failed allocate memory for image file!\n", + WANEC_API_PRINT("ERROR: %s: Failed allocate memory for image file!\n", ec_api->devname); return -EINVAL; } @@ -484,12 +491,12 @@ wanec_api_lib_loadImageFile( wan_ec_api_t *ec_api, ulNumBytesRead = fread( ptr, sizeof(UINT8), - *size, + *file_size, pFile ); - if ( ulNumBytesRead != *size ){ + if ( ulNumBytesRead != *file_size ){ free( ptr ); fclose( pFile ); - printf("ERROR: %s: Failed to read image file!\n", + WANEC_API_PRINT("ERROR: %s: Failed to read image file!\n", ec_api->devname); return -EINVAL; } @@ -537,18 +544,18 @@ int wanec_api_lib_chip_load(int dev, wan_ec_api_t *ec_api, u_int16_t max_channel #endif if (max_channels == 0){ - printf("ERROR: %s: this card does NOT have Echo Canceller chip!\n", + WANEC_API_PRINT("ERROR: %s: this card does NOT have Echo Canceller chip!\n", ec_api->devname); return -EINVAL; } - printf("Searching image for %d channels...\n", max_channels); + WANEC_API_PRINT("Searching image for %d channels...\n", max_channels); image_list = wanec_api_lib_image_search(max_channels); while(image_no < image_list->images_no){ image_info = image_list->image_info[image_no]; if (image_info == NULL){ - printf("Failed!\n\n"); - printf( + WANEC_API_PRINT("Failed!\n\n"); + WANEC_API_PRINT( "ERROR: %s: Failed to find image file to EC chip (max=%d)!\n", ec_api->devname, max_channels); @@ -559,7 +566,7 @@ int wanec_api_lib_chip_load(int dev, wan_ec_api_t *ec_api, u_int16_t max_channel image_info->image_name); #if defined(__WINDOWS__) - printf("Found Image path: %s\n", image_info->image_path); + WANEC_API_PRINT("Found Image path: %s\n", image_info->image_path); #endif ec_api->u_config.max_channels = max_channels; @@ -597,7 +604,7 @@ config_poll: if (ec_api->state == WAN_EC_STATE_CHIP_OPEN_PENDING){ wp_sleep(5); - printf("."); + WANEC_API_PRINT("."); if (ec_api->u_config_poll.cnt++ < WANEC_API_MAX_CONFIG_POLL){ goto config_poll; } @@ -610,7 +617,7 @@ config_poll: } if (ec_api->state != WAN_EC_STATE_CHIP_OPEN){ - printf("Timeout!\n"); + WANEC_API_PRINT("Timeout!\n"); return -EINVAL; } @@ -627,7 +634,7 @@ int wanec_api_lib_config(wan_ec_api_t *ec_api, int verbose) u_int16_t hwec_max_channels = 0; int err; - printf("%s: Configuring Echo Canceller device...\t", + WANEC_API_PRINT("%s: Configuring Echo Canceller device...\t", ec_api->devname); dev = wanec_api_lib_open(ec_api); @@ -636,7 +643,7 @@ int wanec_api_lib_config(wan_ec_api_t *ec_api, int verbose) #else if (dev == INVALID_HANDLE_VALUE){ #endif - printf("Failed (Device open)!\n"); + WANEC_API_PRINT("Failed (Device open)!\n"); return -ENXIO; } @@ -655,7 +662,7 @@ int wanec_api_lib_config(wan_ec_api_t *ec_api, int verbose) } } if (ec_api->state != WAN_EC_STATE_CHIP_OPEN){ - printf("%s: WARNING: Incorrect Echo Canceller state (%s)!\n", + WANEC_API_PRINT("%s: WARNING: Incorrect Echo Canceller state (%s)!\n", ec_api->devname, WAN_EC_STATE_DECODE(ec_api->state)); return -EINVAL; @@ -670,7 +677,7 @@ int wanec_api_lib_config(wan_ec_api_t *ec_api, int verbose) return (err) ? -EINVAL : 0; } - printf("Done!\n"); + WANEC_API_PRINT("Done!\n"); wanec_api_lib_close(ec_api, dev); return err; } @@ -686,7 +693,7 @@ int wanec_api_lib_bufferload(wan_ec_api_t *ec_api) HANDLE dev; #endif - printf("%s: Start Tone loading...\t", + WANEC_API_PRINT("%s: Start Tone loading...\t", ec_api->devname); dev = wanec_api_lib_open(ec_api); #if !defined(__WINDOWS__) @@ -694,7 +701,7 @@ int wanec_api_lib_bufferload(wan_ec_api_t *ec_api) #else if (dev == INVALID_HANDLE_VALUE){ #endif - printf("Failed (Device open)!\n"); + WANEC_API_PRINT("Failed (Device open)!\n"); return -ENXIO; } #if !defined(__WINDOWS__) @@ -709,7 +716,7 @@ int wanec_api_lib_bufferload(wan_ec_api_t *ec_api) &ec_api->u_buffer_config.data, &ec_api->u_buffer_config.size); if (err){ - printf("Failed!\n"); + WANEC_API_PRINT("Failed!\n"); goto buffer_load_done; } @@ -717,7 +724,7 @@ int wanec_api_lib_bufferload(wan_ec_api_t *ec_api) if (err || ec_api->err){ goto buffer_load_done; } - printf("Done!\n"); + WANEC_API_PRINT("Done!\n"); buffer_load_done: wanec_api_lib_close(ec_api, dev); @@ -742,7 +749,7 @@ static int wanec_api_lib_monitor_start(wan_ec_api_t *ec_api) if (dev < 0){ return ENXIO; } - printf("%s: Starting monitor on channel %d ...", + WANEC_API_PRINT("%s: Starting monitor on channel %d ...", ec_api->devname, ec_api->fe_chan); err = wanec_api_lib_ioctl(dev, ec_api, 1); @@ -751,9 +758,9 @@ static int wanec_api_lib_monitor_start(wan_ec_api_t *ec_api) return (err) ? -EINVAL : 0; } #if defined(WANEC_API_MONITOR_NEW) - printf("\n"); + WANEC_API_PRINT("\n"); #else - printf("Done!\n"); + WANEC_API_PRINT("Done!\n"); #endif wanec_api_lib_close(ec_api, dev); return 0; @@ -772,7 +779,7 @@ static int wanec_api_lib_monitor_stop(wan_ec_api_t *ec_api) HANDLE dev; #endif - printf("%s: Reading Monitor Data ..", + WANEC_API_PRINT("%s: Reading Monitor Data ..", ec_api->devname); fflush(stdout); /* Set to zero for the first call only */ ec_api->u_chan_monitor.remain_len = 0; @@ -804,8 +811,8 @@ static int wanec_api_lib_monitor_stop(wan_ec_api_t *ec_api) t.tm_hour,t.tm_min,t.tm_sec); output = fopen(filename, "wb"); if (output == NULL){ - printf("Failed!\n"); - printf("ERROR: %s: Failed to open binary file (%s)\n", + WANEC_API_PRINT("Failed!\n"); + WANEC_API_PRINT("ERROR: %s: Failed to open binary file (%s)\n", ec_api->devname, filename); err = -EINVAL; goto monitor_done; @@ -814,20 +821,20 @@ static int wanec_api_lib_monitor_stop(wan_ec_api_t *ec_api) len = fwrite(&ec_api->u_chan_monitor.data[0], sizeof(UINT8), ec_api->u_chan_monitor.data_len, output); if (len != ec_api->u_chan_monitor.data_len){ - printf("Failed!\n"); - printf("ERROR: %s: Failed to write to binary file (%s)!\n", + WANEC_API_PRINT("Failed!\n"); + WANEC_API_PRINT("ERROR: %s: Failed to write to binary file (%s)!\n", ec_api->devname, filename); err = -EINVAL; goto monitor_done; } if (++cnt % 100 == 0){ - printf("."); + WANEC_API_PRINT("."); } wanec_api_lib_close(ec_api, dev); }while(ec_api->u_chan_monitor.remain_len); if (output) fclose(output); - printf("Done!\n"); - printf("Binary dump information is stored in %s file.\n", filename); + WANEC_API_PRINT("Done!\n"); + WANEC_API_PRINT("Binary dump information is stored in %s file.\n", filename); monitor_done: return err; @@ -843,15 +850,15 @@ int wanec_api_lib_monitor(wan_ec_api_t *ec_api) err = wanec_api_lib_monitor_start(ec_api); #if defined(WANEC_API_MONITOR_NEW) - printf("\n"); - printf("Note: You can start talk now in order to record the binary file!\n"); - printf(" !!! Do not press any key during recording time (%d seconds) !!!\n\n", + WANEC_API_PRINT("\n"); + WANEC_API_PRINT("Note: You can start talk now in order to record the binary file!\n"); + WANEC_API_PRINT(" !!! Do not press any key during recording time (%d seconds) !!!\n\n", data_mode); sec = data_mode; do { wp_sleep(scale); sec -= scale; - printf("Left: %3d sec(s)\r", sec);fflush(stdout); + WANEC_API_PRINT("Left: %3d sec(s)\r", sec);fflush(stdout); }while (sec); err = wanec_api_lib_monitor_stop(ec_api); @@ -887,10 +894,10 @@ int wanec_api_lib_cmd(wan_ec_api_t *ec_api) #else if (dev == INVALID_HANDLE_VALUE){ #endif - printf("Failed (Device open)!\n"); + WANEC_API_PRINT("Failed (Device open)!\n"); return -ENXIO; } - printf("%s: Running %s command to Echo Canceller device...\t", + WANEC_API_PRINT("%s: Running %s command to Echo Canceller device...\t", ec_api->devname, WAN_EC_API_CMD_DECODE(ec_api->cmd)); err = wanec_api_lib_ioctl(dev, ec_api, 1); @@ -898,7 +905,7 @@ int wanec_api_lib_cmd(wan_ec_api_t *ec_api) wanec_api_lib_close(ec_api, dev); return (err) ? -EINVAL : 0; } - printf("Done!\n\n"); + WANEC_API_PRINT("Done!\n\n"); wanec_api_lib_close(ec_api, dev); break; } diff --git a/util/wanpipemon/Makefile.Linux b/util/wanpipemon/Makefile.Linux index f54f8a9..e0b4133 100644 --- a/util/wanpipemon/Makefile.Linux +++ b/util/wanpipemon/Makefile.Linux @@ -26,7 +26,7 @@ ASTBROOT=/usr CC = gcc CPP = gcc -E CFLAGS = -Wall -Wstrict-prototypes -CFLAGS += $(EXTRA_FLAGS) +CFLAGS += $(EXTRA_FLAGS) $(PROTOCOL_DEFS) CFLAGS += $(GLOBAL_CFLAGS) CFLAGS += -D$(OS_TYPE) -I$(SYSINC) -I../ft1 -O2 -fomit-frame-pointer -DLOCALE -D_DEBUG_=$(DEBUG) WAN_VIRTUAL= diff --git a/util/wanpipemon/aftpipemon.c b/util/wanpipemon/aftpipemon.c index 77f42d4..355cc4f 100644 --- a/util/wanpipemon/aftpipemon.c +++ b/util/wanpipemon/aftpipemon.c @@ -335,6 +335,9 @@ int get_if_operational_stats() printf("\trx_fifo_errors\t: %u\n", stats.rx_fifo_errors); printf("\trx_missed_errors: %u\n", stats.rx_missed_errors); + /* Transmitter aborted frame transmission. Not an error. */ + printf("\trx_hdlc_abort_counter: %u\n", stats.rx_hdlc_abort_counter); + printf("\ttx_aborted_errors: %u\n", stats.tx_aborted_errors); printf("\tTx Idle Data\t: %u\n", stats.tx_carrier_errors); @@ -497,50 +500,68 @@ static void link_status (void) static void operational_stats (void) { - aft_op_stats_t *stats; + wanpipe_chan_stats_t *stats; wan_udp.wan_udphdr_command= READ_OPERATIONAL_STATS; wan_udp.wan_udphdr_return_code = 0xaa; wan_udp.wan_udphdr_data_len = 0; DO_COMMAND(wan_udp); + if (wan_udp.wan_udphdr_data_len != sizeof(wanpipe_chan_stats_t)) { + printf("Error: op stats data_len=%i != stats %i\n", + wan_udp.wan_udphdr_data_len,sizeof(wanpipe_chan_stats_t)); + } + + if (wan_udp.wan_udphdr_return_code == 0) { BANNER("AFT OPERATIONAL STATISTICS"); - stats = (aft_op_stats_t *)&wan_udp.wan_udphdr_data[0]; + stats = (wanpipe_chan_stats_t *)&wan_udp.wan_udphdr_data[0]; - printf( " Number of frames transmitted: %u", - stats->Data_frames_Tx_count); - printf( "\n Number of bytes transmitted: %u", - stats->Data_bytes_Tx_count); - printf( "\n Transmit Throughput: %u", - stats->Data_Tx_throughput); - printf( "\n Transmit frames discarded (length error): %u", - stats->Tx_Data_discard_lgth_err_count); - printf( "\n Transmit frames realigned: %u", - stats->Data_frames_Tx_realign_count); + printf( "******* OPERATIONAL_STATS *******\n"); - printf("\n\n Number of frames received: %u", - stats->Data_frames_Rx_count); - printf( "\n Number of bytes received: %u", - stats->Data_bytes_Rx_count); - printf( "\n Receive Throughput: %u", - stats->Data_Rx_throughput); - printf( "\n Received frames discarded (too short): %u", - stats->Rx_Data_discard_short_count); - printf( "\n Received frames discarded (too long): %u", - stats->Rx_Data_discard_long_count); - printf( "\nReceived frames discarded (link inactive): %u", - stats->Rx_Data_discard_inactive_count); + 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); + printf("\ttx_errors\t: %u\n", stats->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); + printf("\trx_frame_errors\t: %u\n", stats->rx_frame_errors); + printf("\trx_fifo_errors\t: %u\n", stats->rx_fifo_errors); + printf("\trx_missed_errors: %u\n", stats->rx_missed_errors); - printf("\n\nHDLC link active/inactive and loopback statistics"); - printf( "\n Times that the link went active: %u", stats->link_active_count); - printf( "\n Times that the link went inactive (modem failure): %u", stats->link_inactive_modem_count); - printf( "\n Times that the link went inactive (keepalive failure): %u", stats->link_inactive_keepalive_count); - printf( "\n link looped count: %u", stats->link_looped_count); + /* Transmitter aborted frame transmission. Not an error. */ + printf("\trx_hdlc_abort_counter: %u\n", stats->rx_hdlc_abort_counter); + 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"); + } - } }; /* Operational_stats */ @@ -834,6 +855,9 @@ loop_rx_exit: } extern int mtp2_msu_only; +extern int trace_only_diff; +extern int trace_rx_only; +extern int trace_tx_only; extern wanpipe_hdlc_engine_t *rx_hdlc_eng; wp_trace_output_iface_t hdlc_trace_iface; @@ -878,6 +902,9 @@ int wanpipe_hdlc_decode (wanpipe_hdlc_engine_t *hdlc_eng, } #endif +static int previous_trace_len=0; +static int previous_trace_data[5000]; + static void line_trace(int trace_mode) { unsigned int num_frames; @@ -1016,6 +1043,13 @@ static void line_trace(int trace_mode) hdlc_trace_iface.trace_all_data = trace_iface.trace_all_data; hdlc_trace_iface.data = trace_iface.data; hdlc_trace_iface.len = trace_iface.len; + + if (trace_rx_only && (trace_iface.status & WP_TRACE_OUTGOING)) { + continue; + } + if (trace_tx_only && !(trace_iface.status & WP_TRACE_OUTGOING)) { + continue; + } /* @@ -1029,6 +1063,26 @@ static void line_trace(int trace_mode) wanpipe_hdlc_decode(rx_hdlc_eng,trace_iface.data,trace_iface.len); continue; } + + + if (mtp2_msu_only) { + if (trace_iface.data[2] < 3) { + continue; + } + } + + + if (trace_only_diff) { + if (trace_iface.len == previous_trace_len) { + int err=memcmp(trace_iface.data,previous_trace_data,trace_iface.len); + if (err == 0) { + continue; + } + } + previous_trace_len=trace_iface.len; + memcpy(previous_trace_data,trace_iface.data,trace_iface.len); + } + if (pcap_output){ trace_iface.type=WP_OUT_TRACE_PCAP; @@ -1395,9 +1449,9 @@ int AFTUsage(void) printf("\t (T1/E1; NORMAL Clock)\n"); printf("\n"); printf("\t adlb Activate Diagnostic (Local) Loopback.\n"); - printf("\t (T1/E1; MASTER Clock\n"); + printf("\t (T1/E1; MASTER Clock)\n"); printf("\t ddlb Deactivate Diagnostic (Local) Loopback.\n"); - printf("\t (T1/E1; MASTER Clock\n"); + printf("\t (T1/E1; MASTER Clock)\n"); printf("\n"); printf("\t lb Read LoopBack status (T1/E1). This is the LoopBack\n"); printf("\t status of the LOCAL device, not a status of LoopBack\n"); @@ -1637,7 +1691,7 @@ static void read_ft1_te1_56k_config (void) static u_int32_t parse_channel_arg(int argc, char* argv[]) { u_int32_t chan_map = 0x00; - int argi = 0, chan; + int argi = 0; for(argi = 1; argi < argc; argi++){ @@ -1849,6 +1903,10 @@ int AFTMain(char *command,int argc, char* argv[]) set_fe_tx_mode(WAN_FE_TXMODE_ENABLE); }else if (!strcmp(opt,"txd")){ set_fe_tx_mode(WAN_FE_TXMODE_DISABLE); + }else if (!strcmp(opt,"tx_ais_on")){ + set_fe_tx_alarm(WAN_FE_DEBUG_ALARM_AIS_ENABLE); + }else if (!strcmp(opt,"tx_ais_off")){ + set_fe_tx_alarm(WAN_FE_DEBUG_ALARM_AIS_DISABLE); }else if (!strcmp(opt,"bert")){ err = set_fe_bert(argc, argv); }else if (!strcmp(opt,"sw_bert")){ diff --git a/util/wanpipemon/fe_lib.c b/util/wanpipemon/fe_lib.c index 131139f..b2b1177 100644 --- a/util/wanpipemon/fe_lib.c +++ b/util/wanpipemon/fe_lib.c @@ -1163,7 +1163,7 @@ void read_te1_56k_stat(unsigned char force) #endif fe_stats = (sdla_fe_stats_t*)get_wan_udphdr_data_ptr(0); if (femedia.media == WAN_MEDIA_T1 || femedia.media == WAN_MEDIA_E1){ - printf("***** %s: %s Alarms (Framer) *****\n\n", + printf("***** %s: %s Rx Alarms (Framer) *****\n\n", if_name, (femedia.media == WAN_MEDIA_T1) ? "T1" : "E1"); printf("ALOS:\t%s\t| LOS:\t%s\n", WAN_TE_PRN_ALARM_ALOS(fe_stats->alarms), @@ -1176,7 +1176,7 @@ void read_te1_56k_stat(unsigned char force) WAN_TE_PRN_ALARM_RAI(fe_stats->alarms)); if (fe_stats->alarms & WAN_TE_ALARM_LIU){ - printf("\n***** %s: %s Alarms (LIU) *****\n\n", + printf("\n***** %s: %s Rx Alarms (LIU) *****\n\n", if_name, (femedia.media == WAN_MEDIA_T1) ? "T1" : "E1"); printf("Short Circuit:\t%s\n", WAN_TE_PRN_ALARM_LIU_SC(fe_stats->alarms)); @@ -1186,6 +1186,13 @@ void read_te1_56k_stat(unsigned char force) WAN_TE_PRN_ALARM_LIU_LOS(fe_stats->alarms)); } + printf("\n***** %s: %s Tx Alarms *****\n\n", + if_name, (femedia.media == WAN_MEDIA_T1) ? "T1" : "E1"); + printf("AIS:\t%s\t| YEL:\t%s\n", + (fe_stats->tx_maint_alarms & WAN_TE_BIT_ALARM_AIS) ? "MAINT" : + (fe_stats->tx_alarms & WAN_TE_BIT_ALARM_AIS) ? "ON":"OFF", + WAN_TE_PRN_ALARM_YEL(fe_stats->tx_alarms)); + }else if (femedia.media == WAN_MEDIA_DS3 || femedia.media == WAN_MEDIA_E3){ printf("***** %s: %s Alarms *****\n\n", if_name, (femedia.media == WAN_MEDIA_DS3) ? "DS3" : "E3"); @@ -1535,6 +1542,35 @@ repeat_read_reg: return; } +void set_fe_tx_alarm(int mode) +{ + sdla_fe_debug_t fe_debug; + unsigned char *data = NULL; + + if(make_hardware_level_connection()){ + return; + } + + wan_udp.wan_udphdr_command = WAN_FE_SET_DEBUG_MODE; + wan_udp.wan_udphdr_data_len = sizeof(sdla_fe_debug_t); + wan_udp.wan_udphdr_return_code = 0xaa; + + fe_debug.type = WAN_FE_DEBUG_ALARM; + fe_debug.mode = mode; + data = get_wan_udphdr_data_ptr(0); + memcpy(data, (unsigned char*)&fe_debug, sizeof(sdla_fe_debug_t)); + + DO_COMMAND(wan_udp); + if (wan_udp.wan_udphdr_return_code != 0){ + printf("Failed to tx alarm\n"); + }else{ + printf("Alarm transmited ok!\n"); + } + + cleanup_hardware_level_connection(); + return; +} + void set_fe_tx_mode(unsigned char mode) { sdla_fe_debug_t fe_debug; @@ -1630,7 +1666,7 @@ repeat_read_reg: * repetitive word: wanpipemon -i -c Tbert ******************************************************************************/ -static int set_fe_bert_help() +static int set_fe_bert_help(void) { printf("\n"); printf("\tSangoma T1 Bit-Error-Test\n\n"); @@ -2089,7 +2125,7 @@ int sw_bert_start(unsigned char bert_sequence_type) return 0; } -int sw_bert_stop() +int sw_bert_stop(void) { memset(&wan_udp, 0x00, sizeof(wan_udp)); @@ -2118,7 +2154,7 @@ int sw_bert_stop() return 0; } -int sw_bert_status() +int sw_bert_status(void) { wp_bert_status_t *wp_bert_status; @@ -2144,7 +2180,7 @@ int sw_bert_status() return 1; } - wp_bert_status = get_wan_udphdr_data_ptr(0); + wp_bert_status = (wp_bert_status_t*) get_wan_udphdr_data_ptr(0); printf("SW BERT Status/Statistics:\n"); if (wp_bert_status->state == WP_BERT_STATUS_IN_SYNCH) { diff --git a/util/wanpipemon/fe_lib.h b/util/wanpipemon/fe_lib.h index a74fa4c..82f9f34 100644 --- a/util/wanpipemon/fe_lib.h +++ b/util/wanpipemon/fe_lib.h @@ -81,6 +81,8 @@ extern void remora_debug_mode(sdla_fe_debug_t *); extern int set_fe_bert(int argc, char *argv[]); extern int set_sw_bert(int argc, char *argv[]); +extern void set_fe_tx_alarm(int type); + #define WAN_TRUE 1 #define WAN_FALSE 0 #endif /* _SDLA_FT1_H */ diff --git a/util/wanpipemon/wanpipemon.c b/util/wanpipemon/wanpipemon.c index 71a2472..9e0ca36 100644 --- a/util/wanpipemon/wanpipemon.c +++ b/util/wanpipemon/wanpipemon.c @@ -139,6 +139,9 @@ FILE *trace_bin_in; int trace_binary=0; int mtp2_msu_only=0; +int trace_only_diff=0; +int trace_rx_only=0; +int trace_tx_only=0; wanpipe_hdlc_engine_t *rx_hdlc_eng; @@ -1064,6 +1067,16 @@ static int init(int argc, char *argv[], char* command) }else if (!strcmp(argv[i], "-mtp2-msu")){ mtp2_msu_only=1; printf("MTP2 Trace MSU Only\n"); + }else if (!strcmp(argv[i], "-diff")){ + trace_only_diff=1; + printf("Trace Diff Only\n"); + }else if (!strcmp(argv[i], "-rx")){ + trace_rx_only=1; + printf("Trace Rx Only\n"); + }else if (!strcmp(argv[i], "-tx")){ + trace_tx_only=1; + printf("Trace Tx Only\n"); + }else if (!strcmp(argv[i], "-7bit-hdlc")){ if (rx_hdlc_eng) { rx_hdlc_eng->seven_bit_hdlc = 1;