/**@file @brief Elements for Radio Resource messsages, GSM 04.08 10.5.2. */ /* * Copyright 2008, 2009 Free Software Foundation, Inc. * * This software is distributed under the terms of the GNU Affero Public License. * See the COPYING file in the main directory for details. * * This use of this software may be subject to additional restrictions. * See the LEGAL file in the main directory for details. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ #ifndef GSML3RRELEMENTS_H #define GSML3RRELEMENTS_H #include #include "GSML3Message.h" #include namespace GSM { /** Cell Options (BCCH), GSM 04.08 10.5.2.3 */ class L3CellOptionsBCCH : public L3ProtocolElement { private: unsigned mPWRC; ///< 1 -> downlink power control may be used unsigned mDTX; ///< discontinuous transmission state unsigned mRADIO_LINK_TIMEOUT; ///< timeout to declare dead phy link public: /** Sets defaults for no use of DTX or downlink power control. */ L3CellOptionsBCCH() :L3ProtocolElement() { // Values dictated by the current implementation are hard-coded. mPWRC=0; mDTX=2; // Configuarable values. mRADIO_LINK_TIMEOUT= gConfig.getNum("GSM.RADIO_LINK_TIMEOUT"); } size_t lengthV() const { return 1; } void writeV(L3Frame& dest, size_t &wp) const; void parseV(const L3Frame&, size_t&) { assert(0); } void parseV(const L3Frame&, size_t& , size_t) { assert(0); } void text(std::ostream&) const; }; /** Cell Options (SACCH), GSM 04.08 10.5.2.3a */ class L3CellOptionsSACCH : public L3ProtocolElement { private: unsigned mPWRC; ///< 1 -> downlink power control may be used unsigned mDTX; ///< discontinuous transmission state unsigned mRADIO_LINK_TIMEOUT; ///< timeout to declare dead phy link public: /** Sets defaults for no use of DTX or downlink power control. */ L3CellOptionsSACCH() :L3ProtocolElement() { // Values dictated by the current implementation are hard-coded. mPWRC=0; mDTX=2; // Configuarable values. mRADIO_LINK_TIMEOUT=gConfig.getNum("GSM.RADIO_LINK_TIMEOUT"); } size_t lengthV() const { return 1; } void writeV(L3Frame& dest, size_t &wp) const; void parseV(const L3Frame&, size_t&) { assert(0); } void parseV(const L3Frame&, size_t& , size_t) { assert(0); } void text(std::ostream&) const; }; /** Cell Selection Parameters, GSM 04.08 10.5.2.4 */ class L3CellSelectionParameters : public L3ProtocolElement { private: unsigned mACS; unsigned mNECI; unsigned mCELL_RESELECT_HYSTERESIS; unsigned mMS_TXPWR_MAX_CCH; unsigned mRXLEV_ACCESS_MIN; public: /** Sets defaults to reduce gratuitous handovers. */ L3CellSelectionParameters() :L3ProtocolElement() { // Values dictated by the current implementation are hard-coded. mACS=0; // We don't support SI16 & SI17 yet. // Configurable values. mNECI=gConfig.getNum("GSM.CS.NECI"); mMS_TXPWR_MAX_CCH=gConfig.getNum("GSM.CS.MS_TXPWR_MAX_CCH"); mRXLEV_ACCESS_MIN=gConfig.getNum("GSM.CS.RXLEV_ACCESS_MIN"); mCELL_RESELECT_HYSTERESIS=gConfig.getNum("GSM.CS.CELL_RESELECT_HYSTERESIS"); } size_t lengthV() const { return 2; } void writeV(L3Frame& dest, size_t &wp) const; void parseV(const L3Frame&, size_t&) { assert(0); } void parseV(const L3Frame&, size_t& , size_t) { assert(0); } void text(std::ostream&) const; }; /** Control Channel Description, GSM 04.08 10.5.2.11 */ class L3ControlChannelDescription : public L3ProtocolElement { private: unsigned mATT; ///< 1 -> IMSI attach/detach unsigned mBS_AG_BLKS_RES; ///< access grant channel reservation unsigned mCCCH_CONF; ///< channel combination for CCCH unsigned mBS_PA_MFRMS; ///< paging channel configuration unsigned mT3212; ///< periodic updating timeout public: /** Sets reasonable defaults for a single-ARFCN system. */ L3ControlChannelDescription():L3ProtocolElement() { // Values dictated by the current implementation are hard-coded. mBS_AG_BLKS_RES=2; // reserve 2 CCCHs for access grant mBS_PA_MFRMS=0; // minimum PCH spacing // Configurable values. mATT=gConfig.getNum("GSM.CCD.ATT"); mCCCH_CONF=gConfig.getNum("GSM.CCD.CCCH_CONF"); mT3212=gConfig.getNum("GSM.T3212")/6; } size_t lengthV() const { return 3; } void writeV(L3Frame& dest, size_t &wp) const; void parseV(const L3Frame&, size_t&) { assert(0); } void parseV(const L3Frame&, size_t& , size_t) { assert(0); } void text(std::ostream&) const; }; /** A generic frequency list element base class, GSM 04.08 10.5.2.13. This implementation supports only the "variable bit map" format (GSM 04.08 10.5.2.13.7). */ class L3FrequencyList : public L3ProtocolElement { protected: std::vector mARFCNs; ///< ARFCN list to encode/decode public: /** Default constructor creates an empty list. */ L3FrequencyList():L3ProtocolElement() {} L3FrequencyList(const std::vector& wARFCNs) :L3ProtocolElement(), mARFCNs(wARFCNs) {} //void push_back(unsigned ARFCN) { mARFCNs.push_back(ARFCN); } void ARFCNs(const std::vector& wARFCNs) { mARFCNs=wARFCNs; } const std::vector& ARFCNs() const { return mARFCNs; } size_t lengthV() const { return 16; } void writeV(L3Frame& dest, size_t &wp) const; void parseV(const L3Frame&, size_t&) { assert(0); } void parseV(const L3Frame&, size_t& , size_t) { assert(0); } void text(std::ostream&) const; private: /**@name ARFCN set browsing. */ //@{ /** Return minimum-numbered ARFCN. */ unsigned base() const; /** Return numeric spread of ARFNs. */ unsigned spread() const; /** Return true if a given ARFCN is in the list. */ bool contains(unsigned wARFCN) const; //@} }; /** Cell Channel Description, GSM 04.08 10.5.2.1b. This element is used to provide the Cell Allocation for frequency hopping configurations. It lists the ARFCNs available for hopping and normally lists all of the ARFCNs for the system. It is mandatory, even if you don't use hopping. */ class L3CellChannelDescription : public L3FrequencyList { public: L3CellChannelDescription() :L3FrequencyList() {} void writeV(L3Frame& dest, size_t &wp) const; }; /** Neighbor Cells Description, GSM 04.08 10.5.2.22 (A kind of frequency list.) This element describes neighboring cells that may be candidates for handovers. */ class L3NeighborCellsDescription : public L3FrequencyList { public: L3NeighborCellsDescription() :L3FrequencyList(gConfig.getVector("GSM.Neighbors")) {} void writeV(L3Frame& dest, size_t &wp) const; void parseV(const L3Frame&, size_t&) { assert(0); } void parseV(const L3Frame&, size_t& , size_t) { assert(0); } void text(std::ostream&) const; }; /** NCC Permitted, GSM 04.08 10.5.2.27 */ class L3NCCPermitted : public L3ProtocolElement { private: unsigned mPermitted; ///< NCC allowance mask (NCCs 0-7) public: /** Get default parameters from gConfig. */ L3NCCPermitted() :L3ProtocolElement() { mPermitted = gConfig.getNum("GSM.NCCsPermitted"); } size_t lengthV() const { return 1; } void writeV(L3Frame& dest, size_t &wp) const; void parseV(const L3Frame&, size_t&) { assert(0); } void parseV(const L3Frame&, size_t& , size_t) { assert(0); } void text(std::ostream&) const; }; /** RACH Control Parameters GSM 04.08 10.5.2.29 */ class L3RACHControlParameters : public L3ProtocolElement { private: unsigned mMaxRetrans; ///< code for 1-7 RACH retransmission attempts unsigned mTxInteger; ///< code for 3-50 slots to spread transmission unsigned mCellBarAccess; ///< if true, phones cannot camp unsigned mRE; ///< if true, call reestablishment is not allowed uint16_t mAC; ///< mask of barring flags for the 16 access classes public: /** Default constructor parameters allows all access. */ L3RACHControlParameters() :L3ProtocolElement() { // Values ditected by imnplementation are hard-coded. mRE=1; mCellBarAccess=0; // Configurable values. mMaxRetrans = gConfig.getNum("GSM.RACH.MaxRetrans"); mTxInteger = gConfig.getNum("GSM.RACH.TxInteger"); mAC = gConfig.getNum("GSM.RACH.AC"); } size_t lengthV() const { return 3; } void writeV(L3Frame& dest, size_t &wp) const; void parseV(const L3Frame&, size_t&) { assert(0); } void parseV(const L3Frame&, size_t& , size_t) { assert(0); } void text(std::ostream&) const; }; /** PageMode, GSM 04.08 10.5.2.26 */ class L3PageMode : public L3ProtocolElement { unsigned mPageMode; public: /** Default mode is "normal paging". */ L3PageMode(unsigned wPageMode=0) :L3ProtocolElement(), mPageMode(wPageMode) {} size_t lengthV() const { return 1; } void writeV( L3Frame& dest, size_t &wp ) const; void parseV( const L3Frame &src, size_t &rp ); void parseV(const L3Frame&, size_t& , size_t) { assert(0); } void text(std::ostream&) const; }; /** DedicatedModeOrTBF, GSM 04.08 10.5.2.25b */ class L3DedicatedModeOrTBF : public L3ProtocolElement { unsigned mDownlink; ///< Indicates the IA reset octets contain additional information. unsigned mTMA; ///< This is part of a 2-message assignment. unsigned mDMOrTBF; ///< Dedicated link (circuit-switched) or temporary block flow (GPRS/pakcet). public: L3DedicatedModeOrTBF() :L3ProtocolElement(), mDownlink(0), mTMA(0), mDMOrTBF(0) {} size_t lengthV() const { return 1; } void writeV(L3Frame &dest, size_t &wp ) const; void parseV( const L3Frame&, size_t&) { assert(0); } void parseV(const L3Frame&, size_t& , size_t) { assert(0); } void text(std::ostream&) const; }; /** ChannelDescription, GSM 04.08 10.5.2.5 */ class L3ChannelDescription : public L3ProtocolElement { // Channel Description Format. // 7 6 5 4 3 2 1 0 // [ ChannelTypeTDMAOffset[4:0] ][ TN[2:0] ] Octect 1 // [ TSC ][ H=0 ][ SPARE(0,0)][ ARFCN[9:8] ] Octect 2 // [ [ H=1 ][ MAIO[5:2] ] Octect 2 // [ ARFCN[7:0] ] Octect 3 H=0 // [ MAIO[1:0] ][ HSN[5:0] ] Octect 3 H=1 // // Octet 2. TypeAndOffset mTypeAndOffset; // 5 bit unsigned mTN; //3 bit // Octet 3 & 4. unsigned mTSC; // 3 bit unsigned mHFlag; // 1 bit unsigned mARFCN; // 10 bit overflows unsigned mMAIO; // 6 bit overflows unsigned mHSN; // 6 bit public: /** Non-hopping initializer. */ L3ChannelDescription(TypeAndOffset wTypeAndOffset, unsigned wTN, unsigned wTSC, unsigned wARFCN) :mTypeAndOffset(wTypeAndOffset),mTN(wTN), mTSC(wTSC), mHFlag(0), mARFCN(wARFCN), mMAIO(0),mHSN(0) { } /** Blank initializer */ L3ChannelDescription() :mTypeAndOffset(TDMA_MISC), mTN(0),mTSC(0),mHFlag(0),mARFCN(0),mMAIO(0),mHSN(0) { } size_t lengthV() const { return 3; } void writeV( L3Frame &dest, size_t &wp ) const; void parseV(const L3Frame& src, size_t &rp); void parseV(const L3Frame&, size_t& , size_t) { assert(0); } void text(std::ostream&) const; }; /** RequestReference, GSM 04.08 10.5.2.30 */ class L3RequestReference : public L3ProtocolElement { // Request Reference Format. // 7 6 5 4 3 2 1 0 // [ RequestReference [7:0] ] Octet 2 // [ T1[4:0] ][ T3[5:3] ] Octet 3 // [ T3[2:0] ][ T2[4:0] ] Octet 4 unsigned mRA; ///< random tag from original RACH burst /**@name Timestamp of the corresponing RACH burst. */ //@{ unsigned mT1p; ///< T1 mod 32 unsigned mT2; unsigned mT3; //@} public: L3RequestReference() {} L3RequestReference(unsigned wRA, const GSM::Time& when) :mRA(wRA), mT1p(when.T1()%32),mT2(when.T2()),mT3(when.T3()) {} size_t lengthV() const { return 3; } void writeV(L3Frame &, size_t &wp ) const; void parseV( const L3Frame&, size_t&) { assert(0); } void parseV(const L3Frame&, size_t& , size_t) { assert(0); } void text(std::ostream&) const; }; /** Timing Advance, GSM 04.08 10.5.2.40 */ class L3TimingAdvance : public L3ProtocolElement { // TimingAdvance // 7 6 5 4 3 2 1 0 // [ spare(0,0) ][ TimingAdvance [5:0] ] Octet 1 unsigned mTimingAdvance; public: L3TimingAdvance(unsigned wTimingAdvance=0) :L3ProtocolElement(), mTimingAdvance(wTimingAdvance) {} size_t lengthV() const { return 1; } void writeV(L3Frame&, size_t &wp) const; void parseV(const L3Frame&, size_t&) { assert(0); } void parseV(const L3Frame&, size_t& , size_t) { assert(0); } void text(std::ostream&) const; }; /** GSM 04.08 10.5.2.31 */ class L3RRCause : public L3ProtocolElement { int mCauseValue; public: L3RRCause(int wValue=0) :L3ProtocolElement() { mCauseValue=wValue; } int causeValue() const { return mCauseValue; } size_t lengthV() const { return 1; } void writeV(L3Frame&, size_t&) const; void parseV(const L3Frame&, size_t&); void parseV(const L3Frame&, size_t& , size_t) { assert(0); } void text(std::ostream&) const; }; /** GSM 04.08 10.5.2.28 */ class L3PowerCommand : public L3ProtocolElement { unsigned mCommand; public: L3PowerCommand(unsigned wCommand=0) :L3ProtocolElement(), mCommand(wCommand) {} size_t lengthV() const { return 1; } void writeV( L3Frame &dest, size_t &wp ) const; void parseV( const L3Frame&, size_t&) { assert(0); } void parseV(const L3Frame&, size_t& , size_t) { assert(0); } void text(std::ostream&) const; }; /** GSM 04.08 10.5.2.6 */ class L3ChannelMode : public L3ProtocolElement { public: enum Mode { SignallingOnly=0, SpeechV1=1, SpeechV2=2, SpeechV3=3 }; private: Mode mMode; public: L3ChannelMode(Mode wMode=SignallingOnly) :L3ProtocolElement(), mMode(wMode) {} bool operator==(const L3ChannelMode& other) const { return mMode==other.mMode; } bool operator!=(const L3ChannelMode& other) const { return mMode!=other.mMode; } size_t lengthV() const { return 1; } void writeV(L3Frame&, size_t&) const; void parseV(const L3Frame&, size_t&); void parseV(const L3Frame&, size_t& , size_t) { assert(0); } void text(std::ostream&) const; }; std::ostream& operator<<(std::ostream&, L3ChannelMode::Mode); /** GSM 04.08 10.5.2.43 */ class L3WaitIndication : public L3ProtocolElement { private: unsigned mValue; ///< T3122 or T3142 value in seconds public: L3WaitIndication(unsigned seconds) :L3ProtocolElement(), mValue(seconds) {} size_t lengthV() const { return 1; } void writeV(L3Frame& dest, size_t &wp) const { dest.writeField(wp,mValue,8); } void parseV(const L3Frame&, size_t&) { assert(0); } void parseV(const L3Frame&, size_t& , size_t) { assert(0); } void text(std::ostream& os) const { os << mValue; } }; /** Application Information Information Elements (encapsulates the RRLP message) */ /** GSM 04.08 10.5.2.48 */ class L3APDUID : public L3ProtocolElement { private: unsigned mProtocolIdentifier; public: /** Default Protocol Identifier is RRLP=0, the only one defined so far (rest are reserved). */ L3APDUID(unsigned protocolIdentifier=0) :L3ProtocolElement(), mProtocolIdentifier(protocolIdentifier) {} size_t lengthV() const { return 1; } void writeV(L3Frame& dest, size_t &wp) const; void parseV(const L3Frame&, size_t&); void parseV(const L3Frame&, size_t& , size_t) { assert(0); } void text(std::ostream& os) const; }; /** GSM 04.08 10.5.2.49 */ class L3APDUFlags : public L3ProtocolElement { private: // TODO - use bool for flags? unsigned mCR; unsigned mFirstSegment; unsigned mLastSegment; // TODO - put enums for CR, FirstSegment, LastSegment public: /** Default is the flags for a single segment APDU - one that fits in a single Application Information message **/ L3APDUFlags(unsigned cr=0, unsigned firstSegment=0, unsigned lastSegment=0) :L3ProtocolElement(), mCR(cr), mFirstSegment(firstSegment), mLastSegment(lastSegment) {} size_t lengthV() const { return 1; } void writeV(L3Frame& dest, size_t &wp) const; void parseV(const L3Frame&, size_t&); void parseV(const L3Frame&, size_t& , size_t) { assert(0); } void text(std::ostream& os) const; }; /** GSM 04.08 10.5.2.50 */ class L3APDUData : public L3ProtocolElement { private: BitVector mData; // will contain a RRLP message public: virtual ~L3APDUData(); /** Default is a zero length APDUData IE */ L3APDUData(); L3APDUData(BitVector data); size_t lengthV() const { return mData.size(); }; void writeV(L3Frame& dest, size_t &wp) const; void parseV( const L3Frame& src, size_t &rp, size_t expectedLength ); void parseV(const L3Frame&, size_t&) { abort(); } void text(std::ostream& os) const; }; /** GSM 04.08 10.5.2.20 */ class L3MeasurementResults : public L3ProtocolElement { private: bool mBA_USED; bool mDTX_USED; bool mMEAS_VALID; ///< 0 for valid, 1 for non-valid unsigned mRXLEV_FULL_SERVING_CELL; unsigned mRXLEV_SUB_SERVING_CELL; unsigned mRXQUAL_FULL_SERVING_CELL; unsigned mRXQUAL_SUB_SERVING_CELL; unsigned mNO_NCELL; unsigned mRXLEV_NCELL[6]; unsigned mBCCH_FREQ_NCELL[6]; unsigned mBSIC_NCELL[6]; public: L3MeasurementResults() :mMEAS_VALID(false), mNO_NCELL(0) { } size_t lengthV() const { return 16; } void writeV(L3Frame&, size_t&) const { assert(0); } void parseV(const L3Frame&, size_t&); void parseV(const L3Frame&, size_t& , size_t) { assert(0); } void text(std::ostream& os) const; /**@name Accessors. */ //@{ bool BA_USED() const { return mBA_USED; } bool DTX_USED() const { return mDTX_USED; } bool MEAS_VALID() const { return mMEAS_VALID; } unsigned RXLEV_FULL_SERVING_CELL() const { return mRXLEV_FULL_SERVING_CELL; } unsigned RXLEV_SUB_SERVING_CELL() const { return mRXLEV_SUB_SERVING_CELL; } unsigned RXQUAL_FULL_SERVING_CELL() const { return mRXQUAL_FULL_SERVING_CELL; } unsigned RXQUAL_SUB_SERVING_CELL() const { return mRXQUAL_SUB_SERVING_CELL; } unsigned NO_NCELL() const { return mNO_NCELL; } unsigned RXLEV_NCELL(unsigned i) const { assert(i