/////////////////////////////////////////////////////////////////////////////////////////////// /// \file SangomaPort.h /// \brief This file contains the declaration of the SangomaPort class /////////////////////////////////////////////////////////////////////////////////////////////// #ifndef _SANGOMA_PORT_H #define _SANGOMA_PORT_H #ifdef WIN32 #define __WINDOWS__ #include #endif #include #include "PortBuffer.h" // Forward declarations to limit the third-party Sangoma includes to the .cpp file only. struct sangoma_wait_obj; typedef sangoma_wait_obj sangoma_wait_obj_t; class sangoma_interface; #ifdef LINUX typedef pthread_mutex_t CRITICAL_SECTION; #endif struct wanpipe_api; typedef wanpipe_api wanpipe_api_t; namespace Sangoma { // Read/Write error codes const int ERROR_NO_DATA_AVAILABLE = -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 details. 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 absence 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 }; typedef enum SNG_API_MODE{ SNG_SPAN_MODE=0, SNG_CHAN_MODE=1, SNG_DATA_MODE=2 } sng_api_mode_t; /////////////////////////////////////////////////////////////////////////////////////////////// /// \struct Configuration /// \brief Structure containing all settings necessary to configure a Sangoma port /////////////////////////////////////////////////////////////////////////////////////////////// struct Configuration { Sangoma::E1OrT1 E1OrT1; ///< Configures the port as either E1 or T1 FramingType Framing; ///< Framing type and signalling of the E1/T1 port Sangoma::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 int dchan; ///< Integer value of a dchan int chunk_ms; ///< Integer value of ms chunk size default 20 (160bytes per timeslot) sng_api_mode_t api_mode; int dchan_seven_bit; int dchan_mtp1_filter; /////////////////////////////////////////////////////////////////////////////////////////////// /// \fn Configuration::Configuration() /// \brief Constructor (for the Configuration structure) /// \author J. Markwordt /// \date 10/04/2007 /////////////////////////////////////////////////////////////////////////////////////////////// Configuration(): E1OrT1(E1), Framing(E1_CAS_CRC4_ON), LineCoding(OFF), HighImpedanceMode(true), TxTristateMode(false), Master(false), dchan(0) {} }; /////////////////////////////////////////////////////////////////////////////////////////////// /// \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 /////////////////////////////////////////////////////////////////////////////////////////////// /// \fn Statistics::Statistics() /// \brief Constructor (for the Statistics structure) /// \author J. Markwordt /// \date 10/04/2007 /////////////////////////////////////////////////////////////////////////////////////////////// Statistics(): TimeLastOpened(0), TimeLastClosed(0), TimeLastFoundSync(0), TimeLastLostSync(0), OpenCount(0), CloseCount(0), FoundSyncCount(0), LostSyncCount(0), BytesReceived(0), BytesSent(0), Errors(0) {} }; /////////////////////////////////////////////////////////////////////////////////////////////// /// \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 std::string ToString(); // G3 specific change }; /////////////////////////////////////////////////////////////////////////////////////////////// /// \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. const static unsigned int MAXIMUM_BUFFER_MULTIPLIER_FACTOR; const static unsigned int MINIMUM_BUFFER_MULTIPLIER_FACTOR; const static unsigned int MINIMUM_NUMBER_OF_BUFFERS_PER_API_INTERFACE; // G3 specific change start /// \fn BufferSettings::BufferSettings() /// \brief Constructor to set the members to default values BufferSettings() { Reset(); } /// \fn BufferSettings::Reset() /// \brief Set the members to default values void Reset() { BufferMultiplierFactor = 0; NumberOfBuffersPerPort = 0; } // G3 specific change end }; /////////////////////////////////////////////////////////////////////////////////////////////// /// \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); ~SangomaPort(); bool Open(const Configuration& configuration); bool Close(); int Read(unsigned int event_flag); ///< Reads Rx data or an Event and places them in the ReceiveBuffer. ///< Returns reason for wait object being signaled unsigned char *GetRxDataBuffer(); unsigned int GetRxDataLength(); 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 bool GetSynchronizationStatus(); unsigned int GetCardNumber() const {return CardNumber;} unsigned int GetPortNumber() const; ///< Returns this port's number bool GetConfiguration(Configuration& current_configuration); 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 bool GetReceiverLevelInDb(float& receiver_level_in_db); std::string GetLastError() const; ///< Returns a description of the last error that occurred (NO_ERROR_OCCURRED if the last command was successful) PortBuffer *pReceiveBuffer; ///< Buffers allocated to receive data for this port PortBuffer *pTransmitBuffer; ///< Buffers allocated to transmit data for this port unsigned int GetUnmappedPortNumber(); int SetAndOpenTxFile(const char *szTxFileName); ///< Open a file which will be continuesly transmitted int GetTransmitMtu() { return TxMtu; } ///< Provides the chunk size to be used each time data is written to the port. This changes based on the frame type. 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 RxDiscardCounter; ///< Number of rx buffers to discard after LineConnected event (the buffers may contain idle data). unsigned int RxCount; ///< Number of rx buffers to discard after LineConnected event (the buffers may contain idle data). unsigned int SyncCount; ///< Number of rx buffers to discard after LineConnected event (the buffers may contain idle data). unsigned int RxLength; ///< Number of rx buffers to discard after LineConnected event (the buffers may contain idle data). unsigned int next_framing_type; time_t rx_pkt_timeout; 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; ///< These are the settings for the buffer that holds the data when it is received. BufferSettings TransmitBufferSettings; ///< These are the settings for the buffer that holds the data that is to be transmitted. sangoma_interface *pSangomaInterface; 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