/**@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