networkprotocolmodules/common/suplrrlpasn1/src/suplpos.cpp
branchRCL_3
changeset 65 a796fdeeb33c
parent 0 9cfd9a3ee49c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/networkprotocolmodules/common/suplrrlpasn1/src/suplpos.cpp	Wed Oct 13 16:07:50 2010 +0300
@@ -0,0 +1,532 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+/**
+ @file
+ @internalTechnology
+ 
+*/
+
+#include "RRLP-Messages.h"
+#include "ULP.h"
+
+#include "suplpos.h"
+#include "suplpospayload.h"
+#include "rrlpmeasureposrequest.h"
+#include "rrlpassistancedata.h"
+#include "rrlpprotocolerror.h"
+#include "suplasn1error.h"
+#include "supldevloggermacros.h" 
+
+#include <lbssatellite.h>
+#include <lbs/lbsgpsmeasurement.h>
+
+/** 
+Static factory constructor 
+*/
+EXPORT_C CSuplPos* CSuplPos::NewL(TBool aIsOutgoingMessage)
+	{
+	SUPLLOG(ELogP1, "CSuplPos::NewL() Begin\n");
+	CSuplPos* self = CSuplPos::NewLC(aIsOutgoingMessage);
+	SUPLLOG(ELogP1, "CSuplPos::NewL() End\n");
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+EXPORT_C CSuplPos* CSuplPos::NewLC(TBool aIsOutgoingMessage)
+	{
+	SUPLLOG(ELogP1, "CSuplPos::NewLC() Begin\n");
+	CSuplPos* self = new (ELeave) CSuplPos(aIsOutgoingMessage);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	SUPLLOG(ELogP1, "CSuplPos::NewLC() End\n");
+	return self;
+	}
+
+
+/** 
+Constructor 
+*/
+CSuplPos::CSuplPos(TBool aIsOutgoingMessage)
+ : CSuplMessageBase::CSuplMessageBase(ESuplPos, aIsOutgoingMessage)
+	{
+	}
+
+
+/** 
+Second stage constructor 
+*/
+void CSuplPos::ConstructL()
+	{
+	// call the base class ConstructL() to create common data structures
+	CSuplMessageBase::ConstructL();
+
+	// message specific structures for outgoing messages.
+	if (iIsOutgoingMessage)
+		{
+		// local reference to context object
+		OSCTXT* pctxt = iControl->getCtxtPtr();
+
+		// create the SUPL POS specific data structures
+		iData->message.t =  T_UlpMessage_msSUPLPOS;
+		iData->message.u.msSUPLPOS = (ASN1T_SUPLPOS*)rtxMemAllocZ(pctxt, sizeof(ASN1T_SUPLPOS));
+   		LeaveIfAllocErrorL();
+		
+		iData->message.u.msSUPLPOS->m.velocityPresent = 0;
+		
+		iData->message.u.msSUPLPOS->posPayLoad.t = T_PosPayLoad_rrlpPayload;
+		iData->message.u.msSUPLPOS->posPayLoad.u.rrlpPayload = (ASN1T_PosPayLoad_rrlpPayload*)rtxMemAllocZ(pctxt, sizeof(ASN1T_PosPayLoad_rrlpPayload));
+   		LeaveIfAllocErrorL();
+		}
+	}
+
+
+/** 
+Destructor 
+*/
+CSuplPos::~CSuplPos()
+	{
+	SUPLLOG(ELogP1, "CSuplPos::~CSuplPos() Begin\n");
+	delete iPosPayload;
+	delete iDecodeBuffer;
+	delete iPayloadData;
+	delete iPayloadPdu;
+	SUPLLOG(ELogP1, "CSuplPos::~CSuplPos() End\n");
+	}
+
+	
+/** 
+SetVelocity()
+
+Set the velocity parameter. The parameter TPositionInfoBase must contain
+course information (eg be TPositionCourseInfo or derived) for the velocity
+parameter to be set.
+
+@param  aPosInfo: contains current velocity estimate
+@return KErrNone normally
+		KErrNotFound if no TCourse information present
+		KErrNoMemory if failed to allocate memory to store the outgoing data
+*/
+EXPORT_C TInt CSuplPos::SetVelocity(const TPositionInfoBase& aPosInfo)
+	{
+	SUPLLOG(ELogP1, "CSuplPos::SetVelocity() Begin\n");
+	__ASSERT_DEBUG(iIsOutgoingMessage, User::Invariant());
+	__ASSERT_DEBUG(iData->message.u.msSUPLPOS != NULL, User::Invariant());
+
+		// handle velocity (TCourse) information
+	if ((aPosInfo.PositionClassType() & EPositionCourseInfoClass) != 0)
+		{
+		TPositionCourseInfo courseInfo = reinterpret_cast <const TPositionCourseInfo&> (aPosInfo);
+		TCourse course;
+		courseInfo.GetCourse(course);
+		
+		// populate the velocity parameter
+		iData->message.u.msSUPLPOS->m.velocityPresent = 1;
+		TInt velErr = PopulateVelocity(course, iData->message.u.msSUPLPOS->velocity);
+		if (velErr != KErrNone)
+			{
+			SUPLLOG(ELogP1, "CSuplPos::SetVelocity() End (error populating velocity)\n");
+			return velErr;
+			}
+		}
+	else
+		{
+		// passed parameter does not contain course information.
+		SUPLLOG(ELogP1, "CSuplPos::SetVelocity() End (Course Information Not Present)\n");
+		return KErrNotFound;
+		}
+		
+	SUPLLOG(ELogP1, "CSuplPos::SetVelocity() End\n");
+	return KErrNone;
+	}
+
+
+/**
+VelocityPresent()
+
+@return ETrue if the optional velocity parameter is present
+*/
+EXPORT_C TBool CSuplPos::VelocityPresent()
+	{
+	SUPLLOG(ELogP1, "CSuplPos::VelocityPresent() Begin\n");
+	__ASSERT_DEBUG(!iIsOutgoingMessage, User::Invariant());
+	__ASSERT_DEBUG(iData->message.u.msSUPLPOS != NULL, User::Invariant());
+	
+	if (iData->message.u.msSUPLPOS->m.velocityPresent != 0)
+		{
+		SUPLLOG(ELogP1, "CSuplPos::VelocityPresent(ETrue) End\n");
+		return ETrue;
+		}
+
+	SUPLLOG(ELogP1, "CSuplPos::VelocityPresent(EFalse) End\n");
+	return EFalse;
+	}
+
+	
+/** 
+Velocity()
+
+Populates aPosInfo according to the velocity parameter 
+The parameter TPositionInfoBase must be able to store course information 
+(eg be TPositionCourseInfo or derived) for the velocity parameter to be set.
+
+Note that the LBS course API currently does not support vertical velocity, 
+so vertical speed information is ignored.
+
+@param  aPosInfo: on return, populated with velocity information.
+@return KErrNotFound if the velocity is not available in the received message
+		KErrNotSupported if the TPositionInfoBase can not hold course information.
+		KErrArgument if the received data is not in the expected format.
+		KErrNone otherwise
+*/
+EXPORT_C TInt CSuplPos::GetVelocity(TPositionInfoBase& aPosInfo)
+	{
+	SUPLLOG(ELogP1, "CSuplPos::Velocity() Begin\n");
+	__ASSERT_DEBUG(!iIsOutgoingMessage, User::Invariant());
+	__ASSERT_DEBUG(iData->message.u.msSUPLPOS != NULL, User::Invariant());
+
+	// check the velocity was present in the received message
+	if (iData->message.u.msSUPLPOS->m.velocityPresent == 0)
+		{
+		return KErrNotFound;
+		}
+	
+	// check the TPositionInfoBase can receive course information.
+	if ((aPosInfo.PositionClassType() & EPositionCourseInfoClass) == 0)
+		{
+		__ASSERT_DEBUG(0, User::Invariant());
+		return KErrNotSupported;
+		}
+		
+	// source velocity reference
+	ASN1T_Velocity& velocity = iData->message.u.msSUPLPOS->velocity;
+
+	// target course reference
+	TCourse course;
+	
+	// set the course information according to the received velocity type
+	switch (velocity.t)
+		{
+		case T_Velocity_horvel:
+			{
+			TUint bearing = 0;
+			bearing = velocity.u.horvel->bearing.data[0] << 1;
+			bearing |= velocity.u.horvel->bearing.data[1] >> 7;
+			
+			TUint speed = 0;
+			speed = velocity.u.horvel->horspeed.data[0] << 8;
+			speed |= velocity.u.horvel->horspeed.data[1];
+			
+			course.SetHeading((TReal32)bearing);
+			course.SetSpeed(ConvertHorSpeedToMetersPerSecond(speed));
+			break;
+			}
+		case T_Velocity_horandvervel:
+			{
+			TUint bearing = 0;
+			bearing = velocity.u.horandvervel->bearing.data[0] << 1;
+			bearing |= velocity.u.horandvervel->bearing.data[1] >> 7;
+			
+			TUint speed = 0;
+			speed = velocity.u.horandvervel->horspeed.data[0] << 8;
+			speed |= velocity.u.horandvervel->horspeed.data[1];
+			
+			course.SetHeading((TReal32)bearing);
+			course.SetSpeed(ConvertHorSpeedToMetersPerSecond(speed));
+			break;
+			}
+		case T_Velocity_horveluncert:
+			{
+			TUint bearing = 0;
+			bearing = velocity.u.horveluncert->bearing.data[0] << 1;
+			bearing |= velocity.u.horveluncert->bearing.data[1] >> 7;
+			
+			TUint speed = 0;
+			speed = velocity.u.horveluncert->horspeed.data[0] << 8;
+			speed |= velocity.u.horveluncert->horspeed.data[1];
+			
+			TUint speedAccuracy = velocity.u.horveluncert->uncertspeed.data[0];
+			
+			course.SetHeading((TReal32)bearing);
+			course.SetSpeed(ConvertHorSpeedToMetersPerSecond(speed));
+			course.SetSpeedAccuracy(ConvertHorSpeedAccuracyToMetersPerSecond(speedAccuracy));
+			break;
+			}
+		case T_Velocity_horandveruncert:
+			{
+			TUint bearing = 0;
+			bearing = velocity.u.horandveruncert->bearing.data[0] << 1;
+			bearing |= velocity.u.horandveruncert->bearing.data[1] >> 7;
+			
+			TUint speed = 0;
+			speed = velocity.u.horandveruncert->horspeed.data[0] << 8;
+			speed |= velocity.u.horandveruncert->horspeed.data[1];
+			
+			TUint speedAccuracy = velocity.u.horandveruncert->horuncertspeed.data[0];
+			
+			course.SetHeading((TReal32)bearing);
+			course.SetSpeed(ConvertHorSpeedToMetersPerSecond(speed));
+			course.SetSpeedAccuracy(ConvertHorSpeedAccuracyToMetersPerSecond(speedAccuracy));
+			break;
+			}
+		default:
+			{
+			__ASSERT_DEBUG(0, User::Invariant());
+			return KErrArgument;
+			}
+		}
+
+	// set the course information in the return parameter.
+	TPositionCourseInfo posInfo = reinterpret_cast <const TPositionCourseInfo&> (aPosInfo);
+	posInfo.SetCourse(course);
+	
+	SUPLLOG(ELogP1, "CSuplPos::Velocity() End\n");
+	return KErrNone;
+	}
+	
+
+/** 
+SetPosPayload()
+
+Assigns the payload RRLP message for outgoing messages. 
+CSuplPos instance takes immediate ownership of the CSuplPosPayload object.
+
+@param
+*/
+EXPORT_C void CSuplPos::SetPosPayload(CSuplPosPayload* aPayload)
+	{
+	SUPLLOG(ELogP1, "CSuplPos::SetPosPayload() Begin\n");
+	__ASSERT_DEBUG(iIsOutgoingMessage, User::Invariant());
+	__ASSERT_DEBUG(iPosPayload == NULL, User::Invariant());
+	iPosPayload = aPayload;	
+	SUPLLOG(ELogP1, "CSuplPos::SetPosPayload() End\n");
+	}
+	
+	
+/**
+DecodePosPayloadL()
+
+Decodes the content of received positioning payload. Must be called before content
+of the payload may be accessed
+
+@param aError, on return indicates if an error was encountered, 
+               eg KErrNotSupported for unsupported payload types.
+*/
+void CSuplPos::DecodePosPayloadL(TInt& aError)
+	{
+	SUPLLOG(ELogP1, "CSuplPos::DecodePosPayloadL() Begin\n");
+	__ASSERT_DEBUG(!iIsOutgoingMessage, User::Invariant());
+	__ASSERT_DEBUG(iPosPayload == NULL, User::Invariant());
+	__ASSERT_DEBUG(iData->message.u.msSUPLPOS != NULL, User::Invariant());
+	
+	// check that the payload is RRLP
+	if (iData->message.u.msSUPLPOS->posPayLoad.t != T_PosPayLoad_rrlpPayload)
+		{
+		aError = ESuplAsn1ErrUnsupportedPosProtocol;
+		return;
+		}
+	
+	// extract the RRLP payload and decode and compare...
+	TInt payloadLength  = iData->message.u.msSUPLPOS->posPayLoad.u.rrlpPayload->numocts;
+	OSOCTET* payloadptr = &iData->message.u.msSUPLPOS->posPayLoad.u.rrlpPayload->data[0];
+
+	// Create the payload decode buffer
+	ASN1Context* payloadContext = new (ELeave) ASN1Context;
+	CleanupDeletePushL(payloadContext);
+	iDecodeBuffer = new (ELeave) ASN1PERDecodeBuffer (payloadptr, payloadLength, FALSE, payloadContext);
+	// construction of iDecodeBuffer successful, pop payloadContext off the cleanup stack
+	CleanupStack::Pop(payloadContext);
+
+	// Create data and control objects to manage the decode
+	iPayloadData  = new (ELeave) ASN1T_PDU();
+	iPayloadPdu   = new (ELeave) ASN1C_PDU (*iDecodeBuffer, *iPayloadData);
+	
+	TInt stat = iPayloadPdu->Decode();
+
+	// return now if error encountered while decoding
+	if (stat != KErrNone)
+		{
+		aError = ProcessAsn1Error(stat);
+		return;
+		}
+
+	// build payload content wrapper.
+	switch (iPayloadData->component.t)
+		{
+		case T_RRLP_Component_msrPositionReq:
+			{
+			iPosPayload = CRrlpMeasurePositionRequest::NewL();
+			break;
+			}
+			
+		case T_RRLP_Component_assistanceData:
+			{
+			iPosPayload = CRrlpAssistanceData::NewL();
+			break;
+			}
+
+		case T_RRLP_Component_protocolError:
+			{
+			iPosPayload = CRrlpProtocolError::NewL(EFalse);
+			break;
+			}
+
+		case T_RRLP_Component_msrPositionRsp:
+ 		case T_RRLP_Component_assistanceDataAck:
+		default:
+			{
+			// unsupported message type
+			aError = ESuplAsn1ErrUnsupportedPosMessageType;
+			return;
+			}
+		}
+	
+	// pass ownership of the decoded message content.
+	CRrlpMessageBase* rrlpMessage = (CRrlpMessageBase*)iPosPayload;
+	rrlpMessage->SetDecodedData(iPayloadData, iPayloadPdu);
+	iPayloadData = NULL;
+	iPayloadPdu  = NULL;
+
+	// no longer need the decode buffer object.
+	delete iDecodeBuffer;
+	iDecodeBuffer = NULL;
+	SUPLLOG(ELogP1, "CSuplPos::DecodePosPayloadL() End\n");
+	}
+	
+
+/** 
+PosPayload()
+
+Returns the decoded positioning payload for received SUPL POS messages.
+Note that ownership of the position payload is returned - the calling entity 
+becomes responsible for the destruction of the positioning payload.
+
+@return pointer to the positioning payload.
+*/
+EXPORT_C CSuplPosPayload* CSuplPos::PosPayload()
+	{
+	SUPLLOG(ELogP1, "CSuplPos::PosPayload() Begin\n");
+	__ASSERT_DEBUG(!iIsOutgoingMessage, User::Invariant());
+	__ASSERT_DEBUG(iPosPayload != NULL, User::Invariant());
+	__ASSERT_DEBUG(iData->message.u.msSUPLPOS != NULL, User::Invariant());
+	
+	CSuplPosPayload* posPayload = iPosPayload;
+	iPosPayload = NULL;
+
+	SUPLLOG(ELogP1, "CSuplPos::PosPayload() End\n");
+
+	return posPayload;
+	}
+
+	
+/** 
+EncodePosPayloadL()
+
+Encodes the positioning payload.
+
+@return error indication, KErrNone otherwise
+*/
+TInt CSuplPos::EncodePosPayloadL()
+	{
+	SUPLLOG(ELogP1, "CSuplPos::EncodePosPayloadL() Begin\n");
+	__ASSERT_DEBUG(iIsOutgoingMessage, User::Invariant());
+	__ASSERT_DEBUG(iPosPayload!=NULL, User::Invariant());
+
+	// encode the positioning payload. 
+	// Payload is encoded directly to the supl payload container.
+	TPtr8 payloadPtr(iData->message.u.msSUPLPOS->posPayLoad.u.rrlpPayload->data, 8192);
+	TInt err = iPosPayload->EncodeToL(payloadPtr);
+	if (err!=KErrNone)
+		{
+		SUPLLOG(ELogP1, "CSuplPos::EncodePosPayloadL() Error\n");
+		return ProcessAsn1Error(err);
+		}
+	
+	// set the SUPL payload length to the encoded payload.
+	iData->message.u.msSUPLPOS->posPayLoad.u.rrlpPayload->numocts = payloadPtr.Length();
+	
+	SUPLLOG(ELogP1, "CSuplPos::EncodePosPayloadL() End\n");
+	return KErrNone;
+	}
+
+/** 
+ConvertHorSpeedToMetersPerSecond()
+
+Converts received speed value N to meters per second, according to
+3GPP GAD:
+
+for N = 0 					N <= h < N+0.5
+for 0 < N < 2^16-1			N-0.5 <= h < N+0.5
+for N=2^16-1				N-0.5 <= h
+
+where h = speed in km/hour
+
+@param  aSpeed - the received, encoded speed N.
+@return the uncertainty speed in meters per second.
+*/
+TReal32 CSuplPos::ConvertHorSpeedToMetersPerSecond(TUint aSpeed)
+	{
+	SUPLLOG(ELogP1, "CSuplPos::ConvertHorSpeedToMetersPerSecond() Begin\n");
+	TReal32 kph;
+	if (aSpeed == 0)
+		{
+		kph = 0;
+		}
+	else if (aSpeed < 65536)
+		{
+		kph = aSpeed - 0.5;
+		}
+	else
+		{
+		kph = 65535 - 0.5;
+		}
+	
+	TReal32 metersPerSec = kph / 3.6;
+	SUPLLOG(ELogP1, "CSuplPos::ConvertHorSpeedToMetersPerSecond() End\n");
+	return metersPerSec;
+	}
+
+/** 
+ConvertHorSpeedAccuracyToMetersPerSecond()
+
+Converts received speed uncertainty value N to meters per second, according to
+3GPP GAD:
+
+Uncertainty is encoded in increments of 1 kilometer per hour using an 8bit
+encoded number N. N is therefore the uncertainty speed in kmph, except for 
+N=255 which indicates that the uncertainty is not specified
+
+@param  aSpeedAccuracy - the received, encoded uncertainty speed N.
+@return the uncertainty speed in meters per second.
+*/
+TReal32 CSuplPos::ConvertHorSpeedAccuracyToMetersPerSecond(TUint aSpeedAccuracy)
+	{
+	SUPLLOG(ELogP1, "CSuplPos::ConvertHorSpeedAccuracyToMetersPerSecond() Begin\n");
+	TReal32 metersPerSec = aSpeedAccuracy / 3.6;
+	SUPLLOG(ELogP1, "CSuplPos::ConvertHorSpeedAccuracyToMetersPerSecond() End\n");
+	return metersPerSec;
+	}
+
+/** 
+Prints the content payload data structure to the logger 
+*/
+void CSuplPos::LogPayload()
+	{
+	if (iPosPayload)
+		{
+		iPosPayload->LogMessageContent();
+		}
+	}
+