Yate
yatemodem.h
00001 /*
00002  * yatemodem.h
00003  * This file is part of the YATE Project http://YATE.null.ro
00004  *
00005  * Yet Another Modem
00006  *
00007  * Yet Another Telephony Engine - a fully featured software PBX and IVR
00008  * Copyright (C) 2004-2006 Null Team
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
00023  */
00024 
00025 #ifndef __YATEMODEM_H
00026 #define __YATEMODEM_H
00027 
00028 #include <yateclass.h>
00029 
00030 #ifdef _WINDOWS
00031 
00032 #ifdef LIBYMODEM_EXPORTS
00033 #define YMODEM_API __declspec(dllexport)
00034 #else
00035 #ifndef LIBYMODEM_STATIC
00036 #define YMODEM_API __declspec(dllimport)
00037 #endif
00038 #endif
00039 
00040 #endif /* _WINDOWS */
00041 
00042 #ifndef YMODEM_API
00043 #define YMODEM_API
00044 #endif
00045 
00046 
00050 namespace TelEngine {
00051 
00052 class BitAccumulator;                    // 1-byte length bit accumulator
00053 class FSKModem;                          // Frequency Shift Keying modulator/demodulator
00054 class UART;                              // UART receiver/transmitter
00055 class UARTBuffer;                        // A byte accumulator used by an UART
00056 class ETSIModem;                         // An analog signal processor as defined by ETSI
00057 // Internal forward declarations
00058 class BitBuffer;                         // Used to accumulate all bits to be printed to output
00059 class FSKFilter;                         // The internal signal filter
00060 
00061 
00066 class YMODEM_API BitAccumulator
00067 {
00068 public:
00073     inline BitAccumulator(unsigned char dataBits)
00074         : m_crtByte(0), m_crtPos(0), m_dataBits(dataBits), m_oddParity(false)
00075         {}
00076 
00081     inline unsigned char dataBits() const
00082         { return m_dataBits; }
00083 
00088     inline void dataBits(unsigned char value) {
00089             m_dataBits = value;
00090             reset();
00091         }
00092 
00098     inline unsigned char reset(bool* oddParity = 0) {
00099             unsigned char tmp = m_crtByte;
00100             m_crtByte = m_crtPos = 0;
00101             if (oddParity)
00102                 *oddParity = m_oddParity;
00103             m_oddParity = false;
00104             return tmp;
00105         }
00106 
00113     inline unsigned int accumulate(bool bit, bool* oddParity = 0) {
00114             if (bit) {
00115                 m_crtByte |= (1 << m_crtPos);
00116                 m_oddParity = !m_oddParity;
00117             }
00118             m_crtPos++;
00119             if (m_crtPos != m_dataBits)
00120                 return 0xffff;
00121             return reset(oddParity);
00122         }
00123 
00124 private:
00125     unsigned char m_crtByte;             // Current partial byte
00126     unsigned char m_crtPos;              // Current free bit position
00127     unsigned char m_dataBits;            // The length of a data byte (interval: 1..8)
00128     bool m_oddParity;                    // The parity of the current byte value (true: odd)
00129 };
00130 
00131 
00137 class YMODEM_API FSKModem
00138 {
00139 public:
00143     enum Type {
00144         ETSI = 0,                        // ETSI caller id signal: MARK:1200 SPACE:2200 BAUDRATE:1200
00145                                          //  SAMPLERATE:8000 SAMPLES/BIT:7 STOPBITS:1 PARITY:NONE
00146         TypeCount = 1
00147         // NOTE: Don't change these values: they are used as array indexes
00148     };
00149 
00155     FSKModem(const NamedList& params, UART* uart);
00156 
00160     ~FSKModem();
00161 
00167     inline bool terminated() const
00168         { return m_terminated; }
00169 
00174     inline int type() const
00175         { return m_type; }
00176 
00180     void reset();
00181 
00187     bool demodulate(const DataBlock& data);
00188 
00197     void modulate(DataBlock& dest, const DataBlock& data);
00198 
00205     static inline void addRaw(DataBlock& dest, void* buf, unsigned int len) {
00206             DataBlock tmp(buf,len,false);
00207             dest += tmp;
00208             tmp.clear(false);
00209         }
00210 
00214     static TokenDict s_typeName[];
00215 
00216 private:
00217     int m_type;                          // Modem type
00218     bool m_terminated;                   // Terminated flag (need reset if true)
00219     FSKFilter* m_filter;                 // Internal filter used to demodulate received data
00220     UART* m_uart;                        // The UART using this modem's services
00221     DataBlock m_buffer;                  // Partial input buffer when used to demodulate or modulate data
00222     BitBuffer* m_bits;                   // Bit buffer used when debugging
00223 };
00224 
00225 
00230 class YMODEM_API UART : public DebugEnabler
00231 {
00232 public:
00236     enum State {
00237         Idle,                            // Not started
00238         BitStart,                        // Waiting for start bit (SPACE)
00239         BitData,                         // Accumulate data bits
00240         BitParity,                       // Waiting for parity bit(s)
00241         BitStop,                         // Waiting for stop bit (MARK)
00242         UARTError,                       // Error
00243     };
00244 
00248     enum Error {
00249         EFraming,                        // Frame error: invalid stop bit(s)
00250         EParity,                         // Parity error
00251         EChksum,                         // Message checksum error
00252         EInvalidData,                    // Invalid (inconsistent) data
00253         EUnknown,                        // Unknown error
00254         EStopped,                        // Aborted by descendants
00255         ENone
00256     };
00257 
00264     UART(State state, const NamedList& params, const char* name = 0);
00265 
00269     virtual ~UART()
00270         {}
00271 
00276     inline State state() const
00277         { return m_state; }
00278 
00283     inline Error error() const
00284         { return m_error; }
00285 
00290     inline int modemType() const
00291         { return m_modem.type(); }
00292 
00297     inline const BitAccumulator& accumulator() const
00298         { return m_accumulator; }
00299 
00304     virtual void reset(State newState = Idle);
00305 
00311     inline bool demodulate(const DataBlock& data)
00312         { return m_modem.demodulate(data); }
00313 
00320     inline bool modulate(DataBlock& dest, NamedList& params) {
00321             DataBlock data;
00322             if (!createMsg(params,data))
00323                 return false;
00324             m_modem.modulate(dest,data);
00325             return true;
00326         }
00327 
00333     inline void modulate(DataBlock& dest, const DataBlock& src)
00334         { m_modem.modulate(dest,src); }
00335 
00341     bool recvBit(bool value);
00342 
00348     virtual bool recvByte(unsigned char data)
00349         { return false; }
00350 
00355     virtual bool fskStarted()
00356         { return true; }
00357 
00361     static TokenDict s_errors[];
00362 
00363 protected:
00369     virtual int idleRecvByte(unsigned char data)
00370         { return false; }
00371 
00378     virtual bool createMsg(NamedList& params, DataBlock& data)
00379         { return false; }
00380 
00386     bool error(Error e);
00387 
00388 private: 
00389     // Change this UART's state
00390     void changeState(State newState);
00391 
00392     FSKModem m_modem;                    // The modem used by this UART
00393     State m_state;                       // The state of this UART
00394     Error m_error;                       // The error type if state is error
00395     int m_parity;                        // Used parity: 0=none, -1=odd, 1=even
00396     bool m_expectedParity;               // The expected value of the parity bit if used
00397     BitAccumulator m_accumulator;        // The data bits accumulator
00398 };
00399 
00400 
00405 class YMODEM_API UARTBuffer
00406 {
00407 public:
00412     inline UARTBuffer(UART* client)
00413         : m_client(client)
00414         { reset(); }
00415 
00420     inline const DataBlock& buffer() const
00421         { return m_buffer; }
00422 
00427     inline unsigned int free() const
00428         { return m_free; }
00429 
00434     inline void reset(unsigned int len = 0) {
00435             m_buffer.clear();
00436             m_crtIdx = m_free = 0;
00437             if (len) {
00438                 m_buffer.assign(0,len);
00439                 m_free = len;
00440             }
00441         }
00442 
00448     inline bool accumulate(unsigned char value) {
00449             if (m_free) {
00450                 ((unsigned char*)m_buffer.data())[m_crtIdx++] = value;
00451                 m_free--;
00452                 return true;
00453             }
00454             Debug(m_client,DebugNote,"Buffer overflow");
00455             return false;
00456         }
00457 
00458 private:
00459     UART* m_client;                      // The client
00460     unsigned int m_crtIdx;               // Current index n buffer
00461     unsigned int m_free;                 // Free buffer length
00462     DataBlock m_buffer;                  // The buffer
00463 };
00464 
00465 
00471 class YMODEM_API ETSIModem : public UART
00472 {
00473 public:
00477     enum State {
00478         StateError,                      // Error encountered: need reset
00479         WaitFSKStart,                    // Waiting for data start pattern
00480         WaitMark,                        // Waiting for mark pattern
00481         WaitMsg,                         // Wait a message
00482         WaitMsgLen,                      // Received message: wait length
00483         WaitParam,                       // Wait a parameter
00484         WaitParamLen,                    // Received parameter: wait length
00485         WaitData,                        // Received parameter length: wait data
00486         WaitChksum,                      // Wait checksum
00487     };
00488 
00492     enum MsgType {
00493         MsgCallSetup = 0x80,             // Call setup
00494         MsgMWI       = 0x82,             // Message waiting indicator
00495         MsgCharge    = 0x86,             // Advise of charge
00496         MsgSMS       = 0x89,             // Short message service
00497     };
00498 
00502     enum MsgParam {
00503         DateTime         = 0x01,         // 8           Date and Time
00504         CallerId         = 0x02,         // max. 20     Calling Line Identity
00505         CalledId         = 0x03,         // max. 20     Called Line Identity
00506         CallerIdReason   = 0x04,         // 1           Reason for Absence of Calling Line Identity
00507         CallerName       = 0x07,         // max. 50     Calling Party Name
00508         CallerNameReason = 0x08,         // 1           Reason for absence of Calling Party Name
00509         VisualIndicator  = 0x0B,         // 1           Visual Indicator
00510         MessageId        = 0x0D,         // 3           Message Identification
00511         LastMsgCLI       = 0x0E,         // max. 20     Last Message CLI
00512         CompDateTime     = 0x0F,         // 8 or 10     Complementary Date and Time
00513         CompCallerId     = 0x10,         // max. 20     Complementary Calling Line Identity
00514         CallType         = 0x11,         // 1           Call type
00515         FirstCalledId    = 0x12,         // max. 20     First Called Line Identity
00516         MWICount         = 0x13,         // 1           Number of Messages
00517         FwdCallType      = 0x15,         // 1           Type of Forwarded call
00518         CallerType       = 0x16,         // 1           Type of Calling user
00519         RedirNumber      = 0x1A,         // max. 20     Redirecting Number
00520         Charge           = 0x20,         // 14          Charge
00521         AdditionalCharge = 0x21,         // 14          Additional Charge
00522         Duration         = 0x23,         // 6           Duration of the Call
00523         NetworkID        = 0x30,         // max. 20     Network Provider Identity
00524         CarrierId        = 0x31,         // max. 20     Carrier Identity
00525         SelectFunction   = 0x40,         // 2-21        Selection of Terminal Function
00526         Display          = 0x50,         // max. 253    Display Information
00527         ServiceInfo      = 0x55,         // 1           Service Information
00528         Extension        = 0xE0,         // 10          Extension for network operator use
00529         Unknown
00530     };
00531 
00537     ETSIModem(const NamedList& params, const char* name = 0);
00538 
00542     virtual ~ETSIModem();
00543 
00547     virtual void reset();
00548 
00554     virtual bool recvByte(unsigned char data);
00555 
00559     static TokenDict s_msg[];
00560 
00564     static TokenDict s_msgParams[];
00565 
00566 protected:
00572     virtual int idleRecvByte(unsigned char data);
00573 
00580     virtual bool recvParams(MsgType msg, const NamedList& params)
00581         { return false; }
00582 
00589     virtual bool decode(MsgType msg, const DataBlock& buffer);
00590 
00598     virtual bool createMsg(NamedList& params, DataBlock& data);
00599 
00600 private:
00601     // Change decoder's state
00602     void changeState(State newState);
00603 
00604     UARTBuffer m_buffer;                 // The buffer used to accumulate messages
00605     State m_state;                       // Decoder state
00606     unsigned char m_waitSeizureCount;    // Expected number of channel seizure bytes in a row
00607     unsigned char m_crtSeizureCount;     // Current number of channel seizure bytes in a row
00608     unsigned char m_crtMsg;              // Current message id
00609     unsigned char m_crtParamLen;         // Current receiving parameter length
00610     unsigned int m_chksum;               // Current calculated checksum
00611 };
00612 
00613 }
00614 
00615 #endif /* __YATEMODEM_H */
00616 
00617 /* vi: set ts=8 sw=4 sts=4 noet: */