--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothappprofiles/avrcp/avc/avcframe.cpp Mon Jan 18 20:28:57 2010 +0200
@@ -0,0 +1,523 @@
+// Copyright (c) 2004-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
+ @publishedPartner
+ @released
+*/
+
+#include <bluetooth/logger.h>
+#include <avcframe.h>
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_AVRCP_FRAME);
+#endif
+
+#ifdef _DEBUG
+PANICCATEGORY("avctpframe");
+#endif
+
+/** Constructor.
+
+@param aFrameType ECommand if this is a command, EResponse
+ if it's a response.
+@internalComponent
+@released
+*/
+CAVCFrame::CAVCFrame(AVC::TFrameType aFrameType)
+ : iFrameType(aFrameType)
+ {
+ LOG_FUNC
+ }
+
+/** Destructor.
+
+@publishedPartner
+@released
+*/
+EXPORT_C CAVCFrame::~CAVCFrame()
+ {
+ LOG_FUNC
+ iBuffer.Close();
+ }
+
+/** Factory function.
+
+This overload should be called when an AV/C frame is
+to be constructed, that is it is probably an outgoing frame.
+
+@param aFrameType ECommand if this is a command, EResponse
+ if it's a response.
+@param aType The AV/C CType for this frame.
+@param aSubunitType The AV/C subunit type for this frame.
+@param aSubunitId The AV/C subunit id for this frame.
+@return A fully constructed CAVCFrame.
+@leave System wide error code.
+@publishedPartner
+@released
+*/
+EXPORT_C CAVCFrame* CAVCFrame::NewL(AVC::TFrameType aFrameType,
+ AVC::TCType aType,
+ AVC::TSubunitType aSubunitType,
+ AVC::TSubunitID aSubunitID)
+ {
+ CAVCFrame* frame = new(ELeave)CAVCFrame(aFrameType);
+ CleanupStack::PushL(frame);
+ frame->ConstructL(aType, aSubunitType, aSubunitID);
+ CleanupStack::Pop(frame);
+ return frame;
+ }
+
+/** Factory function.
+
+This overload should be used when a data buffer should
+be parsed as an AV/C frame, that is it is probably an
+incoming frame.
+
+@param aBuffer A buffer to be parsed as an AV/C frame.
+@param aFrameType ECommand if this is a command, EResponse
+ if it's a response.
+@return A fully constructed CAVCFrame.
+@leave System wide error code.
+@publishedPartner
+@released
+*/
+EXPORT_C CAVCFrame* CAVCFrame::NewL(const TDesC8& aBuffer, AVC::TFrameType aFrameType)
+ {
+ CAVCFrame* frame = new(ELeave)CAVCFrame(aFrameType);
+ CleanupStack::PushL(frame);
+ frame->ConstructL(aBuffer);
+ CleanupStack::Pop(frame);
+ return frame;
+ }
+
+/** Second phase construction.
+
+This overload is used when an AV/C frame is
+to be constructed, that is it is probably an outgoing frame.
+
+@param aType The AV/C CType for this frame.
+@param aSubunitType The AV/C subunit type for this frame.
+@param aSubunitId The AV/C subunit id for this frame.
+@return A fully constructed CAVCFrame.
+@leave System wide error code.
+@internalComponent
+@released
+*/
+void CAVCFrame::ConstructL(AVC::TCType aType, AVC::TSubunitType aSubunitType, AVC::TSubunitID aSubunitID)
+ {
+ iBuffer.CreateL(KAVCFrameMaxLength);
+ iBuffer.Zero();
+ iBuffer.Append(TChar(aType));
+
+ TInt subType = aSubunitType;
+ TInt subID = aSubunitID;
+
+ if (subType > AVC::ETypeExtended2)
+ {
+ iSubunitTypeExtensionBytes = 1;
+ iBuffer.Append(TChar(AVC::ETypeExtended1 << 3));
+ subType -= 0x100;
+
+ while (subType > 0x100)
+ {
+ iBuffer.Append(TChar(AVC::ETypeExtended2));
+ subType -= 0x100;
+ }
+
+ iBuffer.Append(TChar(subType));
+ }
+ else
+ {
+ iBuffer.Append(TChar(subType << 3));
+ }
+
+ if (subID > AVC::EIDExtended2)
+ {
+ iSubunitIDExtensionBytes = 1;
+ iBuffer[1] |= AVC::EIDExtended1;
+ subID -= 0x100;
+
+ while (subID > 0x100)
+ {
+ iBuffer.Append(TChar(AVC::EIDExtended2));
+ subID -= 0x100;
+ }
+
+ iBuffer.Append(TChar(subID));
+ }
+ else
+ {
+ iBuffer[1] |= subID;
+ }
+ }
+
+/** Second phase construction.
+
+This overload is used when a data buffer should
+be parsed as an AV/C frame, that is it is probably an
+incoming frame.
+
+For details of parsing refer to the AV/C digital
+interface command set specification.
+
+@param aBuffer A buffer to be parsed as an AV/C frame.
+@return A fully constructed CAVCFrame.
+@leave System wide error code.
+@publishedPartner
+@released
+*/
+void CAVCFrame::ConstructL(const TDesC8& aBuffer)
+ {
+ iBuffer.CreateL(aBuffer);
+ FindExtensionL(iBuffer, iSubunitTypeExtensionBytes, iSubunitIDExtensionBytes);
+ }
+
+/** Gets the AV/C frame type.
+
+@return ECommand if this is a command, EResponse if this
+ is a response.
+@publishedPartner
+@released
+*/
+EXPORT_C AVC::TFrameType CAVCFrame::FrameType() const
+ {
+ return iFrameType;
+ }
+
+/** Gets the AV/C frame type.
+
+@param aFrame The frame to get the frame type for.
+@return ECommand if this is a command, EResponse if this
+ is a response.
+@publishedPartner
+@released
+*/
+EXPORT_C AVC::TFrameType CAVCFrame::FrameType(const TDesC8& aFrame)
+ {
+ AVC::TFrameType frameType = AVC::ECommand;
+
+ if( aFrame[0] > KAVCCommandMaxRangeLength )
+ {
+ frameType = AVC::EResponse;
+ }
+ return frameType;
+ }
+
+/** Set the AV/C frame type for this frame.
+
+@param The frame type to set.
+@publishedPartner
+@released
+*/
+EXPORT_C void CAVCFrame::SetFrameType(AVC::TFrameType aFrameType)
+ {
+ iFrameType = aFrameType;
+ }
+
+/** Get the AV/C CType for this frame.
+
+@return The AV/C CType for this frame.
+@publishedPartner
+@released
+*/
+EXPORT_C AVC::TCType CAVCFrame::Type() const
+ {
+ return static_cast<AVC::TCType>(iBuffer[0]);
+ }
+
+/** Set the AV/C CType for this frame.
+
+@param aType The AV/C CType to set.
+@publishedPartner
+@released
+*/
+EXPORT_C void CAVCFrame::SetType(AVC::TCType aType)
+ {
+ iBuffer[0] = aType;
+ }
+
+/** Get the AV/C subunit type for this frame.
+
+@return The AV/C subunit type for this frame.
+@publishedPartner
+@released
+*/
+EXPORT_C AVC::TSubunitType CAVCFrame::SubunitType() const
+ {
+ if (iSubunitTypeExtensionBytes == 0)
+ {
+ return static_cast<AVC::TSubunitType>((iBuffer[1] & KAVCSubunitTypeMask) >> 3);
+ }
+
+ return static_cast<AVC::TSubunitType>(iBuffer[1 + iSubunitTypeExtensionBytes] + (iSubunitTypeExtensionBytes * 0x100));
+ }
+
+/** Get the AV/C subunit id for this frame.
+
+@return The AV/C subunit id for this frame.
+@publishedPartner
+@released
+*/
+EXPORT_C AVC::TSubunitID CAVCFrame::SubunitID() const
+ {
+ if (iSubunitIDExtensionBytes == 0)
+ {
+ return static_cast<AVC::TSubunitID>(iBuffer[1] & KAVCSubunitIDMask);
+ }
+
+ return static_cast<AVC::TSubunitID>(iBuffer[1 + iSubunitTypeExtensionBytes + iSubunitIDExtensionBytes] + (iSubunitIDExtensionBytes * 0x100));
+ }
+
+/** Find extension bytes for the frame.
+
+@param aBuffer buffer to be used.
+@return True if its a valid frame.
+@leave System wide error code.
+@internalComponent
+@released
+*/
+/* static */ void CAVCFrame::FindExtensionL(const TDesC8& aBuffer, TInt& aSubunitTypeExtensionBytes, TInt& aSubunitIDExtensionBytes)
+ {
+ TInt minLength = KAVCFrameHeaderLength;
+ if(aBuffer.Length() < minLength)
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ if (static_cast<AVC::TSubunitType>((aBuffer[1] & KAVCSubunitTypeMask) >> 3) == AVC::ETypeExtended1)
+ {
+ aSubunitTypeExtensionBytes++;
+ minLength++;
+
+ while (aBuffer[1 + aSubunitTypeExtensionBytes] == AVC::ETypeExtended2)
+ {
+ if(aBuffer.Length() < minLength)
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ aSubunitTypeExtensionBytes++;
+ minLength++;
+ }
+ }
+
+ if (static_cast<AVC::TSubunitID>(aBuffer[1] & KAVCSubunitIDMask) == AVC::EIDExtended1)
+ {
+ aSubunitIDExtensionBytes++;
+ minLength++;
+
+ while (aBuffer[1 + aSubunitIDExtensionBytes] == AVC::EIDExtended1)
+ {
+ if(aBuffer.Length() < minLength)
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ aSubunitIDExtensionBytes++;
+ minLength++;
+ }
+ }
+
+ //Ensure frame is a valid length i.e. the Opcode() method can be safely called.
+ if(aBuffer.Length() < minLength)
+ {
+ User::Leave(KErrCorrupt);
+ }
+ }
+
+/** Get the AV/C opcode for this frame.
+
+@param aBuffer buffer to search.
+@return The AV/C opcode for this frame.
+@leave System wide error code.
+@internalComponent
+@released
+*/
+/* static */ EXPORT_C AVC::TOpcode CAVCFrame::OpcodeL(const TDesC8& aBuffer)
+ {
+ TInt subunitTypeExtensionBytes=0;
+ TInt subunitIDExtensionBytes=0;
+
+ FindExtensionL(aBuffer, subunitTypeExtensionBytes, subunitIDExtensionBytes);
+ return static_cast<AVC::TOpcode> (aBuffer[KAVCFrameHeaderLength + subunitTypeExtensionBytes + subunitIDExtensionBytes - 1]);
+ }
+
+/** Get the AV/C opcode for this frame.
+
+@return The AV/C opcode for this frame.
+@publishedPartner
+@released
+*/
+EXPORT_C TUint8 CAVCFrame::Opcode() const
+ {
+ return iBuffer[KAVCFrameHeaderLength + iSubunitTypeExtensionBytes + iSubunitIDExtensionBytes - 1];
+ }
+
+/** Get the AV/C OperationId for this frame.
+
+This is only valid for passthrough commands.
+
+@param aOpId On return, the AV/C opcode for this frame.
+@return KErrNotSupported if this is not a passthrough command,
+ KErrCorrupt if this passthrough command does not contain a OpId,
+ KErrNone otherwise.
+@publishedPartner
+@released
+*/
+EXPORT_C TInt CAVCFrame::OperationId(TUint8& aOpId) const
+ {
+ TInt err = KErrNotSupported;
+
+ if(Opcode() == AVC::EPassThrough)
+ {
+ if(DataLength())
+ {
+ aOpId = (iBuffer[iSubunitTypeExtensionBytes + iSubunitIDExtensionBytes + KAVCFrameHeaderLength]) & 0x7f;
+ err = KErrNone;
+ }
+ else
+ {
+ err = KErrCorrupt;
+ }
+ }
+
+ return err;
+ }
+
+/** Get the AV/C button action for this frame.
+
+This is only valid for passthrough commands.
+
+@param aOpId On return, the AV/C button action for this frame.
+@return KErrNotSupported if this is not a passthrough command,
+ KErrCorrupt if this passthrough command does not contain a button action,
+ KErrNone otherwise.
+@publishedPartner
+@released
+*/
+EXPORT_C TInt CAVCFrame::ButtonAct(AVCPanel::TButtonAction& aButtonAction) const
+ {
+ TInt err = KErrNotSupported;
+
+ if(Opcode() == AVC::EPassThrough)
+ {
+ if(DataLength())
+ {
+ aButtonAction = (((iBuffer[iSubunitTypeExtensionBytes + iSubunitIDExtensionBytes + KAVCFrameHeaderLength]) & 0x80) == AVCPanel::EButtonRelease) ? AVCPanel::EButtonRelease : AVCPanel::EButtonPress;
+ err = KErrNone;
+ }
+ else
+ {
+ err = KErrCorrupt;
+ }
+ }
+ return err;
+ }
+
+/** Retrieve data from the AV/C frame.
+
+@param aIndex The offset of the data element within the data segment of the frame
+@return The data element at aIndex.
+@panic If aIndex is outside the frame. DataLength() should be used to check the length of the data segment before using the [] operator.
+@publishedPartner
+@released
+*/
+EXPORT_C const TUint8& CAVCFrame::operator[](TInt aIndex) const
+ {
+ return iBuffer[aIndex + iSubunitTypeExtensionBytes + iSubunitIDExtensionBytes + KAVCFrameHeaderLength];
+ }
+
+/** Retrieve the entire AV/C frame.
+
+@return The AV/C frame.
+@publishedPartner
+@released
+*/
+EXPORT_C const TDesC8& CAVCFrame::Data() const
+ {
+ return iBuffer;
+ }
+
+/** Append data to the AV/C frame.
+
+@param aDes The data to be appended.
+@publishedPartner
+@released
+*/
+EXPORT_C void CAVCFrame::Append(const TDesC8& aDes)
+ {
+ iBuffer.Append(aDes);
+ }
+
+/** Append data to the AV/C frame.
+
+@param aChar The data to be appended.
+@publishedPartner
+@released
+*/
+EXPORT_C void CAVCFrame::Append(TChar aChar)
+ {
+ iBuffer.Append(aChar);
+ }
+
+/** Return the length of the data in the AV/C frame
+
+@return The length of the data in the AV/C frame
+@publishedPartner
+@released
+*/
+EXPORT_C TInt CAVCFrame::DataLength() const
+ {
+ return (iBuffer.Length() - iSubunitTypeExtensionBytes - iSubunitIDExtensionBytes - KAVCFrameHeaderLength);
+ }
+
+EXPORT_C CAVCFrame* CAVCVendorDependentResponse::NewL(TUint aVendorID)
+ {
+ using namespace AVC;
+ CAVCFrame* frame = CAVCFrame::NewL(EResponse,
+ ENotImplemented, //client can override
+ EPanel,
+ EID0);
+ // stupid frames don't know about themselves so we construct in derived classes
+ // first opcode - base class REALLY ought to have opcode setter
+ frame->Append(0); //opcode for VD frame
+ // second vendor
+ frame->Append(aVendorID>>16);
+ frame->Append(aVendorID>>8);
+ frame->Append(aVendorID);
+ return frame;
+ }
+
+EXPORT_C TPtrC8 CAVCVendorDependentCommand::GetPayloadAndVID(const CAVCFrame& aFrame, TUint& aVID)
+ {
+ ASSERT_DEBUG(aFrame.Opcode()==AVC::EVendorDependent); //opcode
+ aVID = (aFrame.operator[](0)<<16) |
+ (aFrame.operator[](1)<<8) |
+ (aFrame.operator[](2));
+
+ return (aFrame.Data().Right(aFrame.DataLength()-KAVCVendorIdLength));
+ }
+
+EXPORT_C TPtrC8 CAVCVendorUniquePassthroughCommand::GetPayloadAndVID(const CAVCFrame& aFrame, TUint& aVID)
+ {
+ ASSERT_DEBUG(aFrame.Opcode()==AVC::EPassThrough); //opcode
+ aVID = (aFrame.operator[](2)<<16) |
+ (aFrame.operator[](3)<<8) |
+ (aFrame.operator[](4));
+
+ return (aFrame.Data().Right(aFrame.DataLength()-KAVCVendorIdLength-2));
+ }