diff -r 87622fad6b51 -r a796fdeeb33c networkprotocolmodules/common/suplrrlpasn1/src/suplpos.cpp --- /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 +#include + +/** +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 (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 (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(); + } + } +