wanpipe-7.0.2.tgz

This commit is contained in:
Harald Welte 2021-12-29 18:55:48 +01:00
parent ab904c59cc
commit f719dc4b08
31 changed files with 1184 additions and 4966 deletions

View File

@ -1,2 +1,2 @@
wanpipe_linux: git ver a630c90
wanpipe_common: git ver b7dfcf2
wanpipe_linux: git ver 58560a0
wanpipe_common: git ver 81099cc

View File

@ -1 +1 @@
wanpipe-7.0.1
wanpipe-7.0.2

View File

@ -8,6 +8,23 @@ Copyright (c) 1995-2013 Sangoma Technologies Inc.
For more info visit: http://wiki.sangoma.com
------------------------------------------------------------------------------
* Fri May 10 2013 Nenad Corbic <ncorbic@sangoma.com> - 7.0.2
==================================================================
- Added sync error statistic in wanpipeomon Ta command
Sync error indicates clocking or synchronizatio errors
on T1/E1 lines. Provides added statistic to debug line,
slip errors on T1/E1.
- Fixed DAHDI reconfiguration issues.
running dahdi_cfg multiple times will not bring down T1/E1 link
Added config option to change clocking from MASTER to NORMAL
from dahdi system.conf
- New sample_data_tapping sample application for T116 and other
tapping boards.
* Tue Mar 19 2013 Nenad Corbic <ncorbic@sangoma.com> - 7.0.1
==================================================================

2
Setup
View File

@ -7338,7 +7338,7 @@ KERNEL_UNAME=`uname -r`
PKG_NAME=wanpipe
DISTR_NAME="WANPIPE"
PROD=wanrouter
PROD_VER=7.0.1
PROD_VER=7.0.2
PROD_HOME=`pwd`
META_CONF=$PROD_HOME/$PROD.rc
WAN_INTR_DIR=$PROD_HOME/interfaces

View File

@ -1,37 +0,0 @@
///////////////////////////////////////////////////////////////////////////////////////////////
/// \file ChannelizedBuffer.h
/// \brief This file contains the definition of the ChannelizedBuffer class. This class provides
/// a set of dedicated buffers (1 survey, 8 data) for up to 32 timeslots of raw E1 or
/// T1 data.
///////////////////////////////////////////////////////////////////////////////////////////////
#ifndef _CHANNELIZED_BUFFER_H
#define _CHANNELIZED_BUFFER_H
#include <vector>
typedef enum {UNSURVEYED_FRAMING=0, E1_FRAMING=32, T1_FRAMING=24} E1OrT1Framing; ///< Type of port (i.e., E1 or T1). This can also be used as the frame size
///////////////////////////////////////////////////////////////////////////////////////////////
/// \class ChannelizedBuffer
/// \brief This class provides a set of dedicated buffers (1 survey, 8 data) for up
/// to 32 timeslots of raw E1 or T1 data. It accepts data inserted from a L1
/// source. The first data byte must be timeslot 0 for this routine to work
/// correctly.
/// \author Josh Markwordt
/// \date 07/22/2005
///////////////////////////////////////////////////////////////////////////////////////////////
class ChannelizedBuffer
{
public:
explicit ChannelizedBuffer(const unsigned int buffer_size); ///< Constructor
ChannelizedBuffer(const ChannelizedBuffer &other); ///< Copy Constructor
~ChannelizedBuffer(); ///< Destructor
void Reset(const bool clear_buffers); ///< Resets the buffers so that data will be inserted at the beginning
void InsertAndChannelizeFramedData(unsigned char *p_source_buf, const unsigned int num_bytes_to_insert, const E1OrT1Framing frame_size)
{
}
};
#endif //_CHANNELIZED_BUFFER_H

View File

@ -10,27 +10,32 @@
OS_TYPE = __LINUX__
DEBUG = 2
LINK_ARGS= -lcurses -lpthread
LINK_ARGS= -lcurses -lpthread -LSangoma/Code/Sangoma -lSangoma
# Tools options.
CFLAGS = -Wall -g -O0 -D$(OS_TYPE) -D_DEBUG_=$(DEBUG) -D_GNUC_
CFLAGS += -I. -I/usr/include/wanpipe -I/usr/include
CFLAGS += $(EXTRA_FLAGS) -D__LINUX__
CFLAGS += -D_REENTRANT -D_GNU_SOURCE
CFLAGS = -Wall -g -O0 -D$(OS_TYPE) -D_DEBUG_=$(DEBUG) -D_GNUC_
CFLAGS += -I. -ISangoma/Code -ISangoma/Code/Sangoma -I../../ -I../../../../patches/kdrivers/include -I../../wanec -I../../../../patches/kdrivers/wanec -I../../../../patches/kdrivers/wanec/oct6100_api/include
CFLAGS += -I/usr/include/wanpipe
CFLAGS += $(EXTRA_FLAGS) -D__LINUX__ -DLINUX
CFLAGS += -D_REENTRANT -D_GNU_SOURCE
CXX=g++
TARGETS=sample_data_tapping
LIBS= driver_configurator.cpp PortBuffer.cpp SangomaCard.cpp SangomaPort.cpp sangoma_interface.cpp
LIBS=
####### RULES ################################################################
#make -C Sangoma/Code/Sangoma
all: $(TARGETS)
all: pre_build $(TARGETS)
@echo "Ok."
pre_build:
make -f Makefile.Linux -C Sangoma/Code/Sangoma
sample_data_tapping: sample_data_tapping.cpp $(LIBS) $(LIBS_STEL) $(LIBS_TONE)
$(CXX) $(CFLAGS) -o $@ $^ $(LINK_ARGS) -lsangoma -lstelephony -lm
$(CXX) $(CFLAGS) -o $@ $^ $(LINK_ARGS)
clean:
rm -f $(TARGETS)
make -f Makefile.Linux -C Sangoma/Code/Sangoma clean

View File

