laforge
/
openbts-osmo
Archived
1
0
Fork 0
This repository has been archived on 2022-03-30. You can view files and clone it, but cannot push or open issues or pull requests.
openbts-osmo/public-trunk/GSM/GSML3CCElements.cpp

317 lines
6.8 KiB
C++

/**@file
@brief Call Control messages, GSM 04.08 9.3
*/
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "GSML3CCElements.h"
#include <Logger.h>
using namespace std;
using namespace GSM;
void L3BearerCapability::writeV( L3Frame &dest, size_t &wp ) const
{
// See GSM 10.5.4.5.
// This is a hell of a complex element, inherited from ISDN.
// But we're going to ignore a lot of it.
// "octet 3"
// We hard code this octet for circuit switched speech.
dest.writeField(wp, 0x04, 8);
// "octet 3a"
// We hard code for full rate speech v1, the GSM 06.10 codec.
dest.writeField(wp,0x80,8);
}
void L3BearerCapability::parseV( const L3Frame& src, size_t &rp, size_t expectedLength )
{
// See GSM 10.5.4.5.
// This is a hell of a complex element, inherited from ISDN.
// But we're just going to assume circuit-switched speech
// with a full rate codec, since every phone supports that.
// So we can just ignore this hideously complex element.
// Just move the read index and return.
// Shhh. Our little secret.
rp += 8*expectedLength;
}
void L3BearerCapability::text(ostream& os) const
{
os << "(default)";
}
void L3BCDDigits::parse(const L3Frame& src, size_t &rp, size_t numOctets)
{
unsigned i=0;
size_t readOctets = 0;
while (readOctets < numOctets) {
unsigned d2 = src.readField(rp,4);
unsigned d1 = src.readField(rp,4);
readOctets++;
mDigits[i++]=d1+'0';
if (d2!=0x0f) mDigits[i++]=d2+'0';
if (i>maxDigits) L3_READ_ERROR;
}
mDigits[i++]='\0';
}
void L3BCDDigits::write(L3Frame& dest, size_t &wp) const
{
unsigned index = 0;
unsigned numDigits = strlen(mDigits);
while (index < numDigits) {
if ((index+1) < numDigits) dest.writeField(wp,mDigits[index+1]-'0',4);
else dest.writeField(wp,0x0f,4);
dest.writeField(wp,mDigits[index]-'0',4);
index += 2;
}
}
size_t L3BCDDigits::lengthV() const
{
unsigned sz = strlen(mDigits);
return (sz/2) + (sz%2);
}
ostream& GSM::operator<<(ostream& os, const L3BCDDigits& digits)
{
os << digits.digits();
return os;
}
void L3CalledPartyBCDNumber::writeV( L3Frame &dest, size_t &wp ) const
{
dest.writeField(wp, 0x01, 1);
dest.writeField(wp, mType, 3);
dest.writeField(wp, mPlan, 4);
mDigits.write(dest,wp);
}
void L3CalledPartyBCDNumber::parseV( const L3Frame &src, size_t &rp, size_t expectedLength )
{
LOG(DEBUG) << "L3CalledPartyBCDNumber::parseV rp="<<rp<<" expLen="<<expectedLength;
// ext bit must be 1
if (src.readField(rp, 1) != 1) L3_READ_ERROR;
mType = (TypeOfNumber)src.readField(rp, 3);
mPlan = (NumberingPlan)src.readField(rp, 4);
mDigits.parse(src,rp,expectedLength-1);
}
size_t L3CalledPartyBCDNumber::lengthV() const
{
if (mDigits.lengthV()==0) return 0;
return 1 + mDigits.lengthV();
}
void L3CalledPartyBCDNumber::text(ostream& os) const
{
os << "type=" << mType;
os << " plan=" << mPlan;
os << " digits=" << mDigits;
}
void L3CallingPartyBCDNumber::writeV( L3Frame &dest, size_t &wp ) const
{
// If Octet3a is extended, then write 0 else 1.
dest.writeField(wp, (!mHaveOctet3a & 0x01), 1);
dest.writeField(wp, mType, 3);
dest.writeField(wp, mPlan, 4);
if(mHaveOctet3a){
dest.writeField(wp, 0x01, 1);
dest.writeField(wp, mPresentationIndicator, 2);
dest.writeField(wp, 0, 3);
dest.writeField(wp, mScreeningIndicator, 2);
}
mDigits.write(dest,wp);
}
void L3CallingPartyBCDNumber::parseV( const L3Frame &src, size_t &rp, size_t expectedLength)
{
size_t remainingLength = expectedLength;
// Read out first bit = 1.
mHaveOctet3a = src.readField(rp, 1);
mType = (TypeOfNumber)src.readField(rp, 3);
mPlan = (NumberingPlan)src.readField(rp, 4);
remainingLength -= 1;
if (mHaveOctet3a) {
if (src.readField(rp,1)!=1) L3_READ_ERROR;
mPresentationIndicator = src.readField(rp, 3);
src.readField(rp,3);
mScreeningIndicator = src.readField(rp, 4);
remainingLength -= 1;
}
mDigits.parse(src,rp,remainingLength);
}
size_t L3CallingPartyBCDNumber::lengthV() const
{
return 1 + mHaveOctet3a + mDigits.lengthV();
}
void L3CallingPartyBCDNumber::text(ostream& os) const
{
os << "type=" << mType;
os << " plan=" << mPlan;
if (mHaveOctet3a) {
os << " presentation=" << mPresentationIndicator;
os << " screening=" << mScreeningIndicator;
}
os << " digits=" << mDigits;
}
void L3Cause::parseV(const L3Frame& src, size_t &rp , size_t expectedLength)
{
size_t pos = rp;
rp += 8*expectedLength;
// Octet 3
// We only supprt the GSM coding standard.
if (src.readField(pos,4)!=0x0e) L3_READ_ERROR;
mLocation = (Location)src.readField(pos,4);
// Octet 4
if (src.readField(pos,1)!=1) L3_READ_ERROR;
mCause = src.readField(pos,7);
// Skip the diagnostics.
}
void L3Cause::writeV(L3Frame& dest, size_t &wp) const
{
// Write Octet3.
dest.writeField(wp,0x0e,4);
dest.writeField(wp,mLocation,4);
// Write Octet 4.
dest.writeField(wp,0x01,1);
dest.writeField(wp,mCause,7);
}
void L3Cause::text(ostream& os) const
{
os << "location=" << mLocation;
os << " cause=0x" << hex << mCause << dec;
}
void L3CallState::parseV( const L3Frame& src, size_t &rp)
{
rp +=2;
mCallState = src.readField(rp, 6);
}
void L3CallState::writeV( L3Frame& dest, size_t &wp ) const
{
dest.writeField(wp,3,2);
dest.writeField(wp, mCallState, 6);
}
void L3CallState::text(ostream& os) const
{
os << mCallState;
}
void L3ProgressIndicator::writeV(L3Frame& dest, size_t &wp) const
{
// octet 3
// ext bit, GSM coding standard, spare bit
dest.writeField(wp,0x0e,4);
dest.writeField(wp,mLocation,4);
// octet 4
dest.writeField(wp,1,1);
dest.writeField(wp,mProgress,7);
}
void L3ProgressIndicator::text(ostream& os) const
{
os << "location=" << mLocation;
os << " progress=0x" << hex << mProgress << dec;
}
void L3KeypadFacility::parseV(const L3Frame& src, size_t &rp)
{
mIA5 = src.readField(rp,8);
}
void L3KeypadFacility::writeV(L3Frame& dest, size_t &wp) const
{
dest.writeField(wp,mIA5,8);
}
void L3KeypadFacility::text(ostream& os) const
{
os << hex << "0x" << mIA5 << dec;
}
// vim: ts=4 sw=4