[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] r10089 - in openbts/trunk: Control GSM SIP apps
From: |
dburgess00 |
Subject: |
[Commit-gnuradio] r10089 - in openbts/trunk: Control GSM SIP apps |
Date: |
Sat, 29 Nov 2008 15:46:56 -0700 (MST) |
Author: dburgess00
Date: 2008-11-29 15:46:56 -0700 (Sat, 29 Nov 2008)
New Revision: 10089
Added:
openbts/trunk/Control/DCCHDispatch.cpp
Removed:
openbts/trunk/Control/FACCHDispatch.cpp
openbts/trunk/Control/SDCCHDispatch.cpp
Modified:
openbts/trunk/Control/CallControl.cpp
openbts/trunk/Control/ControlCommon.h
openbts/trunk/Control/Makefile.am
openbts/trunk/Control/MobilityManagement.cpp
openbts/trunk/Control/PagerTest.cpp
openbts/trunk/Control/RadioResource.cpp
openbts/trunk/GSM/GSMCommon.cpp
openbts/trunk/GSM/GSMCommon.h
openbts/trunk/GSM/GSML2LAPDm.cpp
openbts/trunk/GSM/GSML3Message.h
openbts/trunk/GSM/GSML3RRElements.cpp
openbts/trunk/GSM/GSML3RRElements.h
openbts/trunk/GSM/GSML3RRMessages.cpp
openbts/trunk/GSM/GSML3RRMessages.h
openbts/trunk/SIP/SIPInterface.cpp
openbts/trunk/apps/OpenBTS850.cpp
openbts/trunk/apps/OpenBTS900.cpp
Log:
Support very early assignment for mobile-terminating calls.
Merge in from branches/developers/dburgess00/veryearly/, r10066:10088.
Includes fixes for #316, #327.
Modified: openbts/trunk/Control/CallControl.cpp
===================================================================
--- openbts/trunk/Control/CallControl.cpp 2008-11-29 06:27:41 UTC (rev
10088)
+++ openbts/trunk/Control/CallControl.cpp 2008-11-29 22:46:56 UTC (rev
10089)
@@ -456,15 +456,20 @@
/**
- This function starts MOC to the point of TCH assignment.
+ This function starts MOC on the SDCCH to the point of TCH assignment.
@param req The CM Service Request that started all of this.
- @param SDCCH The SDCCH used to initiate call setup.
+ @param LCH The logical used to initiate call setup.
*/
-void Control::MOCStarter(const L3CMServiceRequest* req, SDCCHLogicalChannel
*SDCCH)
+void Control::MOCStarter(const L3CMServiceRequest* req, LogicalChannel *LCH)
{
+ assert(LCH);
assert(req);
CLDCOUT("MOC: " << *req);
+ // Determine if very early assignment already happened.
+ bool veryEarly=false;
+ if (LCH->type()==FACCHType) veryEarly=true;
+
// FIXME -- At this point, verify the that subscriber has access to
this service.
// If the subscriber isn't authorized, send a CM Service Reject with
// cause code, 0x41, "requested service option not subscribed",
@@ -478,25 +483,28 @@
// FIXME -- This is quick-and-dirty, not following GSM 04.08 5.
CERR("WARNING -- (ControlLayer) MOC setup with no IMSI");
// Cause 0x60 "Invalid mandatory information"
- SDCCH->send(L3CMServiceReject(L3RejectCause(0x60)));
- SDCCH->send(L3ChannelRelease());
+ LCH->send(L3CMServiceReject(L3RejectCause(0x60)));
+ LCH->send(L3ChannelRelease());
// The SIP side and transaction record don't exist yet.
// So we're done.
return;
}
- // Allocate a TCH for the call.
- TCHFACCHLogicalChannel *TCH = allocateTCH(SDCCH);
- // It's OK to just return on failure; allocateTCH cleaned up already.
- if (TCH==NULL) return;
+ // Allocate a TCH for the call, if we don't have it already.
+ TCHFACCHLogicalChannel *TCH = NULL;
+ if (!veryEarly) {
+ TCH = allocateTCH(dynamic_cast<SDCCHLogicalChannel*>(LCH));
+ // It's OK to just return on failure; allocateTCH cleaned up
already.
+ if (TCH==NULL) return;
+ }
// Let the phone know we're going ahead with the transaction.
CLDCOUT("MOC: sending CMServiceAccept")
- SDCCH->send(L3CMServiceAccept());
+ LCH->send(L3CMServiceAccept());
// Get the Setup message.
// GSM 04.08 5.2.1.2
- const L3Setup *setup = dynamic_cast<const L3Setup*>(getMessage(SDCCH));
+ const L3Setup *setup = dynamic_cast<const L3Setup*>(getMessage(LCH));
if (setup==NULL) throw UnexpectedMessage();
CLDCOUT("MOC: " << *setup);
// Pull out the L3 short transaction information now.
@@ -506,8 +514,8 @@
// FIXME -- This is quick-and-dirty, not following GSM 04.08 5.
CERR("WARNING -- (ControlLayer) MOC setup with no number");
// Cause 0x60 "Invalid mandatory information"
- SDCCH->send(L3ReleaseComplete(0,L3TI,L3Cause(0x60)));
- SDCCH->send(L3ChannelRelease());
+ LCH->send(L3ReleaseComplete(0,L3TI,L3Cause(0x60)));
+ LCH->send(L3ChannelRelease());
// The SIP side and transaction record don't exist yet.
// So we're done.
return;
@@ -527,16 +535,16 @@
setup->calledPartyBCDNumber());
transaction.SIP().User(IMSI);
transaction.Q931State(TransactionEntry::MOCInitiated);
- SDCCH->transactionID(transaction.ID());
- TCH->transactionID(transaction.ID());
+ LCH->transactionID(transaction.ID());
+ if (!veryEarly) TCH->transactionID(transaction.ID());
CLDCOUT("MOC: transaction: " << transaction);
gTransactionTable.add(transaction);
// At this point, we have enough information start the SIP call setup.
// We have 2 seconds to repsond to the MS. ITU-T Q.931 Table 9-1, T303.
- // Now start a call by contacting asterisk. engine methods will return
their
- // current state.
+ // Now start a call by contacting asterisk.
+ // Engine methods will return their current state.
// The remote party will start ringing soon.
CLDCOUT("MOC: starting SIP (INVITE) Calling "<<bcd_digits);
unsigned basePort = allocateRTPPorts();
@@ -548,14 +556,30 @@
delete setup;
// The transaction is moving on to the MOCController.
+ // If we need a TCH assignment, we do it here.
gTransactionTable.update(transaction);
CLDCOUT("MOC: transaction: " << transaction);
- // This call also opens the TCH.
- assignTCHF(SDCCH,TCH);
+ if (veryEarly) {
+ // For very early assignment, we need a mode change.
+ static const L3ChannelMode mode(L3ChannelMode::SpeechV1);
+ LCH->send(L3ChannelModeModify(LCH->channelDescription(),mode));
+ const L3ChannelModeModifyAcknowledge *ack =
+
dynamic_cast<L3ChannelModeModifyAcknowledge*>(getMessage(LCH));
+ if (!ack) throw UnexpectedMessage();
+ // Cause 0x06 is "channel unacceptable"
+ if (ack->mode() != mode) return
abortCall(transaction,LCH,L3Cause(0x06));
+
MOCController(transaction,dynamic_cast<TCHFACCHLogicalChannel*>(LCH));
+ } else {
+ // For late assignment, send the TCH assignment now.
+ // This dispatcher on the next channel will continue the
transaction.
+ assignTCHF(dynamic_cast<SDCCHLogicalChannel*>(LCH),TCH);
+ }
}
+
+
/**
Continue MOC process on the TCH.
@param transaction The call state and SIP interface.
@@ -565,6 +589,7 @@
{
CLDCOUT("MOC: transaction: " << transaction);
unsigned L3TI = transaction.TIValue();
+ assert(TCH);
// Once we can start SIP call setup, send Call Proceeding.
CLDCOUT("MOC: Sending Call Proceeding ");
@@ -682,16 +707,24 @@
-void Control::MTCStarter(const L3PagingResponse *resp,
- SDCCHLogicalChannel *SDCCH)
+void Control::MTCStarter(const L3PagingResponse *resp, LogicalChannel *LCH)
{
assert(resp);
- CLDCOUT("MTC: " << *resp);
+ assert(LCH);
+ CLDCOUT("MTC on " << LCH->type() << ": " << *resp);
+ // Determine if very early assigment already happened.
+ bool veryEarly = false;
+ if (LCH->type()==FACCHType) veryEarly=true;
+
// Allocate a TCH for the call.
- TCHFACCHLogicalChannel *TCH = allocateTCH(SDCCH);
- // The orphaned transaction will be cleared at the next findByMobileID
call.
- if (TCH==NULL) return;
+ TCHFACCHLogicalChannel *TCH = NULL;
+ if (!veryEarly) {
+ TCH = allocateTCH(dynamic_cast<SDCCHLogicalChannel*>(LCH));
+ // It's OK to just return on failure; allocateTCH cleaned up
already.
+ // The orphaned transaction will be cleared at the next
findByMobileID call.
+ if (TCH==NULL) return;
+ }
// Find the transction table entry that was created when the phone was
paged.
CLDCOUT("MTC: find TransactionEntry for " << resp->mobileIdentity());
@@ -701,13 +734,13 @@
return;
}
CLDCOUT("MTC: transaction: "<< transaction);
- TCH->transactionID(transaction.ID());
- SDCCH->transactionID(transaction.ID());
+ if (!veryEarly) TCH->transactionID(transaction.ID());
+ LCH->transactionID(transaction.ID());
unsigned L3TI = transaction.TIValue();
// GSM 04.08 5.2.2.1
CLDCOUT("MTC: sending GSM Setup");
- SDCCH->send(L3Setup(0,L3TI));
+ LCH->send(L3Setup(0,L3TI));
transaction.T303().set();
transaction.Q931State(TransactionEntry::CallPresent);
@@ -715,31 +748,47 @@
CLDCOUT("MTC: wait for GSM Call Confirmed")
while (transaction.Q931State()!=TransactionEntry::MTCConfirmed) {
if (transaction.SIP().MTCSendTrying()==SIP::Fail) {
- TCH->send(RELEASE);
- return abortCall(transaction,SDCCH,L3Cause(0x7F));
+ LCH->send(RELEASE);
+ // Cause 0x03 is "no route to destination"
+ return abortCall(transaction,LCH,L3Cause(0x03));
}
// FIXME -- What's the proper timeout here?
// It's the SIP TRYING timeout, whatever that is.
- if (updateGSMSignalling(transaction,SDCCH,1000)) {
+ if (updateGSMSignalling(transaction,LCH,1000)) {
CLDCOUT("MTC: Release from GSM side");
- TCH->send(RELEASE);
+ LCH->send(RELEASE);
return;
}
// Check for SIP cancel, too.
if (transaction.SIP().MTCWaitForACK()==SIP::Fail) {
- TCH->send(RELEASE);
- return abortCall(transaction,SDCCH,L3Cause(0x7F));
+ LCH->send(RELEASE);
+ // Cause 0x10 is "normal clearing"
+ return abortCall(transaction,LCH,L3Cause(0x10));
}
}
// The transaction is moving to the MTCController.
gTransactionTable.update(transaction);
CLDCOUT("MTC: transaction: " << transaction);
- assignTCHF(SDCCH,TCH);
+ if (veryEarly) {
+ // For very early assignment, we need a mode change.
+ static const L3ChannelMode mode(L3ChannelMode::SpeechV1);
+ LCH->send(L3ChannelModeModify(LCH->channelDescription(),mode));
+ const L3ChannelModeModifyAcknowledge *ack =
+
dynamic_cast<L3ChannelModeModifyAcknowledge*>(getMessage(LCH));
+ if (!ack) throw UnexpectedMessage();
+ // Cause 0x06 is "channel unacceptable"
+ if (ack->mode() != mode) return
abortCall(transaction,LCH,L3Cause(0x06));
+
MTCController(transaction,dynamic_cast<TCHFACCHLogicalChannel*>(LCH));
+ }
+ else {
+ // For late assignment, send the TCH assignment now.
+ // This dispatcher on the next channel will continue the
transaction.
+ assignTCHF(dynamic_cast<SDCCHLogicalChannel*>(LCH),TCH);
+ }
}
-
void Control::MTCController(TransactionEntry& transaction,
TCHFACCHLogicalChannel* TCH)
{
// Early Assignment Mobile Terminated Call.
@@ -747,6 +796,7 @@
CLDCOUT("MTC: transaction: " << transaction);
unsigned L3TI = transaction.TIValue();
+ assert(TCH);
// Get the alerting message.
CLDCOUT("MTC:: waiting for GSM Alerting and Connect");
Modified: openbts/trunk/Control/ControlCommon.h
===================================================================
--- openbts/trunk/Control/ControlCommon.h 2008-11-29 06:27:41 UTC (rev
10088)
+++ openbts/trunk/Control/ControlCommon.h 2008-11-29 22:46:56 UTC (rev
10089)
@@ -47,6 +47,7 @@
#include <GSML3CommonElements.h>
#include <GSML3MMElements.h>
#include <GSML3CCElements.h>
+#include <GSML3RRMessages.h>
#include <SIPEngine.h>
@@ -142,28 +143,36 @@
/address@hidden Functions for mobility manangement operations. */
//@{
-void CMServiceResponder(const GSM::L3CMServiceRequest* cmsrq,
GSM::SDCCHLogicalChannel* SDCCH);
+void CMServiceResponder(const GSM::L3CMServiceRequest* cmsrq,
GSM::LogicalChannel* DCCH);
void IMSIDetachController(const GSM::L3IMSIDetachIndication* idi,
GSM::SDCCHLogicalChannel* SDCCH);
void LocationUpdatingController(const GSM::L3LocationUpdatingRequest* lur,
GSM::SDCCHLogicalChannel* SDCCH);
//@}
/address@hidden Functions for radio resource operations. */
//@{
+/** Decode RACH bits and send an immediate assignment. */
void AccessGrantResponder(unsigned requestReference, const GSM::Time& when);
-void PagingResponseHandler(const GSM::L3PagingResponse*,
GSM::SDCCHLogicalChannel*);
+/** Find and compelte the in-process transaction associated with a paging
repsonse. */
+void PagingResponseHandler(const GSM::L3PagingResponse*, GSM::LogicalChannel*);
+/** Find and compelte the in-process transaction associated with a completed
assignment. */
+void AssignmentCompleteHandler(const GSM::L3AssignmentComplete*,
GSM::TCHFACCHLogicalChannel*);
//@}
/address@hidden Functions for call control operations. */
//@{
/address@hidden MOC */
//@{
-void MOCStarter(const GSM::L3CMServiceRequest* req, GSM::SDCCHLogicalChannel
*SDCCH);
-void MOCController(TransactionEntry& transaction, GSM::TCHFACCHLogicalChannel*
TCHFACCH);
+/** Run the MOC to the point of alerting, doing early assignment if needed. */
+void MOCStarter(const GSM::L3CMServiceRequest*, GSM::LogicalChannel*);
+/** Complete the MOC connection. */
+void MOCController(TransactionEntry&, GSM::TCHFACCHLogicalChannel*);
//@}
/address@hidden MTC */
//@{
-void MTCStarter(const GSM::L3PagingResponse *resp, GSM::SDCCHLogicalChannel
*SDCCH);
-void MTCController(TransactionEntry& transaction, GSM::TCHFACCHLogicalChannel*
TCHFACCH);
+/** Run the MTC to the point of alerting, doing early assignment if needed. */
+void MTCStarter(const GSM::L3PagingResponse*, GSM::LogicalChannel*);
+/** Complete the MTC connection. */
+void MTCController(TransactionEntry&, GSM::TCHFACCHLogicalChannel*);
//@}
/address@hidden MOSMS */
//@{
@@ -186,6 +195,7 @@
//@{
void FACCHDispatcher(GSM::TCHFACCHLogicalChannel *TCHFACCH);
void SDCCHDispatcher(GSM::SDCCHLogicalChannel *SDCCH);
+void DCCHDispatcher(GSM::LogicalChannel *DCCH);
//@}
@@ -199,6 +209,7 @@
private:
// FIXME -- We need to support channel type. See tracker item #316.
+ GSM::ChannelType mType; ///< The needed channel type.
GSM::L3MobileIdentity mID; ///< The mobile ID.
Timeval mExpiration; ///< The expiration time for
this entry.
@@ -209,13 +220,16 @@
@param wID The ID to be paged.
@param wLife The number of milliseconds to keep paging.
*/
- PagingEntry(const GSM::L3MobileIdentity& wID, unsigned wLife)
- :mID(wID),mExpiration(wLife)
+ PagingEntry(const GSM::L3MobileIdentity& wID, GSM::ChannelType wType,
unsigned wLife)
+ :mID(wID),mType(wType),mExpiration(wLife)
{}
/** Access the ID. */
const GSM::L3MobileIdentity& ID() const { return mID; }
+ /** Access the channel type needed. */
+ const GSM::ChannelType type() const { return mType; }
+
/** Renew the timer. */
void renew(unsigned wLife) { mExpiration = Timeval(wLife); }
@@ -252,9 +266,10 @@
/**
Add a mobile ID to the paging list.
@param addID The mobile ID to be paged.
+ @param chanType The channel type to be requested.
@param wLife The paging duration in ms, default based on SIP
INVITE retry preiod.
*/
- void addID(const GSM::L3MobileIdentity& addID, unsigned wLife=4000);
+ void addID(const GSM::L3MobileIdentity& addID, GSM::ChannelType
chanType, unsigned wLife=4000);
private:
Copied: openbts/trunk/Control/DCCHDispatch.cpp (from rev 10088,
openbts/branches/developers/dburgess00/veryearly/Control/DCCHDispatch.cpp)
===================================================================
--- openbts/trunk/Control/DCCHDispatch.cpp (rev 0)
+++ openbts/trunk/Control/DCCHDispatch.cpp 2008-11-29 22:46:56 UTC (rev
10089)
@@ -0,0 +1,179 @@
+/address@hidden Idle-mode dispatcher for dedicated control channels. */
+
+/*
+* Copyright 2008 Free Software Foundation, Inc.
+*
+* This software is distributed under the terms of the GNU Public License.
+* See the COPYING 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 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+
+
+#include "ControlCommon.h"
+#include <GSMLogicalChannel.h>
+#include <GSML3MMMessages.h>
+#include <GSML3RRMessages.h>
+#include <SIPUtility.h>
+#include <SIPInterface.h>
+
+using namespace std;
+using namespace GSM;
+using namespace Control;
+
+
+
+
+/**
+ Dispatch the appropriate controller for a Mobility Management message.
+ @param req A pointer to the initial message.
+ @param DCCH A pointer to the logical channel for the transaction.
+*/
+void DCCHDispatchMM(const L3MMMessage* req, LogicalChannel *DCCH)
+{
+ assert(req);
+ L3MMMessage::MessageType MTI = (L3MMMessage::MessageType)req->MTI();
+ switch (MTI) {
+ case L3MMMessage::LocationUpdatingRequest:
+ LocationUpdatingController(dynamic_cast<const
L3LocationUpdatingRequest*>(req),
+
dynamic_cast<SDCCHLogicalChannel*>(DCCH));
+ break;
+ case L3MMMessage::IMSIDetachIndication:
+ IMSIDetachController(dynamic_cast<const
L3IMSIDetachIndication*>(req),
+
dynamic_cast<SDCCHLogicalChannel*>(DCCH));
+ break;
+ case L3MMMessage::CMServiceRequest:
+ CMServiceResponder(dynamic_cast<const
L3CMServiceRequest*>(req),DCCH);
+ break;
+ default:
+ CERR("NOTICE -- (ControlLayer) unhandled MM message "
<< MTI << " on " << DCCH->type());
+ throw UnsupportedMessage();
+ }
+}
+
+
+/**
+ Dispatch the appropriate controller for a Radio Resource message.
+ @param req A pointer to the initial message.
+ @param DCCH A pointer to the logical channel for the transaction.
+*/
+void DCCHDispatchRR(const L3RRMessage* req, LogicalChannel *DCCH)
+{
+ CLDCOUT("DCCHDispatchRR: cheking MTI"<<
(L3RRMessage::MessageType)req->MTI() )
+
+ assert(req);
+ L3RRMessage::MessageType MTI = (L3RRMessage::MessageType)req->MTI();
+ switch (MTI) {
+ case L3RRMessage::PagingResponse:
+ PagingResponseHandler(dynamic_cast<const
L3PagingResponse*>(req),DCCH);
+ break;
+ case L3RRMessage::AssignmentComplete:
+ AssignmentCompleteHandler(dynamic_cast<const
L3AssignmentComplete*>(req),
+
dynamic_cast<TCHFACCHLogicalChannel*>(DCCH));
+ break;
+ default:
+ CERR("NOTICE -- (ControlLayer) unhandled RR message "
<< MTI << " on " << DCCH->type());
+ throw UnsupportedMessage();
+ }
+}
+
+
+
+
+
+
+/** Example of a closed-loop, persistent-thread control function for the DCCH.
*/
+void Control::DCCHDispatcher(LogicalChannel *DCCH)
+{
+ while (1) {
+ try {
+ // Wait for a transaction to start.
+ CLDCOUT("DCCHDisptacher waiting for " << DCCH->type()
<< " ESTABLISH");
+ while (!waitForPrimitive(DCCH,ESTABLISH)) {}
+ // Pull the first message and dispatch a new
transaction.
+ const L3Message *message = getMessage(DCCH);
+ CLDCOUT("DCCHDispatcher got " << *message);
+ // Each protocol has it's own sub-dispatcher.
+ switch (message->PD()) {
+ case L3MobilityManagementPD:
+ DCCHDispatchMM(dynamic_cast<const
L3MMMessage*>(message),DCCH);
+ break;
+ case L3RadioResourcePD:
+ DCCHDispatchRR(dynamic_cast<const
L3RRMessage*>(message),DCCH);
+ break;
+ default:
+ CERR("NOTICE -- (ControlLayer)
unhandled protocol "
+ << message->PD() << " on DCCH");
+ throw UnsupportedMessage();
+ }
+ delete message;
+ }
+
+ // Catch the various error cases.
+
+ catch (ChannelReadTimeout except) {
+ clearTransactionHistory(except.transactionID());
+ CERR("NOTICE -- ChannelReadTimeout");
+ // Cause 0x03 means "abnormal release, timer expired".
+ DCCH->send(L3ChannelRelease(0x03));
+ }
+ catch (UnexpectedPrimitive except) {
+ clearTransactionHistory(except.transactionID());
+ CERR("NOTICE -- UnexpectedPrimitive");
+ // Cause 0x62 means "message type not not compatible
with protocol state".
+ DCCH->send(L3ChannelRelease(0x62));
+ }
+ catch (UnexpectedMessage except) {
+ clearTransactionHistory(except.transactionID());
+ CERR("NOTICE -- UnexpectedMessage");
+ // Cause 0x62 means "message type not not compatible
with protocol state".
+ DCCH->send(L3ChannelRelease(0x62));
+ }
+ catch (UnsupportedMessage except) {
+ clearTransactionHistory(except.transactionID());
+ CERR("NOTICE -- UnsupportedMessage");
+ // Cause 0x61 means "message type not implemented".
+ DCCH->send(L3ChannelRelease(0x61));
+ }
+ catch (Q931TimerExpired except) {
+ clearTransactionHistory(except.transactionID());
+ CERR("NOTICE -- Q.931 T3xx timer expired");
+ // Cause 0x03 means "abnormal release, timer expired".
+ DCCH->send(L3ChannelRelease(0x03));
+ }
+ catch (SIP::SIPTimeout) {
+ CERR("NOTICE -- Uncaught SIP Timeout");
+ // Cause 0x03 means "abnormal release, timer expired".
+ DCCH->send(L3ChannelRelease(0x03));
+ }
+ catch (SIP::SIPError) {
+ CERR("NOTICE -- Uncaught SIP Error");
+ // Cause 0x01 means "abnormal release, unspecified".
+ DCCH->send(L3ChannelRelease(0x01));
+ }
+
+ CLDCOUT("DCCHDisptacher waiting for " << DCCH->type() << "
RELEASE");
+ //FIXME -- What's the GSM 04.08 Txxx value for this?
+ // Probably N200 * T200
+ waitForPrimitive(DCCH,RELEASE,20000);
+ }
+}
+
+
+
+
+// vim: ts=4 sw=4
Deleted: openbts/trunk/Control/FACCHDispatch.cpp
Modified: openbts/trunk/Control/Makefile.am
===================================================================
--- openbts/trunk/Control/Makefile.am 2008-11-29 06:27:41 UTC (rev 10088)
+++ openbts/trunk/Control/Makefile.am 2008-11-29 22:46:56 UTC (rev 10089)
@@ -31,10 +31,9 @@
libcontrol_la_SOURCES = \
CallControl.cpp \
ControlCommon.cpp \
- FACCHDispatch.cpp \
MobilityManagement.cpp \
RadioResource.cpp \
- SDCCHDispatch.cpp
+ DCCHDispatch.cpp
PagerTest_SOURCES = PagerTest.cpp
PagerTest_LDADD = \
Modified: openbts/trunk/Control/MobilityManagement.cpp
===================================================================
--- openbts/trunk/Control/MobilityManagement.cpp 2008-11-29 06:27:41 UTC
(rev 10088)
+++ openbts/trunk/Control/MobilityManagement.cpp 2008-11-29 22:46:56 UTC
(rev 10089)
@@ -52,24 +52,24 @@
/** Controller for CM Service requests, dispatches out to multiple possible
transaction controllers. */
-void Control::CMServiceResponder(const L3CMServiceRequest* cmsrq,
SDCCHLogicalChannel* SDCCH)
+void Control::CMServiceResponder(const L3CMServiceRequest* cmsrq,
LogicalChannel* DCCH)
{
assert(cmsrq);
CLDCOUT("CMServiceResponder " << *cmsrq);
switch (cmsrq->serviceType().type()) {
case L3CMServiceType::MobileOriginatedCall:
- MOCStarter(cmsrq,SDCCH);
+ MOCStarter(cmsrq,DCCH);
break;
#ifdef SMS
case L3CMServiceType::ShortMessage:
- ShortMessageServiceStarter(cmsrq, SDCCH);
+ ShortMessageServiceStarter(cmsrq,
dynamic_cast<SDCCHLogicalChannel*>(SDCCH));
break;
#endif
default:
CLDCOUT("CMServiceResponder service not supported");
// Cause 0x20 means "serivce not supported".
- SDCCH->send(L3CMServiceReject(0x20));
- SDCCH->send(L3ChannelRelease());
+ DCCH->send(L3CMServiceReject(0x20));
+ DCCH->send(L3ChannelRelease());
}
}
Modified: openbts/trunk/Control/PagerTest.cpp
===================================================================
--- openbts/trunk/Control/PagerTest.cpp 2008-11-29 06:27:41 UTC (rev 10088)
+++ openbts/trunk/Control/PagerTest.cpp 2008-11-29 22:46:56 UTC (rev 10089)
@@ -59,9 +59,9 @@
pager.start();
while (1) {
- pager.addID(L3MobileIdentity(random()));
- pager.addID(L3MobileIdentity(random()));
- pager.addID(L3MobileIdentity("123456789012345"));
+ pager.addID(L3MobileIdentity(random()),GSM::AnyDCCHType);
+ pager.addID(L3MobileIdentity(random()),GSM::AnyDCCHType);
+
pager.addID(L3MobileIdentity("123456789012345"),GSM::AnyDCCHType);
sleep(random() % 2);
}
}
Modified: openbts/trunk/Control/RadioResource.cpp
===================================================================
--- openbts/trunk/Control/RadioResource.cpp 2008-11-29 06:27:41 UTC (rev
10088)
+++ openbts/trunk/Control/RadioResource.cpp 2008-11-29 22:46:56 UTC (rev
10089)
@@ -75,6 +75,52 @@
//@}
+/**
+ Determine the channel type needed.
+ This is based on GSM 04.08 Table 9.3 and 9.3a.
+ The following is assumed about the global BTS capabilities:
+ - We do not support "new establishment causes" and NECI is 0.
+ - We do not support call reestablishment.
+ - We do not support GPRS.
+ @param RA The request reference from the channel request message.
+ @return channel type code, undefined if not a supported service
+*/
+ChannelType decodeChannelNeeded(unsigned RA)
+{
+ // These values assume NECI is 0.
+ // This code is formatted so that it lines up easily with GSM 04.08
Table 9.9.
+ //
+ if ((RA>>5) == 0x05) return TCHFType; // emergency
call
+ //
+ // skip re-establishment cases
+ //
+ // "Answer to paging"
+ if ((RA>>5) == 0x04) return SDCCHType; // answer to
paging, any channel
+ if ((RA>>4) == 0x01) return SDCCHType; // answer to
paging, SDCCH
+ if ((RA>>4) == 0x02) return TCHFType; // answer to
paging, TCH/F
+ if ((RA>>4) == 0x03) return TCHFType; // answer to
paging, TCH/F or TCH/H
+ //
+ if ((RA>>5) == 0x07) return SDCCHType; // MOC or SDCCH
procedures
+ //
+ if ((RA>>4) == 0x04) return TCHFType; // MOC
+ //
+ // skip originating data call cases
+ //
+ if ((RA>>5) == 0x00) return SDCCHType; // location
updating
+ //
+ if ((RA>>4) == 0x00) return SDCCHType; // location
updating
+ //
+ // skip packet (GPRS) cases
+ //
+ // skip LMU case
+ //
+ // skip reserved cases
+ //
+ // Anything else falls through to here.
+ return UndefinedCHType;
+}
+
+
void Control::AccessGrantResponder(unsigned RA, const GSM::Time& when)
{
// RR Establishment.
@@ -82,35 +128,31 @@
// GSM 04.08 3.3.1.1.3.
// Given a request reference, try to allocate a channel
// and send the assignment to the handset on the CCCH.
+ // This GSM's version of medium access control.
// Papa Legba, open that door...
CLDCOUT("AccessGrantResponder RA=" << RA << " when=" << when);
// FIXME -- Check "when" against current clock to see if we're too late.
- // Check the request type to see if it's a service we don't even
support.
+ // Determine the channel type needed.
+ ChannelType chanNeeded = decodeChannelNeeded(RA);
+
+ // Allocate the channel.
+ LogicalChannel *LCH = NULL;
+ if (chanNeeded==TCHFType) LCH = gBTS.getTCH();
+ if (chanNeeded==SDCCHType) LCH = gBTS.getSDCCH();
// If we don't support it, ignore it.
- if ((RA&0xe0)==0x70) return; // GPRS
- if ((RA&0xe0)==0x60) return; // TCH/H reestablishment & some
reserved codes
- if (RA==0x67) return; // LMU
- if (RA==0xef) return; // reserved
+ if (LCH==NULL) return;
// Get an AGCH to send on.
CCCHLogicalChannel *AGCH = gBTS.getAGCH();
assert(AGCH);
- // FIXME -- We are ASSUMING that SDCCH is OK.
- // The truth is that we should decode according GSM 04.08 9.1.8, Table
9.9a.
-
- // Get an SDCCH to assign to.
- SDCCHLogicalChannel *SDCCH = gBTS.getSDCCH();
-
// Nothing available?
- if (!SDCCH) {
+ if (!LCH) {
// Rejection, GSM 04.08 3.3.1.1.3.2.
- // Emergency calls are not subject to T3122 hold-off.
- // They are not handled as a special case because the
- // MS will ignore the T3122 setting.
+ // BTW, emergency calls are not subject to T3122 hold-off.
CERR("NOTICE -- Access Grant CONGESTION");
unsigned waitTime = curT3122()/1000;
CLDCOUT("AccessGrantResponder: assginment reject, wait time "
<< waitTime);
@@ -123,10 +165,10 @@
// Assignment, GSM 04.08 3.3.1.1.3.1.
// Create the ImmediateAssignment message.
// For most of the message, default IE values are correct.
- const L3ImmediateAssignment
assign(L3RequestReference(RA,when),SDCCH->channelDescription());
+ const L3ImmediateAssignment
assign(L3RequestReference(RA,when),LCH->channelDescription());
CLDCOUT("AccessGrantResponder sending " << assign);
AGCH->send(assign);
- SDCCH->open();
+ // This was opened by the gBTS.getXXX() method. LCH->open();
// Reset exponential back-off upon successful allocation.
restoreT3122();
@@ -136,8 +178,10 @@
-void Control::PagingResponseHandler(const L3PagingResponse* resp,
SDCCHLogicalChannel* SDCCH)
+void Control::PagingResponseHandler(const L3PagingResponse* resp,
LogicalChannel* DCCH)
{
+ assert(resp);
+ assert(DCCH);
CLDCOUT("PagingResponseHandler " << *resp);
// FIXME -- Delete the Mobile ID from the paging list to free up CCCH
bandwidth.
@@ -146,9 +190,10 @@
// if not a legitimate reason, need to release the channel.
// FIXME -- Check the transaction table to see if the call is still
valid.
+
#ifndef PAGERTEST
// For now, assume MTC.
- MTCStarter(resp, SDCCH);
+ MTCStarter(resp, DCCH);
#else
COUT("starting MTC...");
#endif
@@ -156,12 +201,42 @@
+void Control::AssignmentCompleteHandler(const L3AssignmentComplete *confirm,
TCHFACCHLogicalChannel *TCH)
+{
+ assert(TCH);
+ assert(confirm);
+ // Check the transaction table to know what to do next.
+ TransactionEntry transaction;
+ if (!gTransactionTable.find(TCH->transactionID(),transaction)) {
+ CLDCOUT("NOTICE -- Assignment Complete from channel with no
transaction");
+ throw UnexpectedMessage();
+ }
+ CLDCOUT("AssignmentCompleteHandler
service="<<transaction.service().type());
+ // These "controller" functions don't return until the call is cleared.
+ switch (transaction.service().type()) {
+ case L3CMServiceType::MobileOriginatedCall:
+ MOCController(transaction,TCH);
+ break;
+ case L3CMServiceType::MobileTerminatedCall:
+ MTCController(transaction,TCH);
+ break;
+ default:
+ CLDCOUT("NOTICE -- request for unsupported service " <<
transaction.service());
+ throw UnsupportedMessage();
+ }
+ // If we got here, the call is cleared.
+ clearTransactionHistory(TCH->transactionID());
+}
-void Pager::addID(const L3MobileIdentity& newID, unsigned wLife)
+
+
+
+
+void Pager::addID(const L3MobileIdentity& newID, ChannelType chanType,
unsigned wLife)
{
// Add a mobile ID to the paging list for a given lifetime.
@@ -180,7 +255,7 @@
}
// If this ID is new, put it in the list.
if (!renewed) {
- mPageIDs.push_back(PagingEntry(newID,wLife));
+ mPageIDs.push_back(PagingEntry(newID,chanType,wLife));
CLDCOUT("Pager::addID " << newID << " added to table");
}
// Signal in case the paging loop is waiting for new entries.
@@ -210,22 +285,25 @@
// Page remaining entries, two at a time if possible.
list<PagingEntry>::iterator lp = mPageIDs.begin();
while (lp != mPageIDs.end()) {
- // HACK -- Just pick the minimum load channel.
- // FIXME -- This completely ignores the paging goups, GSM 04.08
10.5.2.11 and GSM 05.02 6.5.2.
- GSM::CCCHLogicalChannel *PCH = gBTS.getPCH();
+ // FIXME -- This completely ignores the paging groups, GSM
04.08 10.5.2.11 and GSM 05.02 6.5.2.
+ CCCHLogicalChannel *PCH = gBTS.getPCH();
assert(PCH);
- const L3MobileIdentity& id1 = lp->ID(); ++lp;
+ const L3MobileIdentity& id1 = lp->ID();
+ ChannelType type1 = lp->type();
+ ++lp;
if (lp==mPageIDs.end()) {
// Just one ID left?
//CLDCOUT("Pager::pageAll paging " << id1);
- PCH->send(L3PagingRequestType1(id1));
+ PCH->send(L3PagingRequestType1(id1,type1));
numPaged++;
break;
}
// Page by pairs when possible.
- const L3MobileIdentity& id2 = lp->ID(); ++lp;
+ const L3MobileIdentity& id2 = lp->ID();
+ ChannelType type2 = lp->type();
+ ++lp;
//CLDCOUT("Pager::pageAll paging " << id1 << " and " << id2);
- PCH->send(L3PagingRequestType1(id1,id2));
+ PCH->send(L3PagingRequestType1(id1,type1,id2,type2));
numPaged += 2;
}
Deleted: openbts/trunk/Control/SDCCHDispatch.cpp
Modified: openbts/trunk/GSM/GSMCommon.cpp
===================================================================
--- openbts/trunk/GSM/GSMCommon.cpp 2008-11-29 06:27:41 UTC (rev 10088)
+++ openbts/trunk/GSM/GSMCommon.cpp 2008-11-29 22:46:56 UTC (rev 10089)
@@ -274,8 +274,10 @@
case SACCHType: os << "SACCH"; break;
case TCHFType: os << "TCH/F"; break;
case TCHHType: os << "TCH/H"; break;
- case LoopbackFullType: os << "LoopbackFull"; break;
- case LoopbackHalfType: os << "LoopbackHalf"; break;
+ case AnyTCHType: os << "any TCH"; break;
+ case LoopbackFullType: os << "Loopback Full"; break;
+ case LoopbackHalfType: os << "Loopback Half"; break;
+ case AnyDCCHType: os << "any DCCH"; break;
default: os << "?" << (int)val << "?";
}
return os;
Modified: openbts/trunk/GSM/GSMCommon.h
===================================================================
--- openbts/trunk/GSM/GSMCommon.h 2008-11-29 06:27:41 UTC (rev 10088)
+++ openbts/trunk/GSM/GSMCommon.h 2008-11-29 22:46:56 UTC (rev 10089)
@@ -185,12 +185,14 @@
//@{
TCHFType, ///< full-rate traffic
TCHHType, ///< half-rate traffic
+ AnyTCHType, ///< any TCH type
//@}
///@name Special internal channel types.
//@{
LoopbackFullType, ///< loopback testing
LoopbackHalfType, ///< loopback testing
- UndefinedCHType, ///< undefined
+ AnyDCCHType, ///< any dedicated control channel
+ UndefinedCHType, ///< undefined
//@}
};
Modified: openbts/trunk/GSM/GSML2LAPDm.cpp
===================================================================
--- openbts/trunk/GSM/GSML2LAPDm.cpp 2008-11-29 06:27:41 UTC (rev 10088)
+++ openbts/trunk/GSM/GSML2LAPDm.cpp 2008-11-29 22:46:56 UTC (rev 10089)
@@ -43,6 +43,7 @@
using namespace std;
using namespace GSM;
+//#define NDEBUG
ostream& GSM::operator<<(ostream& os, L2LAPDm::LAPDState state)
Modified: openbts/trunk/GSM/GSML3Message.h
===================================================================
--- openbts/trunk/GSM/GSML3Message.h 2008-11-29 06:27:41 UTC (rev 10088)
+++ openbts/trunk/GSM/GSML3Message.h 2008-11-29 22:46:56 UTC (rev 10089)
@@ -102,7 +102,7 @@
It can't be pure virtual because it is not needed by all
subclasses.
*/
virtual void writeBody(L3Frame& dest, size_t &writePosition) const
- { abort(); }
+ { CERR("unimplemented L3Message::writeBody"); abort(); }
/**
The parseBody() method starts processing at the first byte
following the
@@ -111,7 +111,7 @@
It can't be pure virtual because it is not needed by all
subclasses.
*/
virtual void parseBody(const L3Frame& source, size_t &readPosition)
- { abort(); }
+ { CERR("unimplemented L3Message::parseBody"); abort(); }
public:
@@ -201,7 +201,7 @@
@param rp Bit index of read position (updated by read).
*/
virtual void parseV(const L3Frame& src, size_t &rp )
- { abort(); }
+ { CERR("unimplemented L3ProtocolElement::parseV"); abort(); }
/**
The parseV method decodes L3 message bits from variable-length value
parts.
@@ -213,7 +213,7 @@
@param expectedLength Length of available field, in bytes.
*/
virtual void parseV(const L3Frame& src, size_t &rp, size_t
expectedLength)
- { abort(); }
+ { CERR("unimplemented L3ProtocolElement::parseV"); abort(); }
/**
@@ -250,7 +250,7 @@
@param wp The write index (updated by write).
*/
virtual void writeV(L3Frame& dest, size_t &wp) const
- { abort(); }
+ { CERR("unimplemented L3ProtocolElement::writeV"); abort(); }
/**
Write LV format.
Modified: openbts/trunk/GSM/GSML3RRElements.cpp
===================================================================
--- openbts/trunk/GSM/GSML3RRElements.cpp 2008-11-29 06:27:41 UTC (rev
10088)
+++ openbts/trunk/GSM/GSML3RRElements.cpp 2008-11-29 22:46:56 UTC (rev
10089)
@@ -111,6 +111,7 @@
}
+
void L3ControlChannelDescription::text(ostream& os) const
{
os << "ATT=" << mATT;
@@ -298,6 +299,7 @@
void L3ChannelDescription::writeV( L3Frame &dest, size_t &wp ) const
{
+ // GSM 04.08 10.5.2.5
// Channel Description Format (non-hopping)
// 7 6 5 4 3 2 1 0
// [ TSC ][ H=0 ][ SPARE(0,0)][ ARFCN[9:8] ] Octet 3
@@ -305,7 +307,7 @@
//
// HACK -- Hard code for non-hopping.
-
+ assert(mHFlag==0);
dest.writeField(wp,mTypeAndOffset,5);
dest.writeField(wp,mTN,3);
dest.writeField(wp,mTSC,3);
@@ -314,6 +316,24 @@
}
+
+void L3ChannelDescription::parseV(const L3Frame& src, size_t &rp)
+{
+ // GSM 04.08 10.5.2.5
+ mTypeAndOffset = (TypeAndOffset)src.readField(rp,5);
+ mTN = src.readField(rp,3);
+ mTSC = src.readField(rp,3);
+ mHFlag = src.readField(rp,1);
+ if (mHFlag) {
+ mMAIO = src.readField(rp,6);
+ mHSN = src.readField(rp,6);
+ } else {
+ rp += 2; // skip 2 spare bits
+ mARFCN = src.readField(rp,10);
+ }
+}
+
+
void L3ChannelDescription::text(std::ostream& os) const
{
@@ -405,6 +425,13 @@
dest.writeField(wp, mMode, 8);
}
+void L3ChannelMode::parseV(const L3Frame& src, size_t& rp)
+{
+ mMode = (Mode)src.readField(rp,8);
+}
+
+
+
ostream& GSM::operator<<(ostream& os, L3ChannelMode::Mode mode)
{
switch (mode) {
Modified: openbts/trunk/GSM/GSML3RRElements.h
===================================================================
--- openbts/trunk/GSM/GSML3RRElements.h 2008-11-29 06:27:41 UTC (rev 10088)
+++ openbts/trunk/GSM/GSML3RRElements.h 2008-11-29 22:46:56 UTC (rev 10089)
@@ -100,7 +100,7 @@
unsigned mCELL_RESELECT_HYSTERESIS;
unsigned mMS_TXPWR_MAX_CCH;
unsigned mACS;
- unsigned mNECI;
+ static const unsigned mNECI = 0; // new establishment causes not
supported
unsigned mRXLEV_ACCESS_MIN;
public:
@@ -112,7 +112,6 @@
mCELL_RESELECT_HYSTERESIS=6; // 8 dB reselect
mMS_TXPWR_MAX_CCH=0; // a high power
level in all bands
mACS=0;
// no additional relesect parameters
- mNECI=0;
// new establishment causes not supported
mRXLEV_ACCESS_MIN=0; // lowest
allowed access level
}
@@ -388,10 +387,18 @@
mARFCN(wARFCN),
mMAIO(0),mHSN(0)
{ }
+
+ /** Blank initializer */
+ L3ChannelDescription()
+ :mTypeAndOffset(TDMA_MISC),
+ mTN(0),mTSC(0),mHFlag(0),mARFCN(0),mMAIO(0),mHSN(0)
+ { }
void writeV( L3Frame &dest, size_t &wp ) const;
+ void parseV(const L3Frame& src, size_t &rp);
+
size_t lengthV() const { return 3; }
void text(std::ostream&) const;
@@ -538,7 +545,11 @@
mMode(wMode)
{}
+ bool operator==(const L3ChannelMode& other) const { return
mMode==other.mMode; }
+ bool operator!=(const L3ChannelMode& other) const { return
mMode!=other.mMode; }
+
void writeV(L3Frame& dest, size_t &wp) const;
+ void parseV(const L3Frame& src, size_t& wp);
size_t lengthV() const { return 1; }
void text(std::ostream&) const;
Modified: openbts/trunk/GSM/GSML3RRMessages.cpp
===================================================================
--- openbts/trunk/GSM/GSML3RRMessages.cpp 2008-11-29 06:27:41 UTC (rev
10088)
+++ openbts/trunk/GSM/GSML3RRMessages.cpp 2008-11-29 22:46:56 UTC (rev
10089)
@@ -121,6 +121,7 @@
case L3RRMessage::AssignmentFailure: return new
L3AssignmentFailure();
case L3RRMessage::RRStatus: return new L3RRStatus();
case L3RRMessage::PagingResponse: return new L3PagingResponse();
+ case L3RRMessage::ChannelModeModifyAcknowledge: return new
L3ChannelModeModifyAcknowledge();
default:
CERR("WARNING -- no L3 RR factory support for " << MTI);
return NULL;
@@ -143,6 +144,23 @@
+/**
+This is a local function to map the GSM::ChannelType enum
+to one of the codes from GMS 04.07 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: abort();
+ }
+}
+
+
+
size_t L3PagingRequestType1::bodyLength() const
{
int sz = mMobileIDs.size();
@@ -154,14 +172,25 @@
}
+
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 for reverse orders of 1/2-octet fields.
+ // Remember to reverse orders of 1/2-octet fields.
// Because GSM transmits LSB-first within each byte.
- dest.writeField(wp,0x0,4); // "any channel", GSM 04.08
Table 10.5.29
- dest.writeField(wp,0x0,4); // "normal paging", GSM 04.08
Table 10.5.63
+ // 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);
}
@@ -172,7 +201,7 @@
L3RRMessage::text(os);
os << " mobileIDs=(";
for (unsigned i=0; i<mMobileIDs.size(); i++) {
- os << "(" << mMobileIDs[i] << "),";
+ os << "(" << mMobileIDs[i] << "," << mChannelsNeeded[i] << "),";
}
os << ")";
}
@@ -500,5 +529,34 @@
+void L3ChannelModeModify::writeBody(L3Frame &dest, size_t& wp) const
+{
+ mDescription.writeV(dest,wp);
+ mMode.writeV(dest,wp);
+}
+
+void L3ChannelModeModify::text(ostream& os) const
+{
+ L3RRMessage::text(os);
+ os << "description=(" << mDescription << ")";
+ os << " mode=(" << mMode << ")";
+}
+
+
+void L3ChannelModeModifyAcknowledge::parseBody(const L3Frame &src, size_t& rp)
+{
+ mDescription.parseV(src,rp);
+ mMode.parseV(src,rp);
+}
+
+
+void L3ChannelModeModifyAcknowledge::text(ostream& os) const
+{
+ L3RRMessage::text(os);
+ os << "description=(" << mDescription << ")";
+ os << " mode=(" << mMode << ")";
+}
+
+
// vim: ts=4 sw=4
Modified: openbts/trunk/GSM/GSML3RRMessages.h
===================================================================
--- openbts/trunk/GSM/GSML3RRMessages.h 2008-11-29 06:27:41 UTC (rev 10088)
+++ openbts/trunk/GSM/GSML3RRMessages.h 2008-11-29 22:46:56 UTC (rev 10089)
@@ -95,12 +95,12 @@
///@name miscellaneous
//@{
ChannelModeModify=0x10,
+ RRStatus=0x12,
+ ChannelModeModifyAcknowledge=0x17,
ClassmarkChange=0x16,
+ MeasurementReport = 0x15,
GPRSSuspensionRequest=0x34,
- RRStatus=0x12,
//@}
- /// reporting
- MeasurementReport = 0x15,
///@name special cases -- assigned >8-bit codes to avoid
conflicts
//@{
SynchronizationChannelInformation=0x100,
@@ -141,6 +141,7 @@
private:
std::vector<L3MobileIdentity> mMobileIDs;
+ ChannelType mChannelsNeeded[2];
public:
@@ -150,19 +151,30 @@
{
// The empty paging request is a single untyped mobile ID.
mMobileIDs.push_back(L3MobileIdentity());
+ mChannelsNeeded[0]=AnyDCCHType;
+ mChannelsNeeded[1]=AnyDCCHType;
}
- L3PagingRequestType1(const L3MobileIdentity& wId)
+ L3PagingRequestType1(const L3MobileIdentity& wId, ChannelType wType)
:L3RRMessage()
- { mMobileIDs.push_back(wId); }
+ {
+ mMobileIDs.push_back(wId);
+ mChannelsNeeded[0]=wType;
+ mChannelsNeeded[1]=AnyDCCHType;
+ }
- L3PagingRequestType1(const L3MobileIdentity& wId1, const
L3MobileIdentity& wId2)
+ L3PagingRequestType1(const L3MobileIdentity& wId1, ChannelType wType1,
+ const L3MobileIdentity& wId2, ChannelType wType2)
:L3RRMessage()
{
mMobileIDs.push_back(wId1);
+ mChannelsNeeded[0]=wType1;
mMobileIDs.push_back(wId2);
+ mChannelsNeeded[1]=wType2;
}
+ unsigned chanCode(ChannelType) const;
+
size_t bodyLength() const;
int MTI() const { return PagingRequestType1; }
@@ -672,7 +684,60 @@
+/** GSM 04.08 9.1.5 */
+class L3ChannelModeModify : public L3RRMessage {
+ private:
+
+ L3ChannelDescription mDescription;
+ L3ChannelMode mMode;
+
+ public:
+
+ L3ChannelModeModify(const L3ChannelDescription& wDescription,
+ const L3ChannelMode& wMode)
+ :L3RRMessage(),
+ mDescription(wDescription),
+ mMode(wMode)
+ {}
+
+ int MTI() const { return (int) ChannelModeModify; }
+
+ size_t bodyLength() const
+ { return mDescription.lengthV() + mMode.lengthV(); }
+
+ void writeBody(L3Frame&, size_t&) const;
+
+ void text(std::ostream&) const;
+};
+
+
+/** GSM 04.08 9.1.6 */
+class L3ChannelModeModifyAcknowledge : public L3RRMessage {
+
+ private:
+
+ L3ChannelDescription mDescription;
+ L3ChannelMode mMode;
+
+ public:
+
+ const L3ChannelDescription& description() const { return mDescription; }
+ const L3ChannelMode& mode() const { return mMode; }
+
+ int MTI() const { return (int) ChannelModeModifyAcknowledge; }
+
+ size_t bodyLength() const
+ { return mDescription.lengthV() + mMode.lengthV(); }
+
+ void parseBody(const L3Frame&, size_t&);
+
+ void text(std::ostream&) const;
+};
+
+
+
+
}; // GSM
Modified: openbts/trunk/SIP/SIPInterface.cpp
===================================================================
--- openbts/trunk/SIP/SIPInterface.cpp 2008-11-29 06:27:41 UTC (rev 10088)
+++ openbts/trunk/SIP/SIPInterface.cpp 2008-11-29 22:46:56 UTC (rev 10089)
@@ -43,9 +43,17 @@
using namespace Control;
+/**
+ The channel type to request in paging.
+ Request SDCCHType for early assignment or
+ TCHFType for very early assignment.
+*/
+const GSM::ChannelType RequiredChannel = GSM::TCHFType;
+//const GSM::ChannelType RequiredChannel = GSM::SDCCHType;
+
// SIPMessageMap method definitions.
void SIPMessageMap::write(const std::string& call_id, osip_message_t * msg)
@@ -193,7 +201,7 @@
if(msg->sip_method == NULL){ return false; }
if( strcmp(msg->sip_method,"INVITE") != 0) {return false;}
- // FIXME -- Check gBTS for TCH and SDCCH availability. Bug #130.
+ // FIXME -- Check gBTS for TCH availability, bug #330.
// Respond with a congestion message if none are available.
// Get call_id from invite message.
@@ -219,18 +227,13 @@
return false;
}
DCOUT("SIPInterface::checkInvite: repeated SIP invite,
repaging")
- gBTS.pager().addID(mobile_id);
+ gBTS.pager().addID(mobile_id,RequiredChannel);
transaction.T3113().set();
gTransactionTable.update(transaction);
osip_free(to_uri);
return false;
}
- // FIXME -- At this point, check for the mobile_id in the transaction
table.
- // Bug #131.
- // If it's there, it could mean the phone's already busy, depending on
the state.
- // Respond with Busy.
-
// Add an entry to the SIP Map.
mSIPMap.add(call_id_string);
@@ -254,7 +257,7 @@
// Add to paging list.
DCOUT("SIPInterface::checkInvite: new SIP invite, initial paging")
- gBTS.pager().addID(mobile_id);
+ gBTS.pager().addID(mobile_id,RequiredChannel);
osip_free(to_uri);
return true;
Modified: openbts/trunk/apps/OpenBTS850.cpp
===================================================================
--- openbts/trunk/apps/OpenBTS850.cpp 2008-11-29 06:27:41 UTC (rev 10088)
+++ openbts/trunk/apps/OpenBTS850.cpp 2008-11-29 22:46:56 UTC (rev 10089)
@@ -116,7 +116,7 @@
SDCCH[i].downstream(radio);
SDCCH[i].open();
gBTS.addSDCCH(&SDCCH[i]);
-
SDCCHControlThread[i].start((void*(*)(void*))Control::SDCCHDispatcher,&SDCCH[i]);
+
SDCCHControlThread[i].start((void*(*)(void*))Control::DCCHDispatcher,&SDCCH[i]);
}
// TCHs
@@ -134,7 +134,7 @@
TCH[i].downstream(radio);
TCH[i].open();
gBTS.addTCH(&TCH[i]);
-
TCHControlThread[i].start((void*(*)(void*))Control::FACCHDispatcher,&TCH[i]);
+
TCHControlThread[i].start((void*(*)(void*))Control::DCCHDispatcher,&TCH[i]);
}
// Set up the pager.
Modified: openbts/trunk/apps/OpenBTS900.cpp
===================================================================
--- openbts/trunk/apps/OpenBTS900.cpp 2008-11-29 06:27:41 UTC (rev 10088)
+++ openbts/trunk/apps/OpenBTS900.cpp 2008-11-29 22:46:56 UTC (rev 10089)
@@ -114,7 +114,7 @@
Thread SDCCHControlThread[4];
for (int i=0; i<4; i++) {
SDCCH[i].downstream(radio);
-
SDCCHControlThread[i].start((void*(*)(void*))Control::SDCCHDispatcher,&SDCCH[i]);
+
SDCCHControlThread[i].start((void*(*)(void*))Control::DCCHDispatcher,&SDCCH[i]);
SDCCH[i].open();
gBTS.addSDCCH(&SDCCH[i]);
}
@@ -132,7 +132,7 @@
Thread TCHControlThread[7];
for (int i=0; i<7; i++) {
TCH[i].downstream(radio);
-
TCHControlThread[i].start((void*(*)(void*))Control::FACCHDispatcher,&TCH[i]);
+
TCHControlThread[i].start((void*(*)(void*))Control::DCCHDispatcher,&TCH[i]);
TCH[i].open();
gBTS.addTCH(&TCH[i]);
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r10089 - in openbts/trunk: Control GSM SIP apps,
dburgess00 <=