d5791c079f
git-svn-id: http://yate.null.ro/svn/yate/trunk@1562 acf43c95-373e-0410-b603-e72c3f656dc1
618 lines
19 KiB
C++
618 lines
19 KiB
C++
/*
|
|
* yatemodem.h
|
|
* This file is part of the YATE Project http://YATE.null.ro
|
|
*
|
|
* Yet Another Modem
|
|
*
|
|
* Yet Another Telephony Engine - a fully featured software PBX and IVR
|
|
* Copyright (C) 2004-2006 Null Team
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#ifndef __YATEMODEM_H
|
|
#define __YATEMODEM_H
|
|
|
|
#include <yateclass.h>
|
|
|
|
#ifdef _WINDOWS
|
|
|
|
#ifdef LIBYMODEM_EXPORTS
|
|
#define YMODEM_API __declspec(dllexport)
|
|
#else
|
|
#ifndef LIBYMODEM_STATIC
|
|
#define YMODEM_API __declspec(dllimport)
|
|
#endif
|
|
#endif
|
|
|
|
#endif /* _WINDOWS */
|
|
|
|
#ifndef YMODEM_API
|
|
#define YMODEM_API
|
|
#endif
|
|
|
|
|
|
/**
|
|
* Holds all Telephony Engine related classes.
|
|
*/
|
|
namespace TelEngine {
|
|
|
|
class BitAccumulator; // 1-byte length bit accumulator
|
|
class FSKModem; // Frequency Shift Keying modulator/demodulator
|
|
class UART; // UART receiver/transmitter
|
|
class UARTBuffer; // A byte accumulator used by an UART
|
|
class ETSIModem; // An analog signal processor as defined by ETSI
|
|
// Internal forward declarations
|
|
class BitBuffer; // Used to accumulate all bits to be printed to output
|
|
class FSKFilter; // The internal signal filter
|
|
|
|
|
|
/**
|
|
* This class encapsulates an 8 bits length buffer used to accumulate bits
|
|
* @short A 1-byte length bit accumulator
|
|
*/
|
|
class YMODEM_API BitAccumulator
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor
|
|
* @param dataBits The buffer size. Values interval 1..8
|
|
*/
|
|
inline BitAccumulator(unsigned char dataBits)
|
|
: m_crtByte(0), m_crtPos(0), m_dataBits(dataBits), m_oddParity(false)
|
|
{}
|
|
|
|
/**
|
|
* Get the buffer size
|
|
* @return The buffer size
|
|
*/
|
|
inline unsigned char dataBits() const
|
|
{ return m_dataBits; }
|
|
|
|
/**
|
|
* Set the buffer size. Reset the accumulator
|
|
* @param value The new buffer size. Values interval 1..8
|
|
*/
|
|
inline void dataBits(unsigned char value) {
|
|
m_dataBits = value;
|
|
reset();
|
|
}
|
|
|
|
/**
|
|
* Reset the accumulator. Returns the old data
|
|
* @param oddParity Optional pointer to get the parity of old data
|
|
* @return The old data
|
|
*/
|
|
inline unsigned char reset(bool* oddParity = 0) {
|
|
unsigned char tmp = m_crtByte;
|
|
m_crtByte = m_crtPos = 0;
|
|
if (oddParity)
|
|
*oddParity = m_oddParity;
|
|
m_oddParity = false;
|
|
return tmp;
|
|
}
|
|
|
|
/**
|
|
* Accumulate a bit. Reset accumulator when full
|
|
* @param bit The bit value to accumulate
|
|
* @param oddParity Optional pointer to get the data parity when full
|
|
* @return The accumulated byte or a value greater then 255 if incomplete
|
|
*/
|
|
inline unsigned int accumulate(bool bit, bool* oddParity = 0) {
|
|
if (bit) {
|
|
m_crtByte |= (1 << m_crtPos);
|
|
m_oddParity = !m_oddParity;
|
|
}
|
|
m_crtPos++;
|
|
if (m_crtPos != m_dataBits)
|
|
return 0xffff;
|
|
return reset(oddParity);
|
|
}
|
|
|
|
private:
|
|
unsigned char m_crtByte; // Current partial byte
|
|
unsigned char m_crtPos; // Current free bit position
|
|
unsigned char m_dataBits; // The length of a data byte (interval: 1..8)
|
|
bool m_oddParity; // The parity of the current byte value (true: odd)
|
|
};
|
|
|
|
|
|
/**
|
|
* This is a modulator/demodulator class attached to an UART. Used to demodulate bits
|
|
* from frequency modulated signal and send them to an UART
|
|
* @short A Frequency Shift Keying modem
|
|
*/
|
|
class YMODEM_API FSKModem
|
|
{
|
|
public:
|
|
/**
|
|
* Modem type enumeration
|
|
*/
|
|
enum Type {
|
|
ETSI = 0, // ETSI caller id signal: MARK:1200 SPACE:2200 BAUDRATE:1200
|
|
// SAMPLERATE:8000 SAMPLES/BIT:7 STOPBITS:1 PARITY:NONE
|
|
TypeCount = 1
|
|
// NOTE: Don't change these values: they are used as array indexes
|
|
};
|
|
|
|
/**
|
|
* Constructor
|
|
* @param params Modem parameters (including modemtype)
|
|
* @param uart The UART attached to this modem
|
|
*/
|
|
FSKModem(const NamedList& params, UART* uart);
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
~FSKModem();
|
|
|
|
/**
|
|
* Check if this modem is terminated. Need reset if so.
|
|
* The modem can terminate processing on UART's request
|
|
* @return True if this modem is terminated
|
|
*/
|
|
inline bool terminated() const
|
|
{ return m_terminated; }
|
|
|
|
/**
|
|
* Get the type of this modem
|
|
* @return The modem type
|
|
*/
|
|
inline int type() const
|
|
{ return m_type; }
|
|
|
|
/**
|
|
* Reset modem to its initial state
|
|
*/
|
|
void reset();
|
|
|
|
/**
|
|
* Data processor. Demodulate received data. Feed the UART with received bits
|
|
* @param data The data to process
|
|
* @return False to stop feedding data (terminated)
|
|
*/
|
|
bool demodulate(const DataBlock& data);
|
|
|
|
/**
|
|
* Create a buffer containing the modulated representation of a message.
|
|
* A data pattern (depending on modem's type) will be added before the message.
|
|
* A mark pattern (2ms long) will be added after the message.
|
|
* Reset the modem before each request to modulate
|
|
* @param dest Destination buffer
|
|
* @param data Message data (each byte will be enclosed in start/stop/parity bits)
|
|
*/
|
|
void modulate(DataBlock& dest, const DataBlock& data);
|
|
|
|
/**
|
|
* Append a raw buffer to a data block
|
|
* @param dest Destination buffer
|
|
* @param buf Buffer to append to destination
|
|
* @param len the number of bytes to append starting with buf
|
|
*/
|
|
static inline void addRaw(DataBlock& dest, void* buf, unsigned int len) {
|
|
DataBlock tmp(buf,len,false);
|
|
dest += tmp;
|
|
tmp.clear(false);
|
|
}
|
|
|
|
/**
|
|
* Keep the modem type names. Useful to configure the modem
|
|
*/
|
|
static TokenDict s_typeName[];
|
|
|
|
private:
|
|
int m_type; // Modem type
|
|
bool m_terminated; // Terminated flag (need reset if true)
|
|
FSKFilter* m_filter; // Internal filter used to demodulate received data
|
|
UART* m_uart; // The UART using this modem's services
|
|
DataBlock m_buffer; // Partial input buffer when used to demodulate or modulate data
|
|
BitBuffer* m_bits; // Bit buffer used when debugging
|
|
};
|
|
|
|
|
|
/**
|
|
* Accumulate data bits received from a modem
|
|
* @short An UART receiver/transmitter
|
|
*/
|
|
class YMODEM_API UART : public DebugEnabler
|
|
{
|
|
public:
|
|
/**
|
|
* UART state enumeration
|
|
*/
|
|
enum State {
|
|
Idle, // Not started
|
|
BitStart, // Waiting for start bit (SPACE)
|
|
BitData, // Accumulate data bits
|
|
BitParity, // Waiting for parity bit(s)
|
|
BitStop, // Waiting for stop bit (MARK)
|
|
UARTError, // Error
|
|
};
|
|
|
|
/**
|
|
* UART error enumeration
|
|
*/
|
|
enum Error {
|
|
EFraming, // Frame error: invalid stop bit(s)
|
|
EParity, // Parity error
|
|
EChksum, // Message checksum error
|
|
EInvalidData, // Invalid (inconsistent) data
|
|
EUnknown, // Unknown error
|
|
EStopped, // Aborted by descendants
|
|
ENone
|
|
};
|
|
|
|
/**
|
|
* Constructor
|
|
* @param state The initial state of this UART
|
|
* @param params The UART's parameters
|
|
* @param name The name of this debug enabler
|
|
*/
|
|
UART(State state, const NamedList& params, const char* name = 0);
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~UART()
|
|
{}
|
|
|
|
/**
|
|
* Get the current state of this UART
|
|
* @return The current state of this UART as enumeration
|
|
*/
|
|
inline State state() const
|
|
{ return m_state; }
|
|
|
|
/**
|
|
* Get the current error state of this UART, if any
|
|
* @return The current error state of this UART as enumeration
|
|
*/
|
|
inline Error error() const
|
|
{ return m_error; }
|
|
|
|
/**
|
|
* Get the type of this UART's modem
|
|
* @return The type of this UART's modem
|
|
*/
|
|
inline int modemType() const
|
|
{ return m_modem.type(); }
|
|
|
|
/**
|
|
* Get the data bit accumulator used by this UART
|
|
* @return The data bit accumulator used by this UART
|
|
*/
|
|
inline const BitAccumulator& accumulator() const
|
|
{ return m_accumulator; }
|
|
|
|
/**
|
|
* Reset this UART
|
|
* @param newState The state to reset to
|
|
*/
|
|
virtual void reset(State newState = Idle);
|
|
|
|
/**
|
|
* Send data to the enclosed modem to be demodulated
|
|
* @param data The data to process
|
|
* @return False to stop processing
|
|
*/
|
|
inline bool demodulate(const DataBlock& data)
|
|
{ return m_modem.demodulate(data); }
|
|
|
|
/**
|
|
* Create a buffer containing the modulated representation of a list of parameters
|
|
* @param dest Destination buffer
|
|
* @param params The list containing the values to be modulated
|
|
* @return False on failure (an 'error' parameter will be set in params)
|
|
*/
|
|
inline bool modulate(DataBlock& dest, NamedList& params) {
|
|
DataBlock data;
|
|
if (!createMsg(params,data))
|
|
return false;
|
|
m_modem.modulate(dest,data);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Create a buffer containing the modulated representation of another one
|
|
* @param dest Destination buffer
|
|
* @param src Source buffer
|
|
*/
|
|
inline void modulate(DataBlock& dest, const DataBlock& src)
|
|
{ m_modem.modulate(dest,src); }
|
|
|
|
/**
|
|
* Push a bit of data into this UART. Once a data byte is accumulated, push it back to itself
|
|
* @param value The bit to be processed
|
|
* @return False to stop feeding data
|
|
*/
|
|
bool recvBit(bool value);
|
|
|
|
/**
|
|
* Push a data byte into this UART
|
|
* @param data The byte to be processed
|
|
* @return False to stop feeding data
|
|
*/
|
|
virtual bool recvByte(unsigned char data)
|
|
{ return false; }
|
|
|
|
/**
|
|
* Notification from modem that the FSK start was detected
|
|
* @return False to stop the modem
|
|
*/
|
|
virtual bool fskStarted()
|
|
{ return true; }
|
|
|
|
/**
|
|
* Keeps the names associated with UART errors
|
|
*/
|
|
static TokenDict s_errors[];
|
|
|
|
protected:
|
|
/**
|
|
* Process an accumulated byte in Idle state
|
|
* @param data The byte to process
|
|
* @return Negative to stop, positive to change state to BitStart, 0 to continue
|
|
*/
|
|
virtual int idleRecvByte(unsigned char data)
|
|
{ return false; }
|
|
|
|
/**
|
|
* Create a buffer containing the byte representation of a message to be sent
|
|
* @param params The list containing message parameters
|
|
* @param data Destination message data buffer
|
|
* @return False on failure
|
|
*/
|
|
virtual bool createMsg(NamedList& params, DataBlock& data)
|
|
{ return false; }
|
|
|
|
/**
|
|
* Set the error state of this UART
|
|
* @param e The error
|
|
* @return False
|
|
*/
|
|
bool error(Error e);
|
|
|
|
private:
|
|
// Change this UART's state
|
|
void changeState(State newState);
|
|
|
|
FSKModem m_modem; // The modem used by this UART
|
|
State m_state; // The state of this UART
|
|
Error m_error; // The error type if state is error
|
|
int m_parity; // Used parity: 0=none, -1=odd, 1=even
|
|
bool m_expectedParity; // The expected value of the parity bit if used
|
|
BitAccumulator m_accumulator; // The data bits accumulator
|
|
};
|
|
|
|
|
|
/**
|
|
* This class is used by an UART to accumulate messages with known length
|
|
* @short A fixed length byte accumulator used by an UART
|
|
*/
|
|
class YMODEM_API UARTBuffer
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor
|
|
* @param client The client of this buffer
|
|
*/
|
|
inline UARTBuffer(UART* client)
|
|
: m_client(client)
|
|
{ reset(); }
|
|
|
|
/**
|
|
* Get the accumulated data
|
|
* @return The accumulated data
|
|
*/
|
|
inline const DataBlock& buffer() const
|
|
{ return m_buffer; }
|
|
|
|
/**
|
|
* Get the free space length in the buffer
|
|
* @return The free space length
|
|
*/
|
|
inline unsigned int free() const
|
|
{ return m_free; }
|
|
|
|
/**
|
|
* Reset the buffer
|
|
* @param len The new length of the buffer. Set to 0 to left the length unchanged
|
|
*/
|
|
inline void reset(unsigned int len = 0) {
|
|
m_buffer.clear();
|
|
m_crtIdx = m_free = 0;
|
|
if (len) {
|
|
m_buffer.assign(0,len);
|
|
m_free = len;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Accumulate data
|
|
* @param value The value to append to the buffer
|
|
* @return False on buffer overflow
|
|
*/
|
|
inline bool accumulate(unsigned char value) {
|
|
if (m_free) {
|
|
((unsigned char*)m_buffer.data())[m_crtIdx++] = value;
|
|
m_free--;
|
|
return true;
|
|
}
|
|
Debug(m_client,DebugNote,"Buffer overflow");
|
|
return false;
|
|
}
|
|
|
|
private:
|
|
UART* m_client; // The client
|
|
unsigned int m_crtIdx; // Current index n buffer
|
|
unsigned int m_free; // Free buffer length
|
|
DataBlock m_buffer; // The buffer
|
|
};
|
|
|
|
|
|
/**
|
|
* This class implements a modem/UART pair used to demodulate/decode analog signal as defined
|
|
* in ETSI EN 300 659-1, ETSI EN 300 659-2, ETSI EN 300 659-3
|
|
* @short An analog signal processor as defined by ETSI
|
|
*/
|
|
class YMODEM_API ETSIModem : public UART
|
|
{
|
|
public:
|
|
/**
|
|
* The state of this ETSI decoder
|
|
*/
|
|
enum State {
|
|
StateError, // Error encountered: need reset
|
|
WaitFSKStart, // Waiting for data start pattern
|
|
WaitMark, // Waiting for mark pattern
|
|
WaitMsg, // Wait a message
|
|
WaitMsgLen, // Received message: wait length
|
|
WaitParam, // Wait a parameter
|
|
WaitParamLen, // Received parameter: wait length
|
|
WaitData, // Received parameter length: wait data
|
|
WaitChksum, // Wait checksum
|
|
};
|
|
|
|
/**
|
|
* Message type defined in ETSI EN 659-3 5.2
|
|
*/
|
|
enum MsgType {
|
|
MsgCallSetup = 0x80, // Call setup
|
|
MsgMWI = 0x82, // Message waiting indicator
|
|
MsgCharge = 0x86, // Advise of charge
|
|
MsgSMS = 0x89, // Short message service
|
|
};
|
|
|
|
/**
|
|
* Message parameters defined in ETSI EN 659-3 5.3
|
|
*/
|
|
enum MsgParam {
|
|
DateTime = 0x01, // 8 Date and Time
|
|
CallerId = 0x02, // max. 20 Calling Line Identity
|
|
CalledId = 0x03, // max. 20 Called Line Identity
|
|
CallerIdReason = 0x04, // 1 Reason for Absence of Calling Line Identity
|
|
CallerName = 0x07, // max. 50 Calling Party Name
|
|
CallerNameReason = 0x08, // 1 Reason for absence of Calling Party Name
|
|
VisualIndicator = 0x0B, // 1 Visual Indicator
|
|
MessageId = 0x0D, // 3 Message Identification
|
|
LastMsgCLI = 0x0E, // max. 20 Last Message CLI
|
|
CompDateTime = 0x0F, // 8 or 10 Complementary Date and Time
|
|
CompCallerId = 0x10, // max. 20 Complementary Calling Line Identity
|
|
CallType = 0x11, // 1 Call type
|
|
FirstCalledId = 0x12, // max. 20 First Called Line Identity
|
|
MWICount = 0x13, // 1 Number of Messages
|
|
FwdCallType = 0x15, // 1 Type of Forwarded call
|
|
CallerType = 0x16, // 1 Type of Calling user
|
|
RedirNumber = 0x1A, // max. 20 Redirecting Number
|
|
Charge = 0x20, // 14 Charge
|
|
AdditionalCharge = 0x21, // 14 Additional Charge
|
|
Duration = 0x23, // 6 Duration of the Call
|
|
NetworkID = 0x30, // max. 20 Network Provider Identity
|
|
CarrierId = 0x31, // max. 20 Carrier Identity
|
|
SelectFunction = 0x40, // 2-21 Selection of Terminal Function
|
|
Display = 0x50, // max. 253 Display Information
|
|
ServiceInfo = 0x55, // 1 Service Information
|
|
Extension = 0xE0, // 10 Extension for network operator use
|
|
Unknown
|
|
};
|
|
|
|
/**
|
|
* Constructor
|
|
* @param params Decoder parameters
|
|
* @param name The name of this debug enabler
|
|
*/
|
|
ETSIModem(const NamedList& params, const char* name = 0);
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~ETSIModem();
|
|
|
|
/**
|
|
* Reset this decoder (modem and UART)
|
|
*/
|
|
virtual void reset();
|
|
|
|
/**
|
|
* Push a data byte into this decoder. Reset this UART and call decode after validated a received message
|
|
* @param data The byte to be processed
|
|
* @return False to stop feeding data
|
|
*/
|
|
virtual bool recvByte(unsigned char data);
|
|
|
|
/**
|
|
* Keeps the text associated with message type enumeration
|
|
*/
|
|
static TokenDict s_msg[];
|
|
|
|
/**
|
|
* Keeps the text associated with parameter type enumeration
|
|
*/
|
|
static TokenDict s_msgParams[];
|
|
|
|
protected:
|
|
/**
|
|
* Process an accumulated byte in Idle state
|
|
* @param data The byte to process
|
|
* @return Negative to stop, positive to change state to BitStart, 0 to continue
|
|
*/
|
|
virtual int idleRecvByte(unsigned char data);
|
|
|
|
/**
|
|
* Process a list of received message parameters
|
|
* @param msg The message type as enumeration
|
|
* @param params Message parameters
|
|
* @return False to stop processing data
|
|
*/
|
|
virtual bool recvParams(MsgType msg, const NamedList& params)
|
|
{ return false; }
|
|
|
|
/**
|
|
* Process (decode) a valid received buffer. Call recvParams() after decoding the message
|
|
* @param msg The message type as enumeration
|
|
* @param buffer The accumulated data bytes
|
|
* @return False to stop processing data
|
|
*/
|
|
virtual bool decode(MsgType msg, const DataBlock& buffer);
|
|
|
|
/**
|
|
* Create a buffer containing the byte representation of a message to be sent
|
|
* @param params The list containing message parameters.
|
|
* The name of the list must be a valid (known) message
|
|
* @param data Destination message data buffer
|
|
* @return False on failure (an 'error' parameter will be set in params)
|
|
*/
|
|
virtual bool createMsg(NamedList& params, DataBlock& data);
|
|
|
|
private:
|
|
// Change decoder's state
|
|
void changeState(State newState);
|
|
|
|
UARTBuffer m_buffer; // The buffer used to accumulate messages
|
|
State m_state; // Decoder state
|
|
unsigned char m_waitSeizureCount; // Expected number of channel seizure bytes in a row
|
|
unsigned char m_crtSeizureCount; // Current number of channel seizure bytes in a row
|
|
unsigned char m_crtMsg; // Current message id
|
|
unsigned char m_crtParamLen; // Current receiving parameter length
|
|
unsigned int m_chksum; // Current calculated checksum
|
|
};
|
|
|
|
}
|
|
|
|
#endif /* __YATEMODEM_H */
|
|
|
|
/* vi: set ts=8 sw=4 sts=4 noet: */
|