/**@file
@brief GSM Radio Resorce messages, from GSM 04.08 9.1.
*/
/*
* Copyright 2008, 2009, 2010 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 .
*/
#include
#include
#include "GSML3RRMessages.h"
#include
using namespace std;
using namespace GSM;
void L3Message::writeBody(L3Frame&,size_t&) const
{
LOG(ERROR) << "not implemented for " << MTI();
assert(0);
}
void L3Message::parseBody(const L3Frame&, size_t&)
{
LOG(ERROR) << "not implemented for " << MTI();
assert(0);
}
ostream& GSM::operator<<(ostream& os, L3RRMessage::MessageType val)
{
switch (val) {
case L3RRMessage::SystemInformationType1:
os << "System Information Type 1"; break;
case L3RRMessage::SystemInformationType2:
os << "System Information Type 2"; break;
case L3RRMessage::SystemInformationType2bis:
os << "System Information Type 2bis"; break;
case L3RRMessage::SystemInformationType2ter:
os << "System Information Type 2ter"; break;
case L3RRMessage::SystemInformationType3:
os << "System Information Type 3"; break;
case L3RRMessage::SystemInformationType4:
os << "System Information Type 4"; break;
case L3RRMessage::SystemInformationType5:
os << "System Information Type 5"; break;
case L3RRMessage::SystemInformationType5bis:
os << "System Information Type 5bis"; break;
case L3RRMessage::SystemInformationType5ter:
os << "System Information Type 5ter"; break;
case L3RRMessage::SystemInformationType6:
os << "System Information Type 6"; break;
case L3RRMessage::SystemInformationType7:
os << "System Information Type 7"; break;
case L3RRMessage::SystemInformationType8:
os << "System Information Type 8"; break;
case L3RRMessage::SystemInformationType9:
os << "System Information Type 9"; break;
case L3RRMessage::SystemInformationType13:
os << "System Information Type 13"; break;
case L3RRMessage::SystemInformationType16:
os << "System Information Type 16"; break;
case L3RRMessage::SystemInformationType17:
os << "System Information Type 17"; break;
case L3RRMessage::PagingResponse:
os << "Paging Response"; break;
case L3RRMessage::PagingRequestType1:
os << "Paging Request Type 1"; break;
case L3RRMessage::MeasurementReport:
os << "Measurement Report"; break;
case L3RRMessage::AssignmentComplete:
os << "Assignment Complete"; break;
case L3RRMessage::ImmediateAssignment:
os << "Immediate Assignment"; break;
case L3RRMessage::ImmediateAssignmentReject:
os << "Immediate Assignment Reject"; break;
case L3RRMessage::AssignmentCommand:
os << "Assignment Command"; break;
case L3RRMessage::AssignmentFailure:
os << "Assignment Failure"; break;
case L3RRMessage::ChannelRelease:
os << "Channel Release"; break;
case L3RRMessage::ChannelModeModify:
os << "Channel Mode Modify"; break;
case L3RRMessage::ChannelModeModifyAcknowledge:
os << "Channel Mode Modify Acknowledge"; break;
case L3RRMessage::GPRSSuspensionRequest:
os << "GPRS Suspension Request"; break;
case L3RRMessage::ClassmarkEnquiry:
os << "Classmark Enquiry"; break;
case L3RRMessage::ClassmarkChange:
os << "Classmark Change"; break;
case L3RRMessage::RRStatus:
os << "RR Status"; break;
case L3RRMessage::ApplicationInformation:
os << "Application Information"; break;
default: os << hex << "0x" << (int)val << dec;
}
return os;
}
void L3RRMessage::text(ostream& os) const
{
os << "RR " << (MessageType) MTI() << " ";
}
L3RRMessage* GSM::L3RRFactory(L3RRMessage::MessageType MTI)
{
switch (MTI) {
case L3RRMessage::ChannelRelease: return new L3ChannelRelease();
case L3RRMessage::AssignmentComplete: return new L3AssignmentComplete();
case L3RRMessage::AssignmentFailure: return new L3AssignmentFailure();
case L3RRMessage::RRStatus: return new L3RRStatus();
case L3RRMessage::PagingResponse: return new L3PagingResponse();
case L3RRMessage::ChannelModeModifyAcknowledge: return new L3ChannelModeModifyAcknowledge();
case L3RRMessage::ClassmarkChange: return new L3ClassmarkChange();
case L3RRMessage::ClassmarkEnquiry: return new L3ClassmarkEnquiry();
case L3RRMessage::MeasurementReport: return new L3MeasurementReport();
case L3RRMessage::ApplicationInformation: return new L3ApplicationInformation();
// Partial support just to get along with some phones.
case L3RRMessage::GPRSSuspensionRequest: return new L3GPRSSuspensionRequest();
default:
LOG(WARN) << "no L3 RR factory support for " << MTI;
return NULL;
}
}
L3RRMessage* GSM::parseL3RR(const L3Frame& source)
{
L3RRMessage::MessageType MTI = (L3RRMessage::MessageType)source.MTI();
LOG(DEBUG) << "parseL3RR MTI="<parse(source);
return retVal;
}
/**
This is a local function to map the GSM::ChannelType enum
to one of the codes from GMS 04.08 10.5.2.8.
*/
unsigned channelNeededCode(ChannelType wType)
{
switch (wType) {
case AnyDCCHType: return 0;
case SDCCHType: return 1;
case TCHFType: return 2;
case AnyTCHType: return 3;
default: assert(0);
}
}
size_t L3PagingRequestType1::bodyLength() const
{
int sz = mMobileIDs.size();
assert(sz<=2);
size_t sum=1;
sum += mMobileIDs[0].lengthLV();
if (sz>1) sum += mMobileIDs[1].lengthTLV();
return sum;
}
void L3PagingRequestType1::writeBody(L3Frame& dest, size_t &wp) const
{
// See GSM 04.08 9.1.22.
// Page Mode Page Mode M V 1/2 10.5.2.26
// Channels Needed M V 1/2
// Mobile Identity 1 M LV 2-9 10.5.1.4
// 0x17 Mobile Identity 2 O TLV 3-10 10.5.1.4
int sz = mMobileIDs.size();
assert(sz<=2);
// Remember to reverse orders of 1/2-octet fields.
// Because GSM transmits LSB-first within each byte.
// channel needed codes
dest.writeField(wp,channelNeededCode(mChannelsNeeded[1]),2);
dest.writeField(wp,channelNeededCode(mChannelsNeeded[0]),2);
// "normal paging", GSM 04.08 Table 10.5.63
dest.writeField(wp,0x0,4);
// the actual mobile IDs
mMobileIDs[0].writeLV(dest,wp);
if (sz>1) mMobileIDs[1].writeTLV(0x17,dest,wp);
}
void L3PagingRequestType1::text(ostream& os) const
{
L3RRMessage::text(os);
os << " mobileIDs=(";
for (unsigned i=0; i