@ -1,102 +0,0 @@
#include "PortBuffer.h"
#define ERR_PORT_BUFFER printf("Error:%s():line:%d: ", __FUNCTION__, __LINE__);printf
///////////////////////////////////////////////////////////////////////////////////////////////
/// \class PortBuffer
/// \brief Structure containing a buffer for the port to read from or write to. The
/// size of buffer is indicated so that it can be allocated dynamically
/// \author David Rokhvarg (davidr@sangoma.com)
/// \date 11/13/2007
///////////////////////////////////////////////////////////////////////////////////////////////
PortBuffer::PortBuffer(unsigned int size)
{
BufferSize = size;
Buffer = (unsigned char*)malloc(size);
memset(&ApiHeader, 0x00, sizeof(ApiHeader));
}
PortBuffer::~PortBuffer()
{
free(Buffer);
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn PortBuffer::PortBuffer()
/// \brief Returns pointer to Buffer.
/// \return pointer to Buffer.
/// \author David Rokhvarg (davidr@sangoma.com)
/// \date 11/15/2007
///////////////////////////////////////////////////////////////////////////////////////////////
unsigned char *PortBuffer::GetPortBuffer()
{
return Buffer;
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn PortBuffer::PortBuffer()
/// \brief Returns the total Buffer size.
/// \return Buffer size.
/// \author David Rokhvarg (davidr@sangoma.com)
/// \date 11/15/2007
///////////////////////////////////////////////////////////////////////////////////////////////
unsigned int PortBuffer::GetPortBufferSize()
{
return BufferSize;
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn PortBuffer::GetUserDataBuffer()
/// \brief Returns pointer to buffer containng user data.
/// When data is recieved, this buffer will hold rx data.
/// When data is transmitted, this buffer should contain tx data before Write() is called.
/// \return pointer to buffer containing user data.
/// \author David Rokhvarg (davidr@sangoma.com)
/// \date 11/15/2007
///////////////////////////////////////////////////////////////////////////////////////////////
unsigned char *PortBuffer::GetUserDataBuffer()
{
return GetPortBuffer();
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn PortBuffer::GetMaximumUserDataBufferSize()
/// \brief Returns maximum size of user data buffer. This is the maximum length of user data
/// which can be transmitted/received in one buffer.
/// \return maximum size of user data buffer.
/// \author David Rokhvarg (davidr@sangoma.com)
/// \date 11/15/2007
///////////////////////////////////////////////////////////////////////////////////////////////
unsigned int PortBuffer::GetMaximumUserDataBufferSize()
{
return GetPortBufferSize();
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn PortBuffer::GetUserDataLength()
/// \brief Returns current length of user data at DataBuffer.
/// When data is recieved, GetUserDataLength() will return length of rx data.
/// \return current length of user data at DataBuffer..
/// \author David Rokhvarg (davidr@sangoma.com)
/// \date 11/15/2007
///////////////////////////////////////////////////////////////////////////////////////////////
unsigned int PortBuffer::GetUserDataLength()
{
return ApiHeader.data_length;
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn PortBuffer::SetUserDataLength()
/// \brief Set length of user data at DataBuffer.
/// When data is transmitted, SetUserDataLength() will indicate to Sangoma API how many
/// should be transmitted.
/// \return there is no return value.
/// \author David Rokhvarg (davidr@sangoma.com)
/// \date 11/15/2007
///////////////////////////////////////////////////////////////////////////////////////////////
void PortBuffer::SetUserDataLength(unsigned int user_data_length)
{
ApiHeader.data_length = user_data_length;
}

View File

@ -1,87 +0,0 @@
#ifndef _PORT_BUFFER_H
#define _PORT_BUFFER_H
#include "sangoma_interface.h"
#include <stdlib.h>
#include <malloc.h>
///////////////////////////////////////////////////////////////////////////////////////////////
/// \class PortBuffer
/// \brief Structure containing a buffer for the port to read from or write to. The
/// size of buffer is indicated so that it can be allocated dynamically
/// \author David Rokhvarg (davidr@sangoma.com)
/// \date 11/13/2007
///////////////////////////////////////////////////////////////////////////////////////////////
class PortBuffer {
unsigned char *Buffer; ///< Pointer to dynamically allocated buffer of BufferSize size.
unsigned int BufferSize; ///< The size of the unsigned char buffer that was allocated at Buffer.
wp_api_hdr_t ApiHeader; ///< Will store the size of the Rx/Tx DATA at DataBuffer coming To/From User.
public:
PortBuffer(unsigned int size);
~PortBuffer(void);
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn PortBuffer::PortBuffer()
/// \brief Returns pointer to Buffer.
/// \return pointer to Buffer.
/// \author David Rokhvarg (davidr@sangoma.com)
/// \date 11/15/2007
///////////////////////////////////////////////////////////////////////////////////////////////
unsigned char *GetPortBuffer();
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn PortBuffer::GetPortBufferSize()
/// \brief Returns the total Buffer size.
/// \return Buffer size.
/// \author David Rokhvarg (davidr@sangoma.com)
/// \date 11/15/2007
///////////////////////////////////////////////////////////////////////////////////////////////
unsigned int GetPortBufferSize();
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn PortBuffer::GetUserDataBuffer()
/// \brief Returns pointer to buffer containng user data.
/// When data is recieved, this buffer will hold rx data.
/// When data is transmitted, this buffer should contain tx data before Write() is called.
/// \return pointer to buffer containing user data.
/// \author David Rokhvarg (davidr@sangoma.com)
/// \date 11/15/2007
///////////////////////////////////////////////////////////////////////////////////////////////
unsigned char *GetUserDataBuffer();
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn PortBuffer::GetUserDataLength()
/// \brief Returns current length of user data at UserDataBuffer.
/// When data is recieved, GetUserDataLength() will return length of rx data.
/// \return current length of user data at UserDataBuffer..
/// \author David Rokhvarg (davidr@sangoma.com)
/// \date 11/15/2007
///////////////////////////////////////////////////////////////////////////////////////////////
unsigned int GetUserDataLength();
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn PortBuffer::SetUserDataLength()
/// \brief Set lenght of user data at UserDataBuffer.
/// When data is transmitted, SetUserDataLength() will indicate to Sangoma API how many
/// should be transmitted.
/// \return there is no return value.
/// \author David Rokhvarg (davidr@sangoma.com)
/// \date 11/15/2007
///////////////////////////////////////////////////////////////////////////////////////////////
void SetUserDataLength(unsigned int user_data_length);
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn PortBuffer::GetMaximumUserDataBufferSize()
/// \brief Returns maximum size of user data buffer. This is the maximum length of user data
/// which can be transmitted/received in one buffer.
/// \return maximum size of user data buffer.
/// \author David Rokhvarg (davidr@sangoma.com)
/// \date 11/15/2007
///////////////////////////////////////////////////////////////////////////////////////////////
unsigned int GetMaximumUserDataBufferSize();
};
#endif //_PORT_BUFFER_H

View File

@ -1,397 +0,0 @@
///////////////////////////////////////////////////////////////////////////////////////////////
/// \file SangomaCard.cpp
/// \brief This file contains the implementation of the SangomaCard class
///////////////////////////////////////////////////////////////////////////////////////////////
#if defined(__WINDOWS__)
# ifndef _DEBUG
# pragma optimize("2gt",on) // Windows specific (MS_SPECIFIC), enables optimization in Release mode
# endif
#endif
#include "SangomaCard.h"
#include <sstream>
using namespace Sangoma;
#include "driver_configurator.h"
#define DBG_CARD if(0)printf
#define INFO_CARD if(0)printf
#define FUNC_TRACE() DBG_CARD("%s(): Line: %u\n", __FUNCTION__, __LINE__)
//This macro is for Error reporting and should NOT be disabled.
#define ERR_CARD printf("Error:%s():line:%d: ", __FUNCTION__, __LINE__);printf
//these arrays is initialized by GetNumberOfCardsInstalled()
static wanpipe_instance_info_t a104_wanpipe_info_array[MAX_CARDS];
static wanpipe_instance_info_t a108_wanpipe_info_array[MAX_CARDS];
static wanpipe_instance_info_t a116_wanpipe_info_array[MAX_CARDS];
static wanpipe_instance_info_t t116_wanpipe_info_array[MAX_CARDS];
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn unsigned int GetNumberOfCardsInstalled(const CardModel model)
/// \brief Returns the number of Sangoma cards of the model provided for this system. It is
/// possible for there to be a mixture of A104 and A108, and so the number of each can
/// be requested by changing the CardModel provided.
/// \param model CardModel for which we want to retrieve the number of cards installed
/// \return unsigned int number of cards of the CardModel provided
/// \author J. Markwordt
/// \date 10/08/2007
///////////////////////////////////////////////////////////////////////////////////////////////
unsigned int GetNumberOfCardsInstalled(const CardModel model)
{
unsigned int number_of_card_model = 0;
driver_configurator *drv_cfg_obj;
/// Perform operations to get the number of Sangoma cards of the model provided in the system
drv_cfg_obj = new driver_configurator();
switch(model)
{
case A104:
number_of_card_model = drv_cfg_obj->scan_for_sangoma_cards(a104_wanpipe_info_array, A104_ADPTR_4TE1);
break;
case A108:
number_of_card_model = drv_cfg_obj->scan_for_sangoma_cards(a108_wanpipe_info_array, A108_ADPTR_8TE1);
break;
case A116:
number_of_card_model = drv_cfg_obj->scan_for_sangoma_cards(a116_wanpipe_info_array, A116_ADPTR_16TE1);
break;
case T116:
number_of_card_model = drv_cfg_obj->scan_for_sangoma_cards(t116_wanpipe_info_array, AFT_ADPTR_T116);
break;
default:
number_of_card_model = 0;
break;
}
delete drv_cfg_obj;
return number_of_card_model;
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn SangomaCard::SangomaCard(const unsigned int card_number, const CardModel model,
/// const BufferSettings & ReceiveBufferSettings, const BufferSettings & TransmitBufferSettings)
/// \brief Constructor
/// \param card_number const unsigned int of the number of this card (zero indexed)
/// \param model const CardModel of the type of Sangoma card this object is to
/// represent (A104 or A108)
/// \param ReceiveBufferSettings BufferSettings to configure the host memory buffers
/// for receive operations on this port (set NumberOfBuffersPerPort
/// to 0 to disable receiving data on this port)
/// \param TransmitBufferSettings BufferSettings to configure the host memory buffers
/// for transmit operations on this port (set NumberOfBuffersPerPort
/// to 0 to disable transmitting data on this port)
/// \author J. Markwordt
/// \date 10/04/2007
///////////////////////////////////////////////////////////////////////////////////////////////
SangomaCard::SangomaCard(const unsigned int card_number, const CardModel model,
const BufferSettings & ReceiveBufferSettings, const BufferSettings & TransmitBufferSettings)
: CardNumber(card_number),
Model(model), // Set the card model to that provided
NumberOfPorts(NUMBER_OF_A104_PORTS), // Initialize to A104, but will be reset in the body of the constructor
Ports(),
LastError(NO_ERROR_OCCURRED)
{
FUNC_TRACE();
wanpipe_instance_info_t *wanpipe_instance_info;
switch (model) {
case A104:
wanpipe_instance_info = a104_wanpipe_info_array;
break;
case A108:
wanpipe_instance_info = a108_wanpipe_info_array;
break;
case A116:
wanpipe_instance_info = a116_wanpipe_info_array;
break;
case T116:
wanpipe_instance_info = t116_wanpipe_info_array;
break;
}
if(MAX_CARDS <= card_number){
ERR_CARD("%s(): invalid 'card_number' %u!!\n", __FUNCTION__, card_number);
return;
}
// The number of ports was initialized above for the A104,
// so only change it if A108 was the model that was actually provided.
if (A108 == model) {
NumberOfPorts = NUMBER_OF_A108_PORTS;
}
if (A116 == model) {
NumberOfPorts = NUMBER_OF_A116_PORTS;
}
if (T116 == model) {
NumberOfPorts = NUMBER_OF_T116_PORTS;
}
DBG_CARD("%s(): wanpipe_instance_info: 0x%p\n", __FUNCTION__, wanpipe_instance_info);
// Create the number of ports required for this card's
// model type and add them to the Ports vector.
for (unsigned int port = 0; port < NumberOfPorts; port++) {
Ports.push_back(new SangomaPort(wanpipe_instance_info[CardNumber].wanpipe_number, port,
ReceiveBufferSettings, TransmitBufferSettings));
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn SangomaCard::~SangomaCard()
/// \brief Destructor
/// \author J. Markwordt
/// \date 10/04/2007
///////////////////////////////////////////////////////////////////////////////////////////////
SangomaCard::~SangomaCard()
{
// Delete the all of the ports created for this card's
// model type and then clear the Ports vector
for (unsigned int port = 0; port < NumberOfPorts; ++port) {
delete Ports.at(port);
}
Ports.clear();
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn unsigned int SangomaCard::GetCardNumber() const
/// \brief Returns the card number of this Sangoma card (zero indexed)
/// \return unsigned int card number of this card
/// \author J. Markwordt
/// \date 10/04/2007
///////////////////////////////////////////////////////////////////////////////////////////////
unsigned int SangomaCard::GetCardNumber() const
{
return CardNumber;
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn CardModel SangomaCard::GetModel() const
/// \brief Returns the model of Sangoma card that this object represents (A104 or A108)
/// \return CardModel of this SangomaCard
/// \author J. Markwordt
/// \date 10/04/2007
///////////////////////////////////////////////////////////////////////////////////////////////
CardModel SangomaCard::GetModel() const
{
return Model;
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn unsigned int SangomaCard::GetNumberOfPorts() const
/// \brief Returns the number of ports in this card
/// \return unsigned int number of ports in this card
/// \author J. Markwordt
/// \date 10/04/2007
///////////////////////////////////////////////////////////////////////////////////////////////
unsigned int SangomaCard::GetNumberOfPorts() const
{
return NumberOfPorts;
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn SangomaCard::GetPort(const unsigned int port_number)
/// \brief Returns a pointer to the port requested
/// \return SangomaPort* to the port requested
/// \author J. Markwordt
/// \date 10/04/2007
///////////////////////////////////////////////////////////////////////////////////////////////
SangomaPort* SangomaCard::GetPort(const unsigned int port_number)
{
// Check to make make sure the port_number requested is valid
bool valid_port_number = (NumberOfPorts > port_number);
if (!valid_port_number) {
std::ostringstream error_msg;
error_msg << "ERROR: SangomaCard::GetPort() called on invalid port number " << port_number << ".";
LastError = error_msg.str();
return NULL;
}
// Port number is valid, so indicate that no error occured on this operation
LastError = NO_ERROR_OCCURRED;
// If valid, return the pointer to the SangomaPort at that position
return Ports.at(port_number);
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn SangomaCard::GetCardDriverVersion()
/// \brief Returns the card's driver version number. Sangoma has given the card a driver and
/// the port what Sangoma refers to as a "Hardware Abstraction Driver", and although
/// these two should have the same version number IF INSTALLED PROPERLY, they are in
/// fact two separate drivers.
///
/// This function is to retrieve the driver associated with the card as a whole and
/// can be used to verify that it matches the version number of the ports' hardware
/// abstraction drivers.
/// \return DriverVersion structure containing the driver version information for this card
/// \author J. Markwordt
/// \date 10/04/2007
///////////////////////////////////////////////////////////////////////////////////////////////
DriverVersion SangomaCard::GetCardDriverVersion()
{
DriverVersion card_driver_version;
/// Perform low level calls to retrieve the driver version from the card
SangomaPort *p_port = GetPort(0);
if(p_port != NULL){
card_driver_version.Major = p_port->GetDriverVersion().Major;
card_driver_version.Build = p_port->GetDriverVersion().Build;
card_driver_version.Minor = p_port->GetDriverVersion().Minor;
card_driver_version.Revision = p_port->GetDriverVersion().Revision;
DBG_CARD("%s(): card_driver_version: %i.%i.%i.%i\n", __FUNCTION__, card_driver_version.Major,
card_driver_version.Minor, card_driver_version.Build, card_driver_version.Revision);
}
return card_driver_version;
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn SangomaCard::GetSerialNumber() const
/// \brief Returns the card's serial number
/// \return std::string containing the card's serial number
/// \author J. Markwordt
/// \date 10/04/2007
///////////////////////////////////////////////////////////////////////////////////////////////
std::string SangomaCard::GetSerialNumber() const
{
std::string serial_number;
/// \todo Perform low level calls to retrieve the serial number for the card
//DAVIDR: there is no way to know card serial number.
return serial_number;
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn SangomaCard::GetFirmwareVersion() const
/// \brief Returns the card's firmware version
/// \return std::string containing the card's firmware version
/// \author J. Markwordt
/// \date 10/04/2007
///////////////////////////////////////////////////////////////////////////////////////////////
std::string SangomaCard::GetFirmwareVersion() const
{
std::string firmware_version;
wanpipe_instance_info_t *WanpipeInstanceInfo = NULL;
/// Perform low level calls to retrieve the firmware version number for the card
switch(GetModel())
{
case A104:
WanpipeInstanceInfo = a104_wanpipe_info_array;
break;
case A108:
WanpipeInstanceInfo = a108_wanpipe_info_array;
break;
case A116:
WanpipeInstanceInfo = a116_wanpipe_info_array;
break;
case T116:
WanpipeInstanceInfo = t116_wanpipe_info_array;
break;
}
firmware_version = "0000";
if(WanpipeInstanceInfo){
sprintf((char*)firmware_version.c_str(), "%X",
WanpipeInstanceInfo[GetCardNumber()].hardware_info.firmware_version);
DBG_CARD("%s(): card firmware version: %s\n", __FUNCTION__, firmware_version.c_str());
}
return firmware_version;
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn SangomaCard::GetCardPciBus() const
/// \brief Returns the number of the PCI bus that the card is located in
/// \return unsigned int number of the PCI bus that the card is located in
/// \author J. Markwordt
/// \date 10/04/2007
///////////////////////////////////////////////////////////////////////////////////////////////
unsigned int SangomaCard::GetCardPciBus() const
{
unsigned int pci_bus_number = 0;
wanpipe_instance_info_t *WanpipeInstanceInfo = NULL;
/// Perform low level calls to retrieve the number of the PCI bus that the card is located in
switch(GetModel())
{
case A104:
WanpipeInstanceInfo = a104_wanpipe_info_array;
break;
case A108:
WanpipeInstanceInfo = a108_wanpipe_info_array;
break;
case A116:
WanpipeInstanceInfo = a116_wanpipe_info_array;
break;
case T116:
WanpipeInstanceInfo = t116_wanpipe_info_array;
break;
}
if(WanpipeInstanceInfo){
pci_bus_number = WanpipeInstanceInfo[GetCardNumber()].hardware_info.pci_bus_number;
DBG_CARD("%s(): card pci_bus_number: %i\n", __FUNCTION__, pci_bus_number);
}
return pci_bus_number;
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn SangomaCard::GetCardPciSlot() const
/// \brief Returns the number of the PCI slot that the card is located in
/// \return unsigned int number of the PCI slot that the card is located in
/// \author J. Markwordt
/// \date 10/10/2007
///////////////////////////////////////////////////////////////////////////////////////////////
unsigned int SangomaCard::GetCardPciSlot() const
{
unsigned int pci_bus_slot = 0;
wanpipe_instance_info_t *WanpipeInstanceInfo = NULL;
/// Perform low level calls to retrieve the number of the PCI slot that the card is located in
switch(GetModel())
{
case A104:
WanpipeInstanceInfo = a104_wanpipe_info_array;
break;
case A108:
WanpipeInstanceInfo = a108_wanpipe_info_array;
break;
case A116:
WanpipeInstanceInfo = a116_wanpipe_info_array;
break;
case T116:
WanpipeInstanceInfo = t116_wanpipe_info_array;
break;
}
if(WanpipeInstanceInfo){
pci_bus_slot = WanpipeInstanceInfo[GetCardNumber()].hardware_info.pci_slot_number;
DBG_CARD("%s(): card pci_bus_slot: %i\n", __FUNCTION__, pci_bus_slot);
}
return pci_bus_slot;
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// \fn SangomaCard::GetLastError() const
/// \brief Returns a description of the last error that occurred
/// \return Returns a description of the last error that occurred (NO_ERROR_OCCURRED if the last command was successful)
/// \author J. Markwordt
/// \date 10/17/2007
///////////////////////////////////////////////////////////////////////////////////////////////
std::string SangomaCard::GetLastError() const
{
return LastError;
}
#if defined(__WINDOWS__)
# ifndef _DEBUG
# pragma optimize("2gt",off)// Windows specific (MS_SPECIFIC), disables optimization in Release mode
# endif
#endif

View File

@ -1,144 +0,0 @@
///////////////////////////////////////////////////////////////////////////////////////////////
/// \mainpage Sangoma API Design Document
///
/// \section overview Overview
///
/// The Sangoma API defines several C++ classes that provide an interface to perform commands
/// on the Sangoma A104 and A108 E1/T1 cards. Each physical PCI card is represented by a
/// \link Sangoma::SangomaCard \endlink object which contains the appropriate number of \link Sangoma::SangomaPort \endlink
/// objects to encapsulate their behaviour.
///
/// The Sangoma API will transfer data read from the physical port to host memory using Direct
/// Memory Access (DMA), filling a series of buffers and then raising an event to alert calling
/// programs that data is available to be read. By eliminating polling for data, this will
/// improve efficiency.
///
/// \subsection card_object SangomaCard
/// A SangomaCard object represents a physical Sangoma A104 or A108 PCI E1/T1 card containing
/// 4 or 8 E1/T1 ports respectively. The relationship between SangomaCard and SangomaPorts can
/// be seen below for the Sangoma A104:
///
/// \image html SangomaA104Overview.jpg
///
/// and for the Sangoma A108:
///
/// \image html SangomaA108Overview.jpg
///
/// Any behaviour which occurs at the card level and access to the SangomaPort objects (which do
/// most of the actual work) are controlled through this class.
///
/// \subsection port_object SangomaPort
/// A SangomaPort represents a physical E1/T1 port and encapsulates the ability to set the
/// configuration of the port, read, write and retrieve hardware alarms and statistics. Note
/// that since multiple E1/T1 lines are multiplexed into a single physical port on the Sangoma
/// A108, there will be two SangomaPort objects for each physical port of the A108 (as seen in the
/// figure above).
///
/// SangomaPorts can be accessed through SangomaCard::GetPort() and then manipulated directly.
///
/// \subsection port_buffers SangomaPort Buffers
/// Each SangomaPort contains software buffers to store data read from the physical card.
/// Buffers are allocated as multiples of 8188 bytes (8188 bytes is the size of the Sangoma
/// cards hardware buffer. The software buffers use the same size to simplify the processing.).
/// Therefore the size of a single buffer will be set by the BufferMultiplierFactor, such that the
/// size of a buffer is 8188 * BufferMultiplierFactor bytes. SangomaPorts can have multiple buffers.
/// The number of buffers is controlled by NumberOfBuffersPerPort.
///
/// When a buffer becomes full the ReadDataAvailable event is signaled to indicate data is
/// available for retrieval. Note that a full buffer does not necessarily use the fully
/// allocated size. It always contains full E1 (32 bytes) or T1 (24 bytes) frames. Therefore
/// a small portion at the end of each buffer may be left unused.
///
/// The diagram below provides an example of the buffers contained in a SangomaPort.
///
/// \image html SangomaPortBuffers.jpg
///
/// To store data the SangomaPort will cycle through its buffers in a circular fashion so that when the
/// current buffer becomes full data can be stored in the next buffer while the previous one
/// is waiting to be read. The diagram below shows how the buffers will be used within the
/// SangomaPort.
///
/// \image html SangomaPortBuffersCycle.jpg
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
/// \file SangomaCard.h
/// \brief This file contains the declaration of the SangomaCard class
///////////////////////////////////////////////////////////////////////////////////////////////
#ifndef _SANGOMA_CARD_H
#define _SANGOMA_CARD_H
#include <string>
#include <vector>
#include "SangomaPort.h"
const unsigned int NUMBER_OF_A104_PORTS = 4; ///< The number of ports in a Sangoma A104 card
const unsigned int NUMBER_OF_A108_PORTS = 8; ///< The number of ports in a Sangoma A108 card
const unsigned int NUMBER_OF_A116_PORTS = 8; ///< The number of ports in a Sangoma A108 card
const unsigned int NUMBER_OF_T116_PORTS = 16; ///< The number of ports in a Sangoma T116 card
///////////////////////////////////////////////////////////////////////////////////////////////
/// \enum CardModel
/// \brief Enumeration indicating the model of Sangoma card that this SangomaCard is
///////////////////////////////////////////////////////////////////////////////////////////////
enum CardModel {
A104, ///< Indicates the Sangoma A104 card model
A108, ///< Indicates the Sangoma A108 card model
A116, ///< Indicates the Sangoma A108 card model
T116
};
unsigned int GetNumberOfCardsInstalled(const CardModel model); ///< Checks for the number of cards of the model type provided are installed
///////////////////////////////////////////////////////////////////////////////////////////////
/// \namespace Sangoma
/// \brief The Sangoma namespace is used to wrap all Sangoma classes to identify them as a
/// package and to allow simple names for structures, constants, enums and other
/// identifiers without having to worry about creating naming conflicts with other
/// packages.
///////////////////////////////////////////////////////////////////////////////////////////////
namespace Sangoma {
///////////////////////////////////////////////////////////////////////////////////////////////
/// \class SangomaCard
/// \brief This class encapsulates the functionality of a physical Sangoma card (models A104
/// or A108).
/// \author J. Markwordt
/// \date 10/03/2007
///////////////////////////////////////////////////////////////////////////////////////////////
class SangomaCard {
public:
explicit SangomaCard(const unsigned int card_number, const CardModel model,
const BufferSettings & ReceiveBufferSettings,
const BufferSettings & TransmitBufferSettings); ///< Constructor
~SangomaCard(); ///< Destructor
unsigned int GetCardNumber() const; ///< Returns the card number of this Sangoma card
CardModel GetModel() const; ///< Returns the model of Sangoma card that this object represents (A104 or A108)
unsigned int GetNumberOfPorts() const; ///< Returns the number of ports in this card
SangomaPort* GetPort(const unsigned int port_number); ///< Returns a pointer to the port requested
DriverVersion GetCardDriverVersion(); ///< Returns the card's driver version number
std::string GetSerialNumber() const; ///< Returns the card's serial number
std::string GetFirmwareVersion() const; ///< Returns the card's firmware version
unsigned int GetCardPciBus() const; ///< Returns the number of the PCI bus that the card is located in
unsigned int GetCardPciSlot() const; ///< Returns the number of the PCI bus that the card is located in
std::string GetLastError() const; ///< Returns string description of the last error that occured for this card
private:
// Copy constructor and assigment operator are made private
// and left unimplemented to ensure that the SangomaCard object cannot be copied
SangomaCard(const SangomaCard& port); ///< Copy Constructor (do not implement)
SangomaCard& operator=(const SangomaCard& rhs); ///< Assignment Operator (do not implement)
unsigned int CardNumber; ///< Number of this card in the system (zero indexed)
CardModel Model; ///< The model of Sangoma card that this object represents (A104 or A108)
unsigned int NumberOfPorts; ///< The number of SangomaPorts found in this card
std::vector<SangomaPort*> Ports; ///< Vector of the SangomaPorts contained in this card
std::string LastError; ///< String description of the last error that occurred (should be set if an error occurs in any SangomaCard member functions, or empty if successful)
};
}// namespace Sangoma
#endif //_SANGOMA_CARD_H

File diff suppressed because it is too large Load Diff

View File

@ -1,384 +0,0 @@
///////////////////////////////////////////////////////////////////////////////////////////////
/// \file SangomaPort.h
/// \brief This file contains the declaration of the SangomaPort class
///////////////////////////////////////////////////////////////////////////////////////////////
#ifndef _SANGOMA_PORT_H
#define _SANGOMA_PORT_H
#include <string>
#include "ChannelizedBuffer.h"
#include "sangoma_interface.h"
#include "PortBuffer.h"
namespace Sangoma {
// Read/Write error codes
const int ERROR_NO_DATA_AVILABLE = -1; ///< Error code indicating that a SangomaPort::Read was attempted when no data was available (indicates a possible abuse of the API by polling for data instead of waiting for the DataAvailableEvent)
const int ERROR_INVALID_DESTINATION_BUFFER = -2; ///< Error code indicating that the destination buffer provided to SangomaPort::Read was NULL
const int ERROR_INVALID_SOURCE_BUFFER = -3; ///< Error code indicating that the source buffer provided to SangomaPort::Write was NULL
const int ERROR_NO_DATA_WRITTEN = -4; ///< Error code indicating that the SangomaPort::Write command failed
const int ERROR_PORT_NOT_OPEN = -5; ///< Error code indicating that the Read or Write command failed because the port has not been opened. Call SangomaPort::Open() successfully before attempting to Read or Write.
const int ERROR_INVALID_DESTINATION_BUFFER_TOO_SMALL = -6; ///< Error code indicating that the destination buffer provided to SangomaPort::Read was to small to contain a full buffer's worth of data (configuration error)
const int ERROR_INVALID_READ_REQUEST = -7; ///< Error code indicating that the input to SangomaPort::Read was invalid
/// \todo Add more detailed read/write failure codes as available from the API (more detail is better)
const int ERROR_DEVICE_IOCTL = -8; ///< Error code indicating that DeviceIoControl() for API Device Driver failed. Check '\System32\drivers\wanpipelog.txt' messages log for detailes.
const int ERROR_INVALID_TX_DATA_LENGTH = -8; ///< Error code indicating that SangomaPort::Write failed because user data was too long.
const std::string NO_ERROR_OCCURRED = ""; ///< String indicating that no error occurred on the last operation (returned by GetLastError() when the last operation was successful)
const unsigned int MAX_SANGOMA_BUFFER_SIZE = 8188; ///< Maximum Sangoma buffer size in bytes
const unsigned int ALARM_WAIT_TIME_MS = 30000; ///< The number of milliseconds that the Sangoma API must wait in order to be able to reliably report the absense of alarms.
/// If GetAlarms() is called before this amount of time has elapsed after setting a configuration, the card will always
/// report no alarms, giving a false positive that we have found synchronization.
///////////////////////////////////////////////////////////////////////////////////////////////
/// \enum E1OrT1
/// \brief Enumeration indicating whether a port is in E1 or T1 mode
///////////////////////////////////////////////////////////////////////////////////////////////
enum E1OrT1 {
E1=32, ///< Indicates that the port is configured as an E1 port
T1=24 ///< Indicates that the port is configured as a T1 port
};
///////////////////////////////////////////////////////////////////////////////////////////////
/// \enum FramingType
/// \brief Enumeration indicating the framing type and signaling of the port
///////////////////////////////////////////////////////////////////////////////////////////////
enum FramingType {
//DAVIDR: i added the UNFRAMED E1 types
E1_CCS_UNFRAMED, ///< Indicates that Common Channel Signalling (CCS) with Unframed E1, all 32 timeslots available for the E1 port
E1_CAS_UNFRAMED, ///< Indicates that Channel Associated Signaling (CAS) with Unframed E1, all 32 timeslots available for the E1 port
E1_CAS_CRC4_ON, ///< Indicates that Channel Associated Signaling (CAS) with CRC4 is the framing type for the E1 port
E1_CAS_CRC4_OFF, ///< Indicates that Channel Associated Signaling (CAS) with no CRC4 is the framing type for the E1 port
E1_CCS_CRC4_ON, ///< Indicates that Common Channel Signalling (CCS) with CRC4 is the framing type for the E1 port
E1_CCS_CRC4_OFF, ///< Indicates that Common Channel Signalling (CCS) with no CRC4 is the framing type for the E1 port
T1_EXTENDED_SUPERFRAME, ///< Indicates that Extended Superframe (ESF, also called D5 framing) is the framing type for the T1 port
T1_SUPERFRAME ///< Indicates that Superframe (also called D4 or D3/D4 framing) is the framing type for the T1 port
};
#define DECODE_FRAMING(framing)\
(framing == E1_CCS_UNFRAMED)? "E1_CCS_UNFRAMED" : \
(framing == E1_CAS_UNFRAMED)? "E1_CAS_UNFRAMED" : \
(framing == E1_CAS_CRC4_ON) ? "E1_CAS_CRC4_ON" : \
(framing == E1_CAS_CRC4_OFF)? "E1_CAS_CRC4_OFF" : \
(framing == E1_CCS_CRC4_ON) ? "E1_CCS_CRC4_ON" : \
(framing == E1_CCS_CRC4_OFF)? "E1_CCS_CRC4_OFF" : \
(framing == T1_EXTENDED_SUPERFRAME) ? "T1_EXTENDED_SUPERFRAME" : \
(framing == T1_SUPERFRAME) ? "T1_SUPERFRAME" : "???"
#define DECODE_CARD_TYPE(type) \
(type == A104)? "A104" : \
(type == A108)? "A108" : \
(type == A116)? "A116" : \
(type == T116)? "T116" : "Invalid Card"
//DAVIDR: On E1 line Sangoma card provides access to timeslot 0 ONLY if Framing is "Unframed E1".
///////////////////////////////////////////////////////////////////////////////////////////////
/// \enum LineCoding
/// \brief Enumeration indicating whether line coding is on or off for the port
///////////////////////////////////////////////////////////////////////////////////////////////
enum LineCoding {
OFF, ///< Indicates that line coding is off (meaning set to the default AMI value)
ON ///< Indicates that line coding is on (meaning B8ZS for T1, and HDB3 for E1)
};
/**********************************************************
DAVIDR: Receiver Sensitivity (Max Cable Loss Allowed) (dB)
The user will have the following option to choose:
1. HI IMPEDANCE mode:
30 dB
22.5 dB
17.5 dB
12 dB
Depending on selection, use the following values:
300
225
175
120
2. NORMAL mode:
12 dB
18 dB
30 dB
36 dB (for T1)
43 dB (for E1)
Depending on selection, use the following values:
120
180
300
360
430
**********************************************************/
enum MAX_CABLE_LOSS{
MCLV_43_0dB=430,
MCLV_36_0dB=360,
MCLV_30_0dB=300,
MCLV_22_5dB=225,
MCLV_18_0dB=180,
MCLV_17_5dB=175,
MCLV_12_0dB=120
};
///////////////////////////////////////////////////////////////////////////////////////////////
/// \struct Configuration
/// \brief Structure containing all settings necessary to configure a Sangoma port
///////////////////////////////////////////////////////////////////////////////////////////////
struct Configuration {
E1OrT1 e1Ort1; ///< Configures the port as either E1 or T1
FramingType Framing; ///< Framing type and signalling of the E1/T1 port
LineCoding lineCoding; ///< Indicates whether line coding is ON or OFF
bool HighImpedanceMode; ///< true to indicate High Impedance mode is to be enabled, false to disable it
MAX_CABLE_LOSS MaxCableLoss; ///< If High Impedance is true, indicates value of external resistor.
bool TxTristateMode; ///< If true, indicates transmitter is disabled on T1/E1 level.
bool Master; ///< If true, configure for master clock
Configuration(); ///< Constructor
};
///////////////////////////////////////////////////////////////////////////////////////////////
/// \struct Statistics
/// \brief Structure containing all statistics related to a Sangoma port
///////////////////////////////////////////////////////////////////////////////////////////////
struct Statistics {
// The following time values are to be calculated using the time() function found in time.h. This
// is standard ANSI C and returns the current time as the number of seconds elapsed since midnight
// on January 1, 1970. Operations involving elapsed time can then be done by subtracting from
// current time (or some other instant) and converting to hours, minutes and seconds
// The function struct tm * localtime(const time_t * timer); will convert the time to a tm structure
// that is broken into date and time fields
// Statistics maintained in software by the SangomaPort class
time_t TimeLastOpened; ///< System time of the last time this port was opened
time_t TimeLastClosed; ///< System time of the last time this port was closed
time_t TimeLastFoundSync; ///< System time of the last time this port found sync with a valid configuration
time_t TimeLastLostSync; ///< System time of the last time this port lost sync when already in sync
unsigned int OpenCount; ///< Count of the number of times the port was opened (i.e. number of times SangomaPort::Open() returned successfully)
unsigned int CloseCount; ///< Count of the number of times the port was closed (i.e. number of times SangomaPort::Close() returned successfully)
unsigned int FoundSyncCount; ///< Count of the number of times synchronization was found on the port (i.e. number of times sync was found when the port was opened)
unsigned int LostSyncCount; ///< Count of the number of times synchronization was lost on the port (i.e. number of times the LineDisconnected event was raised, since both indicate a loss of sync on the line)
// Statistics maintained in hardware, a command will have to be sent to the port to retrieve this data
unsigned int BytesReceived; ///< Number of bytes received on this port
unsigned int BytesSent; ///< Number of bytes transmitted from this port
unsigned int Errors; ///< Number of bytes transmitted from this port
Statistics(); ///< Constructor
};
///////////////////////////////////////////////////////////////////////////////////////////////
/// \struct Alarms
/// \brief Structure containing a series off boolean flags to indicate the presence of Sangoma
/// hardware alarms. If true, indicates that the given alarm is present, if false indicates
/// that the alarm is not present.
///////////////////////////////////////////////////////////////////////////////////////////////
struct Alarms {
bool LossOfSignal; ///< Indicates that the Loss of Signal (ALOSV) alarm is present if true
bool ReceiveLossOfSignal; ///< Indicates that the Receive Loss of Signal (LOS) alarm is present if true
bool AlternateLossOfSignalStatus; ///< Indicates that the Alternate loss of Signal Status (ALTLOS) alarm is present if true
bool OutOfFrame; ///< Indicates that the Out of Frame (OOF) alarm is present if true
bool Red; ///< Indicates that the Telco Red Alarm condition (RED) is present if true
bool AlarmIndicationSignal; ///< Indicates that the Alarm Indication Signal (AIS) is present if true
bool LossOfSignalingMultiframe; ///< Indicates that the Loss of Signaling Multiframe (OOSMFV) alarm is present if true
bool LossOfCrcMultiframe; ///< Indicates that the Loss of CRC Multiframe (OOCMFV) alarm is present if true
bool OutOfOfflineFrame; ///< Indicates that the Out of Off-Line Frame (OOOFV) alarm is present if true
bool ReceiveLossOfSignalV; ///< Indicates that the Receive Loss of Signal (RAIV) alarm is present if true
bool Yellow; ///< Indicates that the Receive Telco Yellow Alarm (YEL) is present if true
Alarms(); ///< Constructor
Alarms(bool value) ///< Constructor
{
LossOfSignal = value;
ReceiveLossOfSignal = value;
AlternateLossOfSignalStatus = value;
OutOfFrame = value;
Red = value;
AlarmIndicationSignal = value;
LossOfSignalingMultiframe = value;
LossOfCrcMultiframe = value;
OutOfOfflineFrame = value;
ReceiveLossOfSignalV = value;
Yellow = value;
}
};
///////////////////////////////////////////////////////////////////////////////////////////////
/// \struct DriverVersion
/// \brief Structure containing the driver version number
///////////////////////////////////////////////////////////////////////////////////////////////
struct DriverVersion {
unsigned int Major; ///< The major version number of the driver (i.e. the 1 in 1.2.3.4)
unsigned int Minor; ///< The minor version number of the driver (i.e. the 2 in 1.2.3.4)
unsigned int Build; ///< The build version number of the driver (i.e. the 3 in 1.2.3.4)
unsigned int Revision; ///< The revision version number of the driver (i.e. the 4 in 1.2.3.4)
DriverVersion(); ///< Constructor
};
///////////////////////////////////////////////////////////////////////////////////////////////
/// \enum SynchronizationStatus
/// \brief Enumeration indicating the synchronization status of the port
///////////////////////////////////////////////////////////////////////////////////////////////
enum SynchronizationStatus {
PORT_NOT_IN_SYNC, ///< Indicates that an Open() was attempted on the port and the configuration has proved to be incompatible with the data provided on that port
PORT_WAITING_FOR_SYNC, ///< Indicates that an Open() was attempted on the port and not enough time has elapsed to be able to reliably tell whether the configuration is correct
PORT_IN_SYNC ///< Indicates that an Open() was attempted on the port and the configuration matched the data provided, the port is in sync
};
///////////////////////////////////////////////////////////////////////////////////////////////
/// \enum PortEventType
/// \brief Enumeration indicating the type of event that that triggered a call to the PortEventHandler
///////////////////////////////////////////////////////////////////////////////////////////////
enum PortEventType {
Unsignalled, ///< Default value, indicates that the event has not been signalled (should not be seen in actual events that are triggered)
ReadDataAvailable, ///< Indicates that the read buffer is full (SangomaPort::Read() can be called to service the buffer)
LineConnected, ///< Indicates that a port that was unoccupied has had an E1/T1 line plugged in
LineDisconnected, ///< Indicates that a port that had an E1/T1 line plugged in has had the line disconnected
TransmitBufferAvailable ///< Indicated that a port has at least one free Transmit buffer.
};
///////////////////////////////////////////////////////////////////////////////////////////////
/// \struct PortEvent
/// \brief Structure representing an event that occurred on a port within the card
///////////////////////////////////////////////////////////////////////////////////////////////
struct PortEvent {
PortEventType EventType; ///< Status code indicating the type of event that occured
sangoma_wait_obj_t *EventHandle; ///< Handle to the Sangoma waitable object
PortEvent(); ///< Constructor
};
///////////////////////////////////////////////////////////////////////////////////////////////
/// \struct BufferSettings
/// \brief Structure containing settings for configuring the host memory buffers assigned to a
/// Sangoma port. Data is transferred to host memory via DMA, and an event is set to indicate
/// that the buffers are full and read to be read, so it is inportant to configure the host
/// memory buffers to the needs of your application. Sangoma defines a MRU/MTU of 8188 bytes
/// (the maximum size of an HDLC frame) and assigns buffers of this size to a port (although
/// data is always read or written in even frames of 8184 bytes for T1 and 8160 for E1
/// (32 timeslots).
///
/// The size of the buffers will be configurable in multiples of this 8188 bytes enforced
/// by hardware, such that 8188 * BufferMultiplierFactor = BufferSize (i.e. a BufferMultiplierFactor
/// of 4 will result in BufferSize = 4 * 8188 = 32752 byes).
///
/// Multiple buffers are assigned for transmit and receiving to queue a certain amount of
/// data. These are configured by setting NumberOfBuffersPerPort. If you intend to only
/// use a SangomaPort for either receive or transmit, the NumberOfBuffersPerPort for that
/// set of buffers can be set to 0 (SangomaPort also has special constructors which are
/// for receive-only or transmit-only ports).
///////////////////////////////////////////////////////////////////////////////////////////////
struct BufferSettings {
unsigned int BufferMultiplierFactor; ///< Number to multiply the MAX_SANGOMA_BUFFER_SIZE by in order to get the size of the buffers allocated in host memory
unsigned int NumberOfBuffersPerPort; ///< Number of buffers in host memory that will be dedicated to with receiving or transmitting data on this port
};
///////////////////////////////////////////////////////////////////////////////////////////////
/// \class SangomaPort
/// \brief This class encapsulates the functionality of a physical Sangoma port found on the
/// A104 and A108 card models.
/// \author J. Markwordt
/// \date 10/03/2007
///////////////////////////////////////////////////////////////////////////////////////////////
class SangomaPort {
public:
SangomaPort(const unsigned int card_number, const unsigned int port_number,
const BufferSettings & ReceiveBufferSettings,
const BufferSettings & TransmitBufferSettings); ///< Constructor
~SangomaPort(); ///< Destructor
bool Open(const Configuration & config); ///< Opens this port, setting its current configuration to the one provided
bool Close(); ///< Closes this port
int Read(unsigned int out_flags); ///< Reads Rx data or an Event and places them in the ReceiveBuffer.
///< Returns reason for wait object being signaled
unsigned char *GetRxDataBuffer(); ///< Returns a pointer to received data.
unsigned int GetRxDataLength(); ///< Returns length of received data.
int Write(unsigned char* p_source_buffer, const unsigned int bytes_to_write); ///< Writes the specified number of bytes from the source buffer to the port
SynchronizationStatus GetSynchronizationStatus(); ///< Returns the status of port synchronization
//SynchronizationStatus SyncStatus; ///< Stores current status of port synchronization indicated by Connected/Disconnected events
unsigned int GetPortNumber() const; ///< Returns this port's number
Configuration GetConfiguration() const; ///< Returns the current configuration of the port
PortEvent GetEvent() const; ///< Return the PortEvent associated with this port
bool GetIsOpen(); ///< Return true if this port is currently open, false otherwise
DriverVersion GetDriverVersion(); ///< Returns this port's driver version number
Statistics GetStatistics(); ///< Get the statistics for this port
void ClearStatistics(); ///< Clear the statistics for this port
void FlushBuffers(); ///< Clear the statistics for this port
Alarms GetAlarms(); ///< Retrieves the alarms from the hardware for this port
std::string GetLastError() const; ///< Returns a description of the last error that occurred (NO_ERROR_OCCURRED if the last command was successful)
PortBuffer *ReceiveBuffer; ///< Buffers allocated to receive data for this port
PortBuffer *TransmitBuffer; ///< Buffers allocated to transmit data for this port
unsigned int GetUnmappedPortNumber();
int SetAndOpenTxFile(char *szTxFileName); ///< Open a file which will be continuesly transmitted
int WriteChunkOfTxFile(); ///< Transmit a chunk of the TxFile
int LineLoopbackEnable(); ///< Enable line loopback for testing. All transmitted data will be also received locally. Requires the Port to be in Master clock mode.
int LineLoopbackDisable(); ///< Disable line loopback which was enabled by SangomaPort::LineLoopbackEnable()
unsigned int rx_discard_counter; ///< Number of rx buffers to discard after LineConnected event (the buffers may contain idle data).
unsigned int rx_cnt; ///< Number of rx buffers to discard after LineConnected event (the buffers may contain idle data).
unsigned int sync_cnt; ///< Number of rx buffers to discard after LineConnected event (the buffers may contain idle data).
unsigned int rx_len; ///< Number of rx buffers to discard after LineConnected event (the buffers may contain idle data).
private:
// Copy constructor and assigment operator are made private
// and left unimplemented to ensure that the SangomaPort object cannot be copied
SangomaPort(const SangomaPort& port);
SangomaPort& operator=(const SangomaPort& rhs);
unsigned int CardNumber; ///< The number of the SangomaCard that this port is associated with (zero-indexed)
unsigned int PortNumber; ///< The number assigned to this port (zero-indexed)
PortEvent Event; ///< Event used to trigger port events with
bool IsOpen; ///< true if this port is currently open, false otherwise
Configuration CurrentConfiguration; ///< The current configuration of this port
Statistics PortStatistics; ///< Statistics related to this port (made member because some are maintained by the class, some are maintained by the hardware)
std::string LastError; ///< String description of the last error that occurred (should be set if an error occurs in any SangomaPort member functions, or NO_ERROR_OCCURRED if successful)
BufferSettings ReceiveBufferSettings, TransmitBufferSettings;
sangoma_interface *SangomaInterface;
CRITICAL_SECTION cs_CriticalSection;
void EnterPortCriticalSection();
void LeavePortCriticalSection();
int TryEnterPortCriticalSection();
int SetPortConfiguration(const Configuration & config);
/*! API header for rx data */
wp_api_hdr_t rxhdr;
/*! API header for tx data */
wp_api_hdr_t txhdr;
/*! API command structure used to execute API commands. This command structure is used with libsangoma library */
wanpipe_api_t wp_api;
FILE *pTxFile;
int TxMtu;
};
}// namespace Sangoma
#endif //_SANGOMA_PORT_H

View File

@ -1,427 +0,0 @@
//////////////////////////////////////////////////////////////////////
// driver_configurator.cpp: implementation of the driver_configurator class.
//
// Author : David Rokhvarg <davidr@sangoma.com>
//////////////////////////////////////////////////////////////////////
#include "driver_configurator.h"
#define DBG_CFG if(0)printf
#define _DBG_CFG if(0)printf
#define INFO_CFG if(0)printf
#define _INFO_CFG if(0)printf
#define ERR_CFG printf("Error:%s():line:%d: ", __FUNCTION__, __LINE__);printf
#define _ERR_CFG if(1)printf
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
driver_configurator::driver_configurator()
{
DBG_CFG("%s()\n", __FUNCTION__);
wp_handle = INVALID_HANDLE_VALUE;
}
driver_configurator::~driver_configurator()
{
DBG_CFG("%s()\n", __FUNCTION__);
cleanup();
}
void driver_configurator::cleanup()
{
DBG_CFG("%s()\n", __FUNCTION__);
if(wp_handle != INVALID_HANDLE_VALUE){
sangoma_close(&wp_handle);
wp_handle = INVALID_HANDLE_VALUE;
}
}
//GET current configuraion of the API driver
int driver_configurator::get_configuration(port_cfg_t *out_port_cfg)
{
DBG_CFG("%s()\n", __FUNCTION__);
int err = sangoma_driver_port_get_config(wp_handle, out_port_cfg, wp_number);
if (err) {
return 1;
}
return 0;
}
//SET new configuration of the API driver
int driver_configurator::set_configuration(port_cfg_t *port_cfg)
{
port_management_struct_t port_mgmnt;
int err;
DBG_CFG("%s()\n", __FUNCTION__);
////////////////////////////////////////////////////////////////////////////////////
memset(&port_mgmnt, 0x00, sizeof(port_mgmnt));
port_mgmnt.operation_status = SANG_STATUS_GENERAL_ERROR;
err = sangoma_driver_port_stop(wp_handle, &port_mgmnt, wp_number);
if (err) {
ERR_CFG("%s: failed to stop Port for re-configuration!\n", wanpipe_name_str);
return 1;
}
switch(port_mgmnt.operation_status)
{
case SANG_STATUS_SUCCESS:
case SANG_STATUS_CAN_NOT_STOP_DEVICE_WHEN_ALREADY_STOPPED:
//OK
break;
default:
ERR_CFG("%s: %s(): return code: %s\n", wanpipe_name_str,
__FUNCTION__, SDLA_DECODE_SANG_STATUS(port_mgmnt.operation_status));
return 1;
}
////////////////////////////////////////////////////////////////////////////////////
err = sangoma_driver_port_set_config(wp_handle, port_cfg, wp_number);
if (err) {
ERR_CFG("%s: failed to set Port configuration!\n", wanpipe_name_str);
return 1;
}
DBG_CFG("%s(): return code: %s (%d)\n", __FUNCTION__,
SDLA_DECODE_SANG_STATUS(port_cfg->operation_status), port_cfg->operation_status);
switch(port_cfg->operation_status)
{
case SANG_STATUS_DEVICE_BUSY:
ERR_CFG("Error: open handles exist for '%s_IF\?\?' interfaces!\n", wanpipe_name_str);
return port_cfg->operation_status;
case SANG_STATUS_SUCCESS:
//OK
break;
default:
//error
return 1;
}
////////////////////////////////////////////////////////////////////////////////////
memset(&port_mgmnt, 0x00, sizeof(port_mgmnt));
port_mgmnt.operation_status = SANG_STATUS_GENERAL_ERROR;
err=sangoma_driver_port_start(wp_handle, &port_mgmnt, wp_number);
if(err || port_mgmnt.operation_status){
ERR_CFG("%s: failed to start Port after re-configuration!\n", wanpipe_name_str);
return 1;
}
return 0;
}
int driver_configurator::init(unsigned int wanpipe_number, unsigned int port_number)
{
DBG_CFG("%s():\n", __FUNCTION__);
//this the MAPPED port number
wp_number = wanpipe_number + port_number + 1;
wp_snprintf(wanpipe_name_str, sizeof(wanpipe_name_str), "wanpipe%d", wp_number);
DBG_CFG("%s\n", wanpipe_name_str);
wp_handle = sangoma_open_driver_ctrl(wp_number);
if(wp_handle == INVALID_HANDLE_VALUE){
// ERR_CFG("Error: failed to open %s!!\n", wanpipe_name_str);
return 1;
}
return 0;
}
int driver_configurator::print_port_cfg_structure(port_cfg_t *port_cfg)
{
wandev_conf_t *wandev_conf = &port_cfg->wandev_conf;
sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg;
wanif_conf_t *wanif_conf = &port_cfg->if_cfg[0];
DBG_CFG("%s()\n", __FUNCTION__);
_INFO_CFG("\n================================================\n");
INFO_CFG("Card Type\t: %s(%d)\n", SDLA_DECODE_CARDTYPE(wandev_conf->card_type),
wandev_conf->card_type);/* Sangoma Card type - S514, S518 or AFT.*/
INFO_CFG("Number of TimeSlot Groups: %d\n", port_cfg->num_of_ifs);
INFO_CFG("MTU\t\t: %d\n", wandev_conf->mtu);
print_sdla_fe_cfg_t_structure(sdla_fe_cfg);
for(unsigned int i = 0; i < port_cfg->num_of_ifs; i++){
_INFO_CFG("\n************************************************\n");
_INFO_CFG("Configration of Group Number %d:\n", i);
print_wanif_conf_t_structure(&wanif_conf[i]);
}
return 0;
}
int driver_configurator::print_sdla_fe_cfg_t_structure(sdla_fe_cfg_t *sdla_fe_cfg)
{
_INFO_CFG("\n################################################\n");
INFO_CFG("MEDIA\t\t: %s\n", MEDIA_DECODE(sdla_fe_cfg));
if(FE_MEDIA(sdla_fe_cfg) == WAN_MEDIA_T1 || FE_MEDIA(sdla_fe_cfg) == WAN_MEDIA_E1){
INFO_CFG("Line CODE\t: %s\n", LCODE_DECODE(sdla_fe_cfg));
INFO_CFG("Framing\t\t: %s\n", FRAME_DECODE(sdla_fe_cfg));
INFO_CFG("Clock Mode\t: %s\n", TECLK_DECODE(sdla_fe_cfg));
INFO_CFG("Clock Reference port: %d (0 - not used)\n", FE_REFCLK(sdla_fe_cfg));
INFO_CFG("Signalling Insertion Mode: %s\n", TE1SIG_DECODE(sdla_fe_cfg));
INFO_CFG("High Impedance Mode: %s\n",
(FE_HIMPEDANCE_MODE(sdla_fe_cfg) == WANOPT_YES ? "Yes":"No"));
INFO_CFG("FE_RX_SLEVEL: %d\n", FE_RX_SLEVEL(sdla_fe_cfg));
}//if()
INFO_CFG("TDMV LAW\t: %s\n", (FE_TDMV_LAW(sdla_fe_cfg) == WAN_TDMV_MULAW ?"MuLaw":"ALaw"));
switch(FE_MEDIA(sdla_fe_cfg))
{
case WAN_MEDIA_T1:
INFO_CFG("LBO\t\t: %s\n", LBO_DECODE(sdla_fe_cfg));
break;
case WAN_MEDIA_E1:
break;
default:
break;
}
return 0;
}
int driver_configurator::print_wanif_conf_t_structure(wanif_conf_t *wanif_conf)
{
INFO_CFG("Operation Mode\t: %s\n", wanif_conf->usedby);
INFO_CFG("Timeslot BitMap\t: 0x%08X\n", wanif_conf->active_ch);
INFO_CFG("Line Mode\t: %s\n",
(wanif_conf->hdlc_streaming == WANOPT_YES ? "HDLC":"BitStream"));
INFO_CFG("MTU\\MRU\t\t: %d\n", wanif_conf->mtu);
return 0;
}
int driver_configurator::get_hardware_info(hardware_info_t *hardware_info)
{
DBG_CFG("%s()\n", __FUNCTION__);
port_management_struct_t port_management;
int err=sangoma_driver_get_hw_info(wp_handle,&port_management, wp_number);
if (err) {
ERR_CFG("Error: failed to get hw info for wanpipe%d!\n", wp_number);
return 1;
}
memcpy(hardware_info,port_management.data,sizeof(hardware_info_t));
return 0;
}
int driver_configurator::get_driver_version(wan_driver_version_t *version)
{
DBG_CFG("%s()\n", __FUNCTION__);
port_management_struct_t port_management;
int err = sangoma_driver_get_version(wp_handle, &port_management, wp_number);
if (err) {
ERR_CFG("Error: failed to get Driver Version from wanpipe%d!\n", wp_number);
return 1;
}
memcpy(version, port_management.data, sizeof(*version));
return 0;
}
int driver_configurator::push_a_card_into_wanpipe_info_array(
wanpipe_instance_info_t *wanpipe_info_array,
hardware_info_t *new_hw_info)
{
unsigned int card_ind;
hardware_info_t *tmp_hw_info;
//check this card is not in the array already
for(card_ind = 0; card_ind < MAX_CARDS; card_ind++){
tmp_hw_info = &wanpipe_info_array[card_ind].hardware_info;
if( (new_hw_info->pci_bus_number == tmp_hw_info->pci_bus_number) &&
(new_hw_info->pci_slot_number == tmp_hw_info->pci_slot_number)){
//already in array. not an error.
DBG_CFG("already in array.\n");
return 1;
}
}
//find an empty slot in the array and place the new card there
for(card_ind = 0; card_ind < MAX_CARDS; card_ind++){
tmp_hw_info = &wanpipe_info_array[card_ind].hardware_info;
if(tmp_hw_info->card_model == -1){
//found an empty slot in array
memcpy(tmp_hw_info, new_hw_info, sizeof(hardware_info_t));
return 0;
}
}
//too many cards in the computer.
INFO_CFG("Warning: number of cards in the computer is greater than the maximum of %d.\n",
MAX_CARDS);
return 2;
}
//
//Scan all running wanpipes, check which ones are on the same card,
//figure out how many physical cards installed.
//
//Returns: -1 - if error.
// number of cards, starting from zero.
int driver_configurator::scan_for_sangoma_cards(wanpipe_instance_info_t *wanpipe_info_array, int card_model)
{
int card_counter = 0, wp_ind;
hardware_info_t hardware_info;
//initialize hardware information array.
memset(wanpipe_info_array, -1, sizeof(wanpipe_instance_info_t)*MAX_CARDS);
DBG_CFG("%s(): wanpipe_info_array: 0x%p\n", __FUNCTION__, wanpipe_info_array);
for(wp_ind = 0; wp_ind < (MAX_CARDS * MAX_PORTS_PER_CARD); wp_ind++){
if(init(wp_ind, 0)){
continue;
}
if(get_hardware_info(&hardware_info)){
//Port was opened but could not read hw info - dont add the port to the list
//and also consider there are no more ports, so exit the loop.
break;
}
DBG_CFG("card_model : %s (0x%08X)\n",
SDLA_ADPTR_NAME(hardware_info.card_model), hardware_info.card_model);
DBG_CFG("firmware_version\t: 0x%02X\n", hardware_info.firmware_version);
DBG_CFG("pci_bus_number\t\t: %d\n", hardware_info.pci_bus_number);
DBG_CFG("pci_slot_number\t\t: %d\n", hardware_info.pci_slot_number);
if(card_model == hardware_info.card_model){
if(push_a_card_into_wanpipe_info_array(wanpipe_info_array, &hardware_info) == 0){
//At this point we know: 1. WANPIPE number, for example WANPIPE1.
// 2. Card type, for example A104.
//It allows to figure out Device Name of each port on the card.
//For example: for A104 it will be WANPIPE1, WANPIPE2, WANPIPE3, WANPIPE4
wanpipe_info_array[card_counter].wanpipe_number = wp_ind;
DBG_CFG("%s(): wp_ind: %u\n", __FUNCTION__, wp_ind);
card_counter++;
}
}else{
DBG_CFG("Found a Card but Card Model is different from what was searched for.\n");
}
//it is important to Close each port which was opened during the scan.
cleanup();
}//for()
return card_counter;
}
//function to switch between T1 and E1
int driver_configurator::set_t1_e1_configuration(sdla_fe_cfg_t *in_sdla_fe_cfg, buffer_settings_t *buffer_settings)
{
wandev_conf_t *wandev_conf = &port_cfg.wandev_conf;
sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg;
wan_tdmv_conf_t *tdmv_cfg = &wandev_conf->tdmv_conf;
wanif_conf_t *wanif_cfg = &port_cfg.if_cfg[0];
hardware_info_t tmp_hardware_info;
DBG_CFG("%s()\n", __FUNCTION__);
memset(&port_cfg, 0x00, sizeof(port_cfg_t));
get_hardware_info(&tmp_hardware_info);
//copy T1/E1 configuration into the Driver configuration structure.
memcpy(sdla_fe_cfg, in_sdla_fe_cfg, sizeof(sdla_fe_cfg_t));
port_cfg.buffer_settings.buffer_multiplier_factor = buffer_settings->buffer_multiplier_factor;
port_cfg.buffer_settings.number_of_buffers_per_api_interface = buffer_settings->number_of_buffers_per_api_interface;
wandev_conf->fe_cfg.cfg.te_cfg.active_ch = 0xFFFFFFFF;//a constant
port_cfg.num_of_ifs = 1;//1 Group always
///////////////////////////////////////////////////////////////////////////////
wandev_conf->config_id = WANCONFIG_AFT_TE1;
wandev_conf->magic = ROUTER_MAGIC;
wandev_conf->mtu = 2048;
DBG_CFG("%s(): slot: %d, bus: %d, port_number:%d\n", __FUNCTION__,
tmp_hardware_info.pci_slot_number, tmp_hardware_info.pci_bus_number,
tmp_hardware_info.port_number);
wandev_conf->PCI_slot_no = tmp_hardware_info.pci_slot_number;
wandev_conf->pci_bus_no = tmp_hardware_info.pci_bus_number;
wandev_conf->card_type = WANOPT_AFT; //m_DeviceInfoData.card_model;
wanif_cfg->hdlc_streaming = WANOPT_NO;//BitStream
wanif_cfg->magic = ROUTER_MAGIC;
sprintf(wanif_cfg->usedby, SDLA_DECODE_USEDBY_FIELD(TDM_SPAN_VOICE_API));//TDM_SPAN_VOICE_API - span mode supported by libsangoma.dll.
wanif_cfg->u.aft.idle_flag=0xFF;
sprintf(wanif_cfg->name, "w%dg1", wp_number);
///////////////////////////////////////////////////////////////////////////////
port_cfg.port_no = FE_LINENO(sdla_fe_cfg) = tmp_hardware_info.port_number;
//
//Set MTU/MRU per-TIMESLOT - the API driver will multiply this value by the
//number of timeslots this interface is using - t1:24, e1:31 or 32.
//The 'buffer_multiplier_factor' value will control how many of these
//buffers will be received on each RX indication.
//
if(FE_MEDIA(sdla_fe_cfg) == WAN_MEDIA_T1){
//320*24=7680
wanif_cfg->mtu = wanif_cfg->u.aft.mtu = wanif_cfg->u.aft.mru = 320;
} else {
//240*31=7440, 240*32=7680
wanif_cfg->mtu = wanif_cfg->u.aft.mtu = wanif_cfg->u.aft.mru = 240;
}
if(FE_MEDIA(sdla_fe_cfg) == WAN_MEDIA_T1){
//T1, 1 Group of 24 Timeslots.
wanif_cfg->active_ch = 0xFFFFFF;
FE_TDMV_LAW(sdla_fe_cfg) = WAN_TDMV_MULAW;
}else if(FE_MEDIA(sdla_fe_cfg) == WAN_MEDIA_E1){
//E1, 1 Group of 31 or 32 Timeslots.
//API driver will automatically adjust timeslot bitmap for "framed" e1
wanif_cfg->active_ch = 0xFFFFFFFF;
FE_TDMV_LAW(sdla_fe_cfg) = WAN_TDMV_ALAW;
FE_LBO(sdla_fe_cfg) = WAN_T1_LBO_NONE;//important to set to a valid value!!
}else{
ERR_CFG("%s(): Error: invalid Media Type %d!\n", __FUNCTION__, sdla_fe_cfg->media);
return 1;
}
tdmv_cfg->span_no = (unsigned char)wp_number;
print_port_cfg_structure(&port_cfg);
return set_configuration(&port_cfg);
}

View File

@ -1,86 +0,0 @@
//////////////////////////////////////////////////////////////////////
// driver_configurator.h: interface for the driver_configurator class.
//
// Author : David Rokhvarg <davidr@sangoma.com>
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_DRIVER_CONFIGURATOR_H__115A6EC1_518C_45E9_AA55_148A8D999B61__INCLUDED_)
#define AFX_DRIVER_CONFIGURATOR_H__115A6EC1_518C_45E9_AA55_148A8D999B61__INCLUDED_
#if defined(__WINDOWS__)
# include <windows.h>
# include <conio.h>
#elif defined(__LINUX__)
# include <errno.h>
# include <fcntl.h>
# include <string.h>
# include <ctype.h>
# include <sys/stat.h>
# include <sys/ioctl.h>
# include <sys/types.h>
# include <dirent.h>
# include <unistd.h>
# include <sys/socket.h>
# include <netdb.h>
# include <sys/un.h>
# include <sys/wait.h>
# include <unistd.h>
# include <signal.h>
# include <time.h>
# include <curses.h>
#else
# error Unsupported OS
#endif
#include <stdio.h>
#include <stddef.h> //for offsetof()
#include "libsangoma.h"
#include "wanpipe_api.h"
#define MAX_CARDS 16
#define MAX_PORTS_PER_CARD 16
class driver_configurator
{
public:
driver_configurator();
virtual ~driver_configurator();
int get_hardware_info(hardware_info_t *hardware_info);
int get_driver_version(wan_driver_version_t *version);
int set_t1_e1_configuration(sdla_fe_cfg_t *sdla_fe_cfg, buffer_settings_t *buffer_settings);
int init(unsigned int wanpipe_number, unsigned int port_number);
//GET current configuraion of the API driver
int get_configuration(port_cfg_t *port_cfg);
//SET new configuration of the API driver
int set_configuration(port_cfg_t *port_cfg);
//Function to print contents of 'port_cfg_t' structure.
int print_port_cfg_structure(port_cfg_t *port_cfg);
int print_sdla_fe_cfg_t_structure(sdla_fe_cfg_t *sdla_fe_cfg);
int print_wanif_conf_t_structure(wanif_conf_t *wanif_conf);
int scan_for_sangoma_cards(wanpipe_instance_info_t *wanpipe_info_array, int card_model);
private:
port_cfg_t port_cfg;
unsigned int wp_number;
char wanpipe_name_str[WAN_DRVNAME_SZ*2];
sng_fd_t wp_handle;
//reverse actions of init()
void cleanup();
int push_a_card_into_wanpipe_info_array(wanpipe_instance_info_t *wanpipe_info_array, hardware_info_t *new_hw_info);
};
#endif // !defined(AFX_DRIVER_CONFIGURATOR_H__115A6EC1_518C_45E9_AA55_148A8D999B61__INCLUDED_)

View File

@ -1,840 +0,0 @@
//////////////////////////////////////////////////////////////////////
// sangoma_interface.cpp: interface for Sangoma API driver.
//
// Author : David Rokhvarg <davidr@sangoma.com>
//////////////////////////////////////////////////////////////////////
#include "sangoma_interface.h"
#include "driver_configurator.h"
#define DBG_IFACE if(0)printf
#define INFO_IFACE if(0)printf
#define ERR_IFACE printf("Error: %s(): line:%d :", __FUNCTION__, __LINE__);printf
#define WRN_IFACE printf("Warning: %s(): line:%d :", __FUNCTION__, __LINE__);printf
#define DBG_PORT_NUM if(0)printf
#define IFACE_FUNC() if(0)printf("%s():line:%d\n", __FUNCTION__, __LINE__)
#define DO_COMMAND(wan_udp) DoManagementCommand(sangoma_dev, &wan_udp);
sangoma_interface::sangoma_interface(int wanpipe_num, int interface_num)
{
DBG_IFACE("%s()\n", __FUNCTION__);
wanpipe_number = wanpipe_num;
interface_number = interface_num;
DBG_PORT_NUM("%s(): (1) wanpipe_number: %i, interface_number: %i\n",
__FUNCTION__, wanpipe_number, interface_number);
memset(interface_name, 0x00, DEV_NAME_LEN);
memset(&drv_version, 0x00, sizeof(drv_version));
//////////////////////////////////////////////////////////////////
driver_configurator drv_cfg;
hardware_info_t hardware_info;
card_model = A104_ADPTR_4TE1;//default
if(drv_cfg.init(wanpipe_number, 0) == 0){
if(drv_cfg.get_hardware_info(&hardware_info) == 0){
DBG_IFACE("card_model : %s (0x%08X)\n",
SDLA_ADPTR_NAME(hardware_info.card_model), hardware_info.card_model);
DBG_IFACE("firmware_version\t: 0x%02X\n", hardware_info.firmware_version);
DBG_IFACE("pci_bus_number\t\t: %d\n", hardware_info.pci_bus_number);
DBG_IFACE("pci_slot_number\t\t: %d\n", hardware_info.pci_slot_number);
card_model = hardware_info.card_model;
}
} else {
ERR_IFACE("Failed to get Card Model!\n");
exit(1);
}
//G3 requred port numbers on A108 to be different from what Sangoma API provides.
//Physical Port 0: Ports 0 and 1 (not 0 and 4)
//Physical Port 1: Ports 2 and 3 (not 1 and 5)
//Physical Port 2: Ports 4 and 5 (not 2 and 6)
//Physical Port 3: Ports 6 and 7 (not 3 and 7)
if(card_model == A108_ADPTR_8TE1){
DBG_PORT_NUM("%s(): card_model == A108_ADPTR_8TE1\n", __FUNCTION__);
//correct the interface_number for A108 accoringly
switch(interface_num)
{
case 0:
interface_number = 0;
break;
case 1:
interface_number = 4;
break;
case 2:
interface_number = 1;
break;
case 3:
interface_number = 5;
break;
case 4:
interface_number = 2;
break;
case 5:
interface_number = 6;
break;
case 6:
interface_number = 3;
break;
case 7:
interface_number = 7;
break;
}
}
DBG_PORT_NUM("%s(): (2) wanpipe_number: %i, MAPPED interface_number: %i\n",
__FUNCTION__, wanpipe_number, interface_number);
//Form the MAPPED Interface Name from Wanpipe Number and Interface Index (i.e. wanpipe1_if1).
wp_snprintf(interface_name, DEV_NAME_LEN, "\\\\.\\WANPIPE%d_IF%d",
wanpipe_number + 1 + interface_number, 1);
DBG_PORT_NUM( "Using Device Name: %s\n", interface_name);
//////////////////////////////////////////////////////////////////
if(drv_cfg.get_driver_version(&drv_version)){
ERR_IFACE("Failed to get Driver Version!\n");
exit(1);
}
check_api_driver_version();
//////////////////////////////////////////////////////////////////
sangoma_dev = INVALID_HANDLE_VALUE;
sng_wait_obj = NULL;
//////////////////////////////////////////////////////////////////
//receive stuff
rx_frames_count = 0;
rx_bytes_count = 0;
//for counting frames with CRC/Abort errors
bad_rx_frames_count = 0;
//////////////////////////////////////////////////////////////////
//transmit stuff
tx_bytes_count = 0;
tx_frames_count = 0;
tx_test_byte = 0;
//////////////////////////////////////////////////////////////////
//IOCTL management structures and variables
protocol_cb_size = sizeof(wan_mgmt_t)+sizeof(wan_cmd_t)+1;
wan_protocol = 0;
adapter_type = 0;
}
sangoma_interface::~sangoma_interface()
{
DBG_IFACE("%s()\n", __FUNCTION__);
cleanup();
}
HANDLE sangoma_interface::open_first_interface_of_a_mapped_port()
{
sng_fd_t hTmp;
int span, chan;
span = get_mapped_span_number();//wanpipe_number + 1 + interface_number;
chan = 1;/* wanpipe1_if1... */
DBG_IFACE("%s(): opening Span: %d, Chan: %d\n", __FUNCTION__, span, chan);
hTmp = sangoma_open_api_span_chan(span, chan);
if(hTmp == INVALID_HANDLE_VALUE){
DBG_IFACE("%s(): failed to open Span: %d, Chan: %d!\n", __FUNCTION__, span, chan);
}
return hTmp;
}
int sangoma_interface::init()
{
DBG_IFACE("%s()\n", __FUNCTION__);
DBG_IFACE("interface_name: %s, wanpipe_number:%d, interface_number:%d\n", interface_name, wanpipe_number, interface_number);
#if defined(__LINUX__)
//under Linux must wait for interfaces to be available for opening
sangoma_interface_wait_up(get_mapped_span_number(), 1/*chan*/, 2/* 2 second timeout */);
#endif
////////////////////////////////////////////////////////////////////////////
//open handle for reading and writing data, for events reception and other commands
sangoma_dev = open_first_interface_of_a_mapped_port();
if (sangoma_dev == INVALID_HANDLE_VALUE){
ERR_IFACE( "Unable to open %s for Rx/Tx!\n", interface_name);
return 1;
}
DBG_IFACE("Span %i - creatig an object\n",get_mapped_span_number());
if(SANG_ERROR(sangoma_wait_obj_create(&sng_wait_obj, sangoma_dev, SANGOMA_DEVICE_WAIT_OBJ_SIG))){
ERR_IFACE("Failed to create 'Tx/Rx/Event WAIT_OBJECT' for %s\n", interface_name);
return 1;
}
////////////////////////////////////////////////////////////////////////////
//get current protocol
if(GetWANConfig() == WAN_FALSE){
ERR_IFACE( "Failed to get current protocol!\n");
goto init_error;
}
////////////////////////////////////////////////////////////////////////////
//get Front End Type (T1/E1/Analog...)
if (get_fe_type(&adapter_type) == WAN_FALSE){
ERR_IFACE( "Failed to get Front End Type!\n");
goto init_error;
}
////////////////////////////////////////////////////////////////////////////
#if 0
//For Debugging only print the interface configuration.
if_cfg_t wanif_conf_struct;
if(get_interface_configuration(&wanif_conf_struct)){
ERR_IFACE( "Failed to get Interface Configuration!\n");
return 1;
}
#endif
return 0;
init_error:
if(sng_wait_obj){
sangoma_wait_obj_delete(&sng_wait_obj);
sng_wait_obj = NULL;
}
return 1;
}
//
//cleanup() - reverse everything what was done in init().
//
//It is very important to close ALL open
//handles, because the API will continue
//receive data until the LAST handel is closed.
int sangoma_interface::cleanup()
{
DBG_IFACE("%s()\n", __FUNCTION__);
if(sng_wait_obj){
sangoma_wait_obj_delete(&sng_wait_obj);
sng_wait_obj = NULL;
}
if(sangoma_dev != INVALID_HANDLE_VALUE){
DBG_IFACE( "Closing Rx/Tx fd.\n");
sangoma_close(&sangoma_dev);
sangoma_dev = INVALID_HANDLE_VALUE;
}
return 0;
}
int sangoma_interface::GetWANConfig( void )
{
int err = WAN_TRUE;
/* Get Protocol type */
wan_udp.wan_udphdr_command = WAN_GET_PROTOCOL;
wan_udp.wan_udphdr_data_len = 0;
DO_COMMAND(wan_udp);
if (wan_udp.wan_udphdr_return_code){
ERR_IFACE( "Error: Command WAN_GET_PROTOCOL failed! return code: 0x%X",
wan_udp.wan_udphdr_return_code);
return WAN_FALSE;
}
wan_protocol = wan_udp.wan_udphdr_data[0];
DBG_IFACE( "Device %s running protocol: %s\n",
interface_name, DECODE_PROT(wan_protocol));
return err;
}
int sangoma_interface::get_fe_type(unsigned char* adapter_type)
{
int err = WAN_TRUE;
/* Read Adapter Type */
wan_udp.wan_udphdr_command = WAN_GET_MEDIA_TYPE;
wan_udp.wan_udphdr_data[0] = WAN_MEDIA_NONE;
wan_udp.wan_udphdr_data_len = 0;
DO_COMMAND(wan_udp);
if(wan_udp.wan_udphdr_return_code){
ERR_IFACE( "Error: Command WAN_GET_MEDIA_TYPE failed! return code: 0x%X",
wan_udp.wan_udphdr_return_code);
return WAN_FALSE;
}
*adapter_type = get_wan_udphdr_data_byte(0);
DBG_IFACE( "Front End Type: ");
switch(*adapter_type)
{
case WAN_MEDIA_NONE:
DBG_IFACE( "Serial");
break;
case WAN_MEDIA_T1:
DBG_IFACE( "T1");
break;
case WAN_MEDIA_E1:
DBG_IFACE( "E1");
break;
case WAN_MEDIA_56K:
DBG_IFACE( "56K");
break;
case WAN_MEDIA_FXOFXS:
DBG_IFACE( "Aanalog");
break;
default:
DBG_IFACE( "Unknown");
err = WAN_FALSE;
}
DBG_IFACE( "\n");
return err;
}
//return POINTER to data at offset 'off'
unsigned char* sangoma_interface::get_wan_udphdr_data_ptr(unsigned char off)
{
unsigned char *p_data = (unsigned char*)&wan_udp.wan_udphdr_data[0];
p_data += off;
return p_data;
}
unsigned char sangoma_interface::set_wan_udphdr_data_byte(unsigned char off, unsigned char data)
{
unsigned char *p_data = (unsigned char*)&wan_udp.wan_udphdr_data[0];
p_data[off] = data;
return 0;
}
//return DATA at offset 'off'
unsigned char sangoma_interface::get_wan_udphdr_data_byte(unsigned char off)
{
unsigned char *p_data = (unsigned char*)&wan_udp.wan_udphdr_data[0];
return p_data[off];
}
int sangoma_interface::read_te1_56k_stat(unsigned long *p_alarms)
{
unsigned char* data = NULL;
unsigned long alarms = 0x00;
sdla_te_pmon_t* pmon = NULL;
DBG_IFACE("%s()\n", __FUNCTION__);
memset(&wan_udp, 0x00, sizeof(wan_udp));
switch(adapter_type)
{
case WAN_MEDIA_T1:
case WAN_MEDIA_E1:
case WAN_MEDIA_56K:
;//do nothing
break;
default:
ERR_IFACE( "Command invalid for Adapter Type %d.\n", adapter_type);
return 1;
}
/* Read T1/E1/56K alarms and T1/E1 performance monitoring counters */
wan_udp.wan_udphdr_command = WAN_FE_GET_STAT;
wan_udp.wan_udphdr_data_len = 0;
DO_COMMAND(wan_udp);
if (wan_udp.wan_udphdr_return_code != 0){
ERR_IFACE( "Failed to read T1/E1/56K statistics.\n");
return 1;
}
data = get_wan_udphdr_data_ptr(0);
*p_alarms = alarms = *(unsigned long*)data;
if (adapter_type == WAN_MEDIA_T1 || adapter_type == WAN_MEDIA_E1){
DBG_IFACE( "***** %s: %s Alarms *****\n\n",
interface_name, (adapter_type == WAN_MEDIA_T1) ? "T1" : "E1");
DBG_IFACE( "ALOS:\t%s\t| LOS:\t%s\n",
WAN_TE_ALOS_ALARM(alarms),
WAN_TE_LOS_ALARM(alarms));
DBG_IFACE( "RED:\t%s\t| AIS:\t%s\n",
WAN_TE_RED_ALARM(alarms),
WAN_TE_AIS_ALARM(alarms));
if (adapter_type == WAN_MEDIA_T1){
DBG_IFACE( "YEL:\t%s\t| OOF:\t%s\n",
WAN_TE_YEL_ALARM(alarms),
WAN_TE_OOF_ALARM(alarms));
}else{
DBG_IFACE( "OOF:\t%s\n",
WAN_TE_OOF_ALARM(alarms));
}
}else{
DBG_IFACE( "***** %s: 56K CSU/DSU Alarms *****\n\n\n", interface_name);
DBG_IFACE( "In Service:\t\t%s\tData mode idle:\t\t%s\n",
INS_ALARM_56K(alarms),
DMI_ALARM_56K(alarms));
DBG_IFACE( "Zero supp. code:\t%s\tCtrl mode idle:\t\t%s\n",
ZCS_ALARM_56K(alarms),
CMI_ALARM_56K(alarms));
DBG_IFACE( "Out of service code:\t%s\tOut of frame code:\t%s\n",
OOS_ALARM_56K(alarms),
OOF_ALARM_56K(alarms));
DBG_IFACE( "Valid DSU NL loopback:\t%s\tUnsigned mux code:\t%s\n",
DLP_ALARM_56K(alarms),
UMC_ALARM_56K(alarms));
DBG_IFACE( "Rx loss of signal:\t%s\t\n",
RLOS_ALARM_56K(alarms));
}
pmon = (sdla_te_pmon_t*)&data[sizeof(unsigned long)];
/*
//FIXME:
DBG_IFACE( "\n\n***** %s: %s Performance Monitoring Counters *****\n\n",
interface_name, (adapter_type == WAN_MEDIA_T1) ? "T1" : "E1");
DBG_IFACE( "Framing Bit Error:\t%ld\tLine Code Violation:\t%ld\n",
pmon->frm_bit_error,
pmon->lcv);
if (adapter_type == WAN_MEDIA_T1){
DBG_IFACE( "Out of Frame Errors:\t%ld\tBit Errors:\t\t%ld\n",
pmon->oof_errors,
pmon->bit_errors);
}else{
DBG_IFACE( "Far End Block Errors:\t%ld\tCRC Errors:\t%ld\n",
pmon->far_end_blk_errors,
pmon->crc_errors);
}
*/
return 0;
}
char sangoma_interface::alarms_present()
{
unsigned long alarms;
unsigned char is_alarm_set = 0;
wanpipe_api_t wp_api;
SANGOMA_INIT_TDM_API_CMD(wp_api);
DBG_IFACE("%s()\n", __FUNCTION__);
#define DBG_ALARMS if(0)printf
if(read_te1_56k_stat(&alarms)){
return 1;
}
if (adapter_type == WAN_MEDIA_T1 || adapter_type == WAN_MEDIA_E1){
DBG_IFACE( "***** %s: %s Alarms *****\n\n",
interface_name, (adapter_type == WAN_MEDIA_T1) ? "T1" : "E1");
if(!strcmp(WAN_TE_ALOS_ALARM(alarms), ON_STR)){
DBG_ALARMS("ALOS\n");
is_alarm_set = 1;
}
if(!strcmp(WAN_TE_LOS_ALARM(alarms), ON_STR)){
DBG_ALARMS("LOS\n");
is_alarm_set = 1;
}
if(!strcmp(WAN_TE_RED_ALARM(alarms), ON_STR)){
DBG_ALARMS("RED\n");
is_alarm_set = 1;
}
if(!strcmp(WAN_TE_AIS_ALARM(alarms), ON_STR)){
DBG_ALARMS("AIS\n");
is_alarm_set = 1;
}
if (adapter_type == WAN_MEDIA_T1){
if(!strcmp(WAN_TE_YEL_ALARM(alarms), ON_STR)){
DBG_ALARMS("\n");
is_alarm_set = 1;
}
if(!strcmp(WAN_TE_OOF_ALARM(alarms), ON_STR)){
DBG_ALARMS("\n");
is_alarm_set = 1;
}
}else{
if(!strcmp(WAN_TE_OOF_ALARM(alarms), ON_STR)){
DBG_ALARMS("\n");
is_alarm_set = 1;
}
}
}
unsigned char fe_status = FE_DISCONNECTED;
if (is_alarm_set == 1) {
//An alarm may be set, but the Front End code in the driver has
//better idea if it should be ignored. Check FE status, and if,
//it is "Connected", ignore the alarm.
sangoma_get_fe_status(sangoma_dev, &wp_api, &fe_status);
if (fe_status == FE_CONNECTED) {
is_alarm_set = 0;
}
}
DBG_ALARMS("is_alarm_set: %d\n", is_alarm_set);
return is_alarm_set;
}
int sangoma_interface::loopback_command(u_int8_t type, u_int8_t mode, u_int32_t chan_map)
{
sdla_fe_lbmode_t *lb;
int err = 0, cnt = 0;
lb = (sdla_fe_lbmode_t*)get_wan_udphdr_data_ptr(0);
memset(lb, 0, sizeof(sdla_fe_lbmode_t));
lb->cmd = WAN_FE_LBMODE_CMD_SET;
lb->type = type;
lb->mode = mode;
lb->chan_map = chan_map;
lb_poll_again:
wan_udp.wan_udphdr_command = WAN_FE_LB_MODE;
wan_udp.wan_udphdr_data_len = sizeof(sdla_fe_lbmode_t);
wan_udp.wan_udphdr_return_code = 0xaa;
DO_COMMAND(wan_udp);
if (wan_udp.wan_udphdr_return_code){
err = 1;
return err;
}
if (lb->rc == WAN_FE_LBMODE_RC_PENDING){
if (!cnt) printf("Please wait ..");fflush(stdout);
if (cnt++ < 10){
printf(".");fflush(stdout);
Sleep(100);
lb->cmd = WAN_FE_LBMODE_CMD_POLL;
lb->rc = 0x00;
goto lb_poll_again;
}
err = 2;
goto loopback_command_exit;
}else if (lb->rc != WAN_FE_LBMODE_RC_SUCCESS){
err = 3;
}
if (cnt) printf("\n");
loopback_command_exit:
return err;
}
void sangoma_interface::set_lb_modes(unsigned char type, unsigned char mode)
{
DBG_IFACE("%s()\n", __FUNCTION__);
switch(adapter_type)
{
case WAN_MEDIA_T1:
case WAN_MEDIA_E1:
case WAN_MEDIA_56K:
;//do nothing
break;
default:
ERR_IFACE( "Command invalid for Adapter Type %d.\n", adapter_type);
return;
}
if(loopback_command(type, mode, ENABLE_ALL_CHANNELS)){
ERR_IFACE("Error: Loop Back command failed!\n");
return;
}
if (adapter_type == WAN_MEDIA_T1 || adapter_type == WAN_MEDIA_E1){
DBG_IFACE("%s %s mode ... %s!\n",
WAN_TE1_LB_ACTION_DECODE(mode),
WAN_TE1_LB_MODE_DECODE(type),
(!wan_udp.wan_udphdr_return_code)?"Done":"Failed");
}else if (adapter_type == WAN_MEDIA_DS3 || adapter_type == WAN_MEDIA_E3){
DBG_IFACE("%s %s mode ... %s!\n",
WAN_TE3_LB_ACTION_DECODE(mode),
WAN_TE3_LB_TYPE_DECODE(type),
(!wan_udp.wan_udphdr_return_code)?"Done":"Failed");
}else{
DBG_IFACE("%s %s mode ... %s (default)!\n",
WAN_TE1_LB_ACTION_DECODE(mode),
WAN_TE1_LB_MODE_DECODE(type),
(!wan_udp.wan_udphdr_return_code)?"Done":"Failed");
}
return;
}
void sangoma_interface::operational_stats(wanpipe_chan_stats_t *stats)
{
wanpipe_api_t wp_api;
SANGOMA_INIT_TDM_API_CMD(wp_api);
int err = sangoma_get_stats(sangoma_dev, &wp_api, stats);
if (err || wp_api.wp_cmd.result != SANG_STATUS_SUCCESS) {
ERR_IFACE("sangoma_get_stats() failed! err: %d (0x%X), result:%d!\n",
err, err, wp_api.wp_cmd.result);
return;
}
DBG_IFACE( "**** OPERATIONAL_STATS ****\n");
DBG_IFACE( "\ttx_dropped\t: %u\n", stats->tx_dropped);
DBG_IFACE( "\ttx_packets\t: %u\n", stats->tx_packets);
DBG_IFACE( "\ttx_bytes\t: %u\n", stats->tx_bytes);
DBG_IFACE( "\n");
//receive stats
DBG_IFACE( "\trx_packets\t: %u\n", stats->rx_packets);
DBG_IFACE( "\trx_bytes\t: %u\n", stats->rx_bytes);
DBG_IFACE( "\trx_errors\t: %u\n", stats->rx_errors);
DBG_IFACE( "\trx_frame_errors\t: %u\n", stats->rx_frame_errors);
DBG_IFACE( "\trx_packets_discarded_rx_q_full\t: %u\n",
stats->rx_dropped);
DBG_IFACE( "\n");
//hardware level stats
//AFT card
DBG_IFACE( "\trx_fifo_errors\t: %u\n", stats->rx_fifo_errors);
DBG_IFACE( "\ttx_fifo_errors\t: %u\n", stats->tx_fifo_errors);
//BitStream mode only - counter of data blocks transmitted automatically,
//because no User Data was available. Transmit underrun counter from user
//point of view.
DBG_IFACE( "\ttx_idle_data\t: %u\n", stats->tx_idle_packets);
}
void sangoma_interface::flush_operational_stats (void)
{
wanpipe_api_t wp_api;
SANGOMA_INIT_TDM_API_CMD(wp_api);
int err = sangoma_flush_stats(sangoma_dev, &wp_api);
if (err || wp_api.wp_cmd.result != SANG_STATUS_SUCCESS) {
ERR_IFACE("sangoma_flush_stats() failed! err: %d (0x%X), result:%d!\n",
err, err, wp_api.wp_cmd.result);
return;
}
DBG_IFACE( "Command FLUSH_OPERATIONAL_STATS was successful.\n");
}
void sangoma_interface::flush_buffers (void)
{
wanpipe_api_t wp_api;
SANGOMA_INIT_TDM_API_CMD(wp_api);
int err = sangoma_flush_bufs(sangoma_dev, &wp_api);
if (err || wp_api.wp_cmd.result != SANG_STATUS_SUCCESS) {
ERR_IFACE("sangoma_flush_buffers() failed! err: %d (0x%X), result:%d!\n",
err, err, wp_api.wp_cmd.result);
return;
}
DBG_IFACE( "Command sangoma_flush_bufs was successful.\n");
}
int sangoma_interface::get_interface_configuration(if_cfg_t *wanif_conf_ptr)
{
wan_udp.wan_udphdr_command = WANPIPEMON_READ_CONFIGURATION;
wan_udp.wan_udphdr_data_len = sizeof(if_cfg_t);
memset(wanif_conf_ptr, 0x00, sizeof(if_cfg_t));
DO_COMMAND(wan_udp);
if(wan_udp.wan_udphdr_return_code){
ERR_IFACE( "Error: command READ_CONFIGURATION failed!\n");
return 1;
}
memcpy(wanif_conf_ptr, get_wan_udphdr_data_ptr(0), sizeof(if_cfg_t));
DBG_IFACE( "**** READ_CONFIGURATION ****\n");
DBG_IFACE( "Operational Mode\t: %s (%d)\n", SDLA_DECODE_USEDBY_FIELD(wanif_conf_ptr->usedby), wanif_conf_ptr->usedby);
DBG_IFACE( "Configued Active Channels \t: 0x%08X\n", wanif_conf_ptr->active_ch);
DBG_IFACE( "Echo Canceller Channels\t\t: 0x%08X\n", wanif_conf_ptr->ec_active_ch);
DBG_IFACE( "User Specified Channels during Port Config\t: 0x%08X\n", wanif_conf_ptr->cfg_active_ch);
DBG_IFACE( "Interface Number\t: %u\n", wanif_conf_ptr->interface_number);
DBG_IFACE( "Media type\t\t: %u\n", wanif_conf_ptr->media);
DBG_IFACE( "Line Mode\t\t: %s\n", wanif_conf_ptr->line_mode);
DBG_IFACE( "****************************\n");
#if 1
// Audio Codec can be read for Voice interface.
// For Data interface this setting is ignored by the API.
wanpipe_api_t wp_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) {
DBG_IFACE("Audio Codec: %s\n",
WP_CODEC_FORMAT_DECODE(wp_api.wp_cmd.hw_tdm_coding));
}
#endif
return 0;
}
int sangoma_interface::get_api_driver_version (PDRIVER_VERSION p_drv_version)
{
memcpy(p_drv_version, &drv_version, sizeof(DRIVER_VERSION));
DBG_IFACE("\nAPI version\t: %d,%d,%d,%d\n",
p_drv_version->major, p_drv_version->minor, p_drv_version->minor1, p_drv_version->minor2);
DBG_IFACE("\n");
return 0;
}
int sangoma_interface::check_api_driver_version( )
{
DBG_IFACE("\nAPI version\t: %d,%d,%d,%d\n",
drv_version.major, drv_version.minor, drv_version.minor1, drv_version.minor2);
// verify that Driver Version is the same as Header files used to compile this application
if(drv_version.major != WANPIPE_VERSION_MAJOR){
ERR_IFACE("Error: drv_version.major (%d) != WANPIPE_VERSION_MAJOR (%d)\n",
drv_version.major, WANPIPE_VERSION_MAJOR);
exit(1);
}
if(drv_version.minor != WANPIPE_VERSION_MINOR){
ERR_IFACE("Error: drv_version.minor (%d) != WANPIPE_VERSION_MINOR (%d)\n",
drv_version.minor, WANPIPE_VERSION_MINOR);
exit(1);
}
if(drv_version.minor1 != WANPIPE_VERSION_MINOR1){
ERR_IFACE("Error: drv_version.minor1 (%d) != WANPIPE_VERSION_MINOR1 (%d)\n",
drv_version.minor1, WANPIPE_VERSION_MINOR1);
exit(1);
}
unsigned int compiled_minor_version = WANPIPE_VERSION_MINOR2;
// This is a PATCH number - allow it to be greater or equal because binary
// compatibility is guaranteed
if(drv_version.minor2 < compiled_minor_version){
ERR_IFACE("Error: drv_version.minor2 (%d) != WANPIPE_VERSION_MINOR2 (%d)\n",
drv_version.minor2, WANPIPE_VERSION_MINOR2);
exit(1);
}
return 0;
}
int sangoma_interface::DoManagementCommand(sng_fd_t fd, wan_udp_hdr_t* wan_udp)
{
return sangoma_mgmt_cmd(fd, wan_udp);
}
sangoma_wait_obj_t* sangoma_interface::get_wait_object_reference()
{
return sng_wait_obj;
}
unsigned char sangoma_interface::get_adapter_type()
{
return adapter_type;
}
//Returns Port Number mapped specifically for G3 use for a CARD.
unsigned int sangoma_interface::get_mapped_port_number()
{
return interface_number;
}
//Returns Span Number - global for the APPLICATION
unsigned int sangoma_interface::get_mapped_span_number()
{
return wanpipe_number + 1 + get_mapped_port_number();
}
int sangoma_interface::transmit(wp_api_hdr_t* txhdr, void *pTx, UINT buffer_length)
{
txhdr->operation_status = SANG_STATUS_GENERAL_ERROR;
txhdr->data_length = buffer_length;
if(sangoma_writemsg(sangoma_dev, txhdr, sizeof(*txhdr), pTx, buffer_length, 0) < 0){
//error
ERR_IFACE("sangoma_writemsg() failed!\n");
return SANG_STATUS_IO_ERROR;
}
switch(txhdr->operation_status)
{
case SANG_STATUS_SUCCESS:
//OK
break;
default:
//Error! Non-zero return code indicates Error to G3TI application.
ERR_IFACE("Return code: %s (%d) on transmission!\n",
SDLA_DECODE_SANG_STATUS(txhdr->operation_status), txhdr->operation_status);
break;
}//switch()
return txhdr->operation_status;
}
int sangoma_interface::read_data(wp_api_hdr_t* rxhdr, void *pRx, UINT buffer_length)
{
int return_code;
memset(rxhdr, 0x00, sizeof(*rxhdr));
rxhdr->operation_status = SANG_STATUS_GENERAL_ERROR;
//Non-blocking read data.
return_code = sangoma_readmsg(sangoma_dev, rxhdr, sizeof(*rxhdr), pRx, buffer_length, 0);
if(return_code <= 0){
if (SANG_STATUS_NO_DATA_AVAILABLE == rxhdr->operation_status) {
// no data is NOT an error at THIS level
return 0;
} else {
//Error! Non-zero return code indicates Error to G3TI application.
return 1;
}
}
return 0;
}
int sangoma_interface::read_event(wanpipe_api_t* wp_api)
{
SANGOMA_INIT_TDM_API_CMD(*wp_api);
//Non-blocking read Event.
return sangoma_read_event(sangoma_dev, wp_api);
}
int sangoma_interface::set_buffer_multiplier(wanpipe_api_t* wp_api, int buffer_multiplier)
{
SANGOMA_INIT_TDM_API_CMD(*wp_api);
return sangoma_tdm_set_buffer_multiplier(sangoma_dev, wp_api, buffer_multiplier);
}

View File

@ -1,167 +0,0 @@
//////////////////////////////////////////////////////////////////////
// sangoma_interface.h: interface for Sangoma API driver.
//
// Author : David Rokhvarg <davidr@sangoma.com>
//////////////////////////////////////////////////////////////////////
#ifndef SANGOMA_INTERFACE_H
#define SANGOMA_INTERFACE_H
#if defined(__WINDOWS__)
# include <windows.h>
# include <conio.h>
#elif defined(__LINUX__)
/* Include headers */
# include <stddef.h>
# include <errno.h>
# include <fcntl.h>
# include <string.h>
# include <ctype.h>
# include <sys/stat.h>
# include <sys/ioctl.h>
# include <sys/types.h>
# include <dirent.h>
# include <unistd.h>
# include <sys/socket.h>
# include <netdb.h>
# include <sys/un.h>
# include <sys/wait.h>
# include <unistd.h>
# include <signal.h>
# include <time.h>
#else
# error Unsupported OS
#endif
#include <stdio.h>
#include <stddef.h> //for offsetof()
#include "libsangoma.h"
#include "wanpipe_api.h"
/**
*@author David Rokhvarg
*/
struct func_protocol {
int protocol_id;
unsigned char prot_name[10];
unsigned char mbox_offset;
};
#define DECODE_PROT(prot)((prot==WANCONFIG_FR)?"Frame Relay": \
(prot==WANCONFIG_MFR)?"Frame Relay": \
(prot==WANCONFIG_PPP)?"PPP Point-to-Point": \
(prot==WANCONFIG_CHDLC)?"Cisco HDLC": \
(prot==WANCONFIG_X25)?"X25": \
(prot==WANCONFIG_ADSL)?"ADSL: Eth,IP,PPP/ATM": \
(prot==WANCONFIG_ATM)?"ATM": \
(prot==WANCONFIG_AFT)?"AFT T1/E1": \
(prot==WANCONFIG_AFT_TE1)?"AFT T1/E1": \
(prot==WANCONFIG_AFT_ANALOG)?"AFT Analog": \
"Unknown")
#define DEV_NAME_LEN 100
#define ON_STR "ON"
#define OFF_STR "OFF"
#define MAX_INTERFACES_PER_PORT 32
class sangoma_interface {
//////////////////////////////////////////////////////////////////
/*! Sangoma IO device descriptor */
sng_fd_t sangoma_dev;
/*! wait object for an IO device */
sangoma_wait_obj_t *sng_wait_obj;
//////////////////////////////////////////////////////////////////
//receive stuff
ULONG rx_frames_count;
ULONG rx_bytes_count;
//for counting frames with CRC/Abort errors
ULONG bad_rx_frames_count;
//////////////////////////////////////////////////////////////////
//transmit stuff
ULONG tx_bytes_count;
ULONG tx_frames_count;
UCHAR tx_test_byte;
//////////////////////////////////////////////////////////////////
//IOCTL management structures and variables
wan_udp_hdr_t wan_udp;
int protocol_cb_size;
int wan_protocol;
unsigned char adapter_type;
unsigned int card_model;
int GetWANConfig( void );
int get_interface_configuration(if_cfg_t *wanif_conf_ptr);
//return DATA at offset 'off'
unsigned char get_wan_udphdr_data_byte(unsigned char off);
//return POINTER to data at offset 'off'
unsigned char *get_wan_udphdr_data_ptr(unsigned char off);
unsigned char set_wan_udphdr_data_byte(unsigned char off, unsigned char data);
int get_fe_type(unsigned char* adapter_type);
int check_api_driver_version();
int wanpipe_api_ioctl(wan_cmd_api_t *api_cmd);
UCHAR DoWriteCommand(sng_fd_t drv, TX_DATA_STRUCT * pTx, UINT buffer_length);
UCHAR DoSetIdleTxBufferCommand(sng_fd_t drv, TX_DATA_STRUCT *pTx);
int DoManagementCommand(sng_fd_t fd, wan_udp_hdr_t* wan_udp);
//////////////////////////////////////////////////////////////////
wan_driver_version_t drv_version;
char interface_name[DEV_NAME_LEN]; //used only for debugging
if_cfg_t wanif_conf_struct; //used only for debugging
int wanpipe_number, interface_number;
//In Legacy Mode 1-st interface is zero-based (i.g. wanpipe1_if0).
//In Regular Mode 1-st interface is one-based (i.g. wanpipe1_if1).
//The Setup installs in Regular Mode.
HANDLE open_first_interface_of_a_mapped_port();
public:
sangoma_interface(int wanpipe_number, int interface_number);
~sangoma_interface();
int init();
int cleanup();
int read_te1_56k_stat(unsigned long *p_alarms);
char alarms_present();
void set_lb_modes(unsigned char type, unsigned char mode);
int loopback_command(u_int8_t type, u_int8_t mode, u_int32_t chan_map);
void operational_stats (wanpipe_chan_stats_t *stats);
void flush_operational_stats (void);
void flush_buffers (void);
sangoma_wait_obj_t* get_wait_object_reference();
unsigned char get_adapter_type();
//Returns Port Number mapped specifically for G3 use.
unsigned int get_mapped_port_number();
unsigned int get_mapped_span_number();
int get_api_driver_version (PDRIVER_VERSION p_drv_version);
int set_buffer_multiplier(wanpipe_api_t* wp_api, int buffer_multiplier);
int transmit (wp_api_hdr_t* hdr, void *pTx, UINT buffer_length);
int read_data(wp_api_hdr_t* hdr, void *pRx, UINT buffer_length);
int read_event(wanpipe_api_t* wp_api);
};
#endif//#define SANGOMA_INTERFACE_H

View File

@ -2270,6 +2270,7 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_get_global_chip_statistics(sng_fd_t f
sangoma_status_t _LIBSNG_CALL sangoma_hwec_get_chip_image_info(sng_fd_t fd,
int *hwec_api_return_code, wanec_chip_image_t *wanec_chip_image, int verbose);
#ifdef WP_API_FEATURE_LIBSNG_HWEC_DTMF_REMOVAL
/*!
\fn sangoma_status_t _LIBSNG_CALL sangoma_hwec_set_hwdtmf_removal(sng_fd_t fd, unsigned int fe_chan,
int *hwec_api_return_code, int enable)
@ -2292,6 +2293,7 @@ sangoma_status_t _LIBSNG_CALL sangoma_hwec_get_chip_image_info(sng_fd_t fd,
sangoma_status_t _LIBSNG_CALL sangoma_hwec_set_hwdtmf_removal(sng_fd_t fd, unsigned int fe_chan,
int *hwec_api_return_code, int enable, int verbose);
#endif /* WP_API_FEATURE_LIBSNG_HWEC */
#endif

View File

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

View File

@ -475,8 +475,15 @@ typedef struct {
u_int16_t feb_diff;
u_int32_t fer_errors; /* Framing bit errors (T1) */
u_int16_t fer_diff;
u_int32_t sync_errors;
} sdla_te_pmon_t;
#define WAN_PMON_SYNC_ERROR(card) do { \
sdla_te_pmon_t *pmon; \
pmon = &card->fe.fe_stats.te_pmon; \
pmon->sync_errors++; \
} while (0);
#define WAN_TE_RXLEVEL_LEN 20
typedef struct {
u_int16_t mask;

View File

@ -10,14 +10,14 @@
#define WANPIPE_COMPANY "Sangoma Technologies Inc"
/********** LINUX **********/
#define WANPIPE_VERSION "7.0.1"
#define WANPIPE_VERSION "7.0.2"
#define WANPIPE_SUB_VERSION "0"
#define WANPIPE_LITE_VERSION "1.1.1"
#if defined(__LINUX__)
#define WANPIPE_VERSION_MAJOR 7
#define WANPIPE_VERSION_MINOR 0
#define WANPIPE_VERSION_MINOR1 1
#define WANPIPE_VERSION_MINOR1 2
#define WANPIPE_VERSION_MINOR2 0
#endif

View File

@ -6961,8 +6961,9 @@ static void t116_error_counter_check(sdla_t *card)
}
if (wan_test_and_clear_bit(AFT_LCFG_T116_FE_RX_SYNC, &dump)){
err++;
WAN_PMON_SYNC_ERROR(card);
DEBUG_ERROR("%s: Error: T116 Lost Sync\n",card->devname);
err++;
}
if (err) {
@ -7714,6 +7715,7 @@ global_irq_skip:
card->u.aft.lcfg_reg=lcfg_reg;
disable_data_error_intr(card,LINK_DOWN);
WAN_PMON_SYNC_ERROR(card);
if (!wan_test_bit(AFT_FE_RESTART,&card->u.aft.port_task_cmd)) {
DEBUG_ERROR("%s: Warning: Front End Lost Synchronization (sync_cnt=%i,c=%i,f=%i)\n",

View File

@ -1984,8 +1984,6 @@ static int sdla_ds_te1_unconfig(void* pfe)
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);
@ -4784,8 +4782,18 @@ static int sdla_ds_te1_pmon(sdla_fe_t *fe, int action)
WAN_TE_BIT_PMON_CRC4 |
WAN_TE_BIT_PMON_FAS |
WAN_TE_BIT_PMON_FEB;
pmon->crc4_diff = pmon2;
pmon->crc4_errors = pmon->crc4_errors + pmon2;
if (fe->fe_chip_id == DEVICE_ID_DS26519) {
if (WAN_FE_FRAME(fe) == WAN_FR_CRC4){
pmon->crc4_diff = pmon2;
pmon->crc4_errors = pmon->crc4_errors + pmon2;
} else {
pmon->crc4_diff = 0;
pmon->crc4_errors = 0;
}
} else {
pmon->crc4_diff = pmon2;
pmon->crc4_errors = pmon->crc4_errors + pmon2;
}
pmon->fas_diff = pmon3;
pmon->fas_errors = pmon->fas_errors + pmon3;
pmon->feb_diff = pmon4;

View File

@ -1690,6 +1690,7 @@ static int wp_tdmv_spanconfig(struct zt_span *span, struct zt_lineconfig *lc)
sdla_t *card = NULL;
int err = 0;
wan_smp_flag_t smp_flags;
int need_reconfig=0;
WAN_ASSERT2(span == NULL, -ENODEV);
@ -1697,8 +1698,20 @@ static int wp_tdmv_spanconfig(struct zt_span *span, struct zt_lineconfig *lc)
WAN_ASSERT2(wp == NULL, -ENODEV);
card = (sdla_t*)wp->card;
DEBUG_EVENT("%s: DAHDI Configuring span device..\n", wp->devname);
DEBUG_EVENT("%s: DAHDI Configuring device [name=%s, span=%i, sync=%i, lcfg=0x%X,]\n",
wp->devname,lc->name, lc->span,lc->sync,lc->lineconfig);
if (lc->sync == 0) {
if (WAN_TE1_CLK(&card->fe) != WAN_MASTER_CLK) {
WAN_TE1_CLK(&card->fe) = WAN_MASTER_CLK;
need_reconfig=1;
}
} else {
if (WAN_TE1_CLK(&card->fe) != WAN_NORMAL_CLK) {
WAN_TE1_CLK(&card->fe) = WAN_NORMAL_CLK;
need_reconfig=1;
}
}
if (!wp->ise1) {
if (lc->lineconfig & ZT_CONFIG_B8ZS) {
@ -1725,7 +1738,10 @@ static int wp_tdmv_spanconfig(struct zt_span *span, struct zt_lineconfig *lc)
return -EINVAL;
}
WAN_TE1_LBO(&card->fe) = lc->lbo+WAN_T1_0_133;
if (WAN_TE1_LBO(&card->fe) != (lc->lbo+WAN_T1_0_133)) {
WAN_TE1_LBO(&card->fe) = lc->lbo+WAN_T1_0_133;
need_reconfig=1;
}
} else {
if (lc->lineconfig & ZT_CONFIG_HDB3){
@ -1743,35 +1759,52 @@ static int wp_tdmv_spanconfig(struct zt_span *span, struct zt_lineconfig *lc)
wp->frame = WAN_FR_CRC4;
}
card->fe.fe_cfg.cfg.te_cfg.sig_mode = WAN_TE1_SIG_CAS;
if (lc->lineconfig & ZT_CONFIG_CCS) {
span->lineconfig |= ZT_CONFIG_CCS;
card->fe.fe_cfg.cfg.te_cfg.sig_mode = WAN_TE1_SIG_CCS;
if (card->fe.fe_cfg.cfg.te_cfg.sig_mode != WAN_TE1_SIG_CCS) {
card->fe.fe_cfg.cfg.te_cfg.sig_mode = WAN_TE1_SIG_CCS;
need_reconfig=1;
}
} else {
if (card->fe.fe_cfg.cfg.te_cfg.sig_mode != WAN_TE1_SIG_CAS) {
need_reconfig=1;
card->fe.fe_cfg.cfg.te_cfg.sig_mode = WAN_TE1_SIG_CAS;
}
}
WAN_TE1_LBO(&card->fe) = WAN_E1_120;
}
WAN_FE_LCODE(&card->fe) = wp->lcode;
WAN_FE_FRAME(&card->fe) = wp->frame;
if (card->wandev.fe_iface.config &&
card->wandev.fe_iface.unconfig &&
card->wandev.fe_iface.reconfig) {
if (WAN_FE_LCODE(&card->fe) != wp->lcode ||
WAN_FE_FRAME(&card->fe) != wp->frame) {
card->hw_iface.hw_lock(card->hw,&smp_flags);
card->wandev.fe_iface.unconfig(&card->fe);
card->hw_iface.hw_unlock(card->hw,&smp_flags);
WAN_FE_LCODE(&card->fe) = wp->lcode;
WAN_FE_FRAME(&card->fe) = wp->frame;
need_reconfig=1;
}
card->wandev.fe_iface.post_unconfig(&card->fe);
card->hw_iface.hw_lock(card->hw,&smp_flags);
card->wandev.fe_iface.config(&card->fe);
card->wandev.fe_iface.reconfig(&card->fe);
card->hw_iface.hw_unlock(card->hw,&smp_flags);
if (need_reconfig) {
if (card->wandev.fe_iface.config &&
card->wandev.fe_iface.unconfig &&
card->wandev.fe_iface.reconfig) {
card->wandev.fe_iface.post_init(&card->fe);
card->hw_iface.hw_lock(card->hw,&smp_flags);
card->wandev.fe_iface.unconfig(&card->fe);
card->hw_iface.hw_unlock(card->hw,&smp_flags);
card->wandev.fe_iface.post_unconfig(&card->fe);
card->hw_iface.hw_lock(card->hw,&smp_flags);
card->wandev.fe_iface.config(&card->fe);
card->wandev.fe_iface.reconfig(&card->fe);
card->hw_iface.hw_unlock(card->hw,&smp_flags);
card->wandev.fe_iface.post_init(&card->fe);
}
} else {
DEBUG_EVENT("%s: Wanpipe front end skipped, no changes in config\n", wp->devname);
}
span->txlevel = 0;

View File

@ -1,6 +1,6 @@
%define WANPIPE_VER wanpipe-modules
%define name %{WANPIPE_VER}
%define version 7.0.1
%define version 7.0.2
%define release 0
%define serial 1
%define MODULES_DIR /lib/modules
@ -59,6 +59,23 @@ fi
%changelog
* Fri May 10 2013 Nenad Corbic <ncorbic@sangoma.com> - 7.0.2
==================================================================
- Added sync error statistic in wanpipeomon Ta command
Sync error indicates clocking or synchronizatio errors
on T1/E1 lines. Provides added statistic to debug line,
slip errors on T1/E1.
- Fixed DAHDI reconfiguration issues.
running dahdi_cfg multiple times will not bring down T1/E1 link
Added config option to change clocking from MASTER to NORMAL
from dahdi system.conf
- New sample_data_tapping sample application for T116 and other
tapping boards.
* Tue Mar 19 2013 Nenad Corbic <ncorbic@sangoma.com> - 7.0.1
==================================================================

View File

@ -1,6 +1,6 @@
%define WANPIPE_VER wanpipe-util
%define name %{WANPIPE_VER}
%define version 7.0.1
%define version 7.0.2
%define release 0
%define serial 1
%define UTILS_DIR /usr/sbin
@ -229,6 +229,23 @@ chmod 755 /usr/local/sbin/setup-sangoma
%changelog
* Fri May 10 2013 Nenad Corbic <ncorbic@sangoma.com> - 7.0.2
==================================================================
- Added sync error statistic in wanpipeomon Ta command
Sync error indicates clocking or synchronizatio errors
on T1/E1 lines. Provides added statistic to debug line,
slip errors on T1/E1.
- Fixed DAHDI reconfiguration issues.
running dahdi_cfg multiple times will not bring down T1/E1 link
Added config option to change clocking from MASTER to NORMAL
from dahdi system.conf
- New sample_data_tapping sample application for T116 and other
tapping boards.
* Tue Mar 19 2013 Nenad Corbic <ncorbic@sangoma.com> - 7.0.1
==================================================================

View File

@ -1,7 +1,7 @@
%define KERNEL_VERSION %{?kern_ver}
%define WANPIPE_VER wanpipe
%define name %{WANPIPE_VER}
%define version 7.0.1
%define version 7.0.2
%define release 0
%define serial 1
%define UTILS_DIR /usr/sbin
@ -246,6 +246,23 @@ chmod 755 /usr/local/sbin/setup-sangoma
%changelog
* Fri May 10 2013 Nenad Corbic <ncorbic@sangoma.com> - 7.0.2
==================================================================
- Added sync error statistic in wanpipeomon Ta command
Sync error indicates clocking or synchronizatio errors
on T1/E1 lines. Provides added statistic to debug line,
slip errors on T1/E1.
- Fixed DAHDI reconfiguration issues.
running dahdi_cfg multiple times will not bring down T1/E1 link
Added config option to change clocking from MASTER to NORMAL
from dahdi system.conf
- New sample_data_tapping sample application for T116 and other
tapping boards.
* Tue Mar 19 2013 Nenad Corbic <ncorbic@sangoma.com> - 7.0.1
==================================================================

View File

@ -2231,7 +2231,7 @@ init_global_params()
{
if [ $OSYSTEM = "Linux" ]; then
ROUTER_VERSION=7.0.1
ROUTER_VERSION=7.0.2
IFCONFIG_LIST=ifconfig
MODULE_STAT=lsmod
WAN_DRIVERS="wanpipe"

View File

@ -443,6 +443,11 @@ sub gen_wanpipe_conf{
$wp_file =~ s/RXSLEVEL/$rx_slevel/g;
$wp_file =~ s/FELBO/$fe_lbo/g;
if ($fe_lcode eq "AMI" && $fe_frame eq "D4" ){
print "Setting DCHAN $dchan to zero\n";
$dchan=0;
}
if($self->is_data_api eq '0') {
$wp_file =~ s/TDMVDCHAN/0/g;
$hw_dtmf="NO";

View File

@ -1277,6 +1277,8 @@ void read_te1_56k_stat(unsigned char force)
printf("FAS Errors\t\t: %d\n",
pmon->fas_errors);
}
printf("Sync Errors\t\t: %d\n",
pmon->sync_errors);
}
if (femedia.media == WAN_MEDIA_DS3 || femedia.media == WAN_MEDIA_E3){

View File

@ -25,7 +25,7 @@
#
%define NAME wanpipe
%define VERSION 7.0.1
%define VERSION 7.0.2
%define RELEASE 0
%define KVERSION %{?kernel}
%define KSRC %{?ksrc}
@ -259,6 +259,23 @@ fi
%changelog
* Fri May 10 2013 Nenad Corbic <ncorbic@sangoma.com> - 7.0.2
==================================================================
- Added sync error statistic in wanpipeomon Ta command
Sync error indicates clocking or synchronizatio errors
on T1/E1 lines. Provides added statistic to debug line,
slip errors on T1/E1.
- Fixed DAHDI reconfiguration issues.
running dahdi_cfg multiple times will not bring down T1/E1 link
Added config option to change clocking from MASTER to NORMAL
from dahdi system.conf
- New sample_data_tapping sample application for T116 and other
tapping boards.
* Tue Mar 19 2013 Nenad Corbic <ncorbic@sangoma.com> - 7.0.1
==================================================================