--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothappprofiles/avrcp/avrcpipc/src/ipc.cpp Mon Jan 18 20:28:57 2010 +0200
@@ -0,0 +1,1541 @@
+// Copyright (c) 2007-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
+ @released
+*/
+
+#include <e32debug.h>
+#include <remconmediaerror.h>
+#include "avrcpipcutils.h"
+#include "avrcpinternalinterface.h"
+#include "mediabrowse.h"
+#include "mediainformation.h"
+#include "nowplaying.h"
+#include "playerinformation.h"
+
+/*
+ * These methods are intended to provide structured IPC communication between
+ * the AVRCP bearer, and the client API DLLs. They are intended to be 'simple'
+ * classes, in which the basic operation are as follows:
+ *
+ * reading: call ReadL(request) and pull information out of member variables
+ * writing: put information into member variables, then call WriteL(request)
+ *
+ * The ReadL() and WriteL() methods effectively just serialize the information
+ * already stored in the member varables. However, they serialize in Big-Endian
+ * format, so that after calling WriteL() and then sending the response back to
+ * the AVRCP bearer via IPC, the bearer can just append the response straight
+ * into an AVC frame; no bit-twiddling is necessary.
+ *
+ * Therefore it is important that these classes _ALWAYS_ write in Big-Endian
+ * format, and write out responses that conform to the AVRCP specification for
+ * PDUs listed in sections 5.1 - 5.4 of the AVRCP 1.3 specification. The ReadL()
+ * operation is the inverse of the WriteL() operation and reads an AVRCP request
+ * in the format listed in the AVRCP specification.
+ *
+ * There's also a Size() method, which will return the size of the response
+ * before WriteL() is called. This is required particularly for responses with
+ * text strings so that the correct-sized buffer can be allocated, as these
+ * could be very large responses (theoretically up to 16 megabytes!) sent via
+ * IPC (just once) and then kept and fragmented in the AVRCP bearer. The Close()
+ * method frees up any memory allocated with these classes.
+ */
+
+
+// --------------------------------------------------------------------------------
+// Used for constructing PDU 0x30 responses
+
+EXPORT_C void RRemConPlayerInformationGetPlayStatusResponse::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+ iTrackLength = Read32L();
+ iPlayPos = Read32L();
+ iStatus = (MPlayerEventsObserver::TPlaybackStatus) Read8L();
+ iReadStream.Close();
+ }
+
+EXPORT_C void RRemConPlayerInformationGetPlayStatusResponse::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ Write32L(KErrNone); // Successful operation
+ Write32L(iTrackLength);
+ Write32L(iPlayPos);
+ Write8L(iStatus);
+ iStream.CommitL();
+ }
+
+// --------------------------------------------------------------------------------
+// Used for constructing PDU 0xff requests
+
+EXPORT_C void RRemConPlayerInformationGetPlayStatusUpdateRequest::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+ iStatus = (MPlayerEventsObserver::TPlaybackStatus) Read8L();
+ iReadStream.Close();
+ }
+
+EXPORT_C void RRemConPlayerInformationGetPlayStatusUpdateRequest::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ Write8L(iStatus);
+ iStream.CommitL();
+ }
+
+// --------------------------------------------------------------------------------
+// Used for constructing PDU 0xff responses
+
+EXPORT_C void RRemConPlayerInformationGetPlayStatusUpdateResponse::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+ iStatus = (MPlayerEventsObserver::TPlaybackStatus) Read8L();
+ iReadStream.Close();
+ }
+
+EXPORT_C void RRemConPlayerInformationGetPlayStatusUpdateResponse::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ Write32L(KErrNone); // Successful operation
+ Write8L(iStatus);
+ iStream.CommitL();
+ }
+// --------------------------------------------------------------------------------
+// Used for constructing PDU 0x15 and PDU 0x16 responses
+
+EXPORT_C void RRemConGetPlayerApplicationTextResponse::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+ iNumberAttributes = Read8L();
+ for (TInt i = 0; i < iNumberAttributes; i++ )
+ {
+ RSettingWithCharset setting;
+ CleanupClosePushL(setting);
+ setting.iAttributeId = Read8L();
+ setting.iCharset = Read16L();
+ setting.iStringLen = Read8L();
+ setting.iString = HBufC8::NewL(setting.iStringLen);
+ TPtr8 ptr = setting.iString->Des();
+ iReadStream.ReadL(ptr);
+ iAttributes.AppendL(setting);
+ CleanupStack::Pop(&setting);
+ }
+
+ }
+
+EXPORT_C void RRemConGetPlayerApplicationTextResponse::WriteL(TDes8& aOutData)
+ {
+ // The caller should have called Size() to pre-allocate enough buffer space
+ __ASSERT_DEBUG(aOutData.MaxLength() >= Size(), AvrcpIpcUtils::Panic(EAvrcpIpcCommandDataTooLong));
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ Write32L(KErrNone); // Successful operation
+ Write8L(iNumberAttributes);
+ for (TInt i = 0; i < iNumberAttributes; i++ )
+ {
+ Write8L(iAttributes[i].iAttributeId);
+ Write16L(iAttributes[i].iCharset);
+ Write8L(iAttributes[i].iStringLen);
+ iStream.WriteL(iAttributes[i].iString->Des());
+ }
+ iStream.CommitL();
+ }
+
+EXPORT_C TInt RRemConGetPlayerApplicationTextResponse::Size()
+ {
+ // Return the size that a buffer needs to be allocated to
+ // serialise the data encapsulated within this data structure.
+
+ TInt size = 5; // 5 bytes: status code + number attributes
+ for (TInt i = 0; i < iNumberAttributes; i++)
+ {
+ size += 4; // 4 bytes: attribute id + charset + stringlen
+ size += iAttributes[i].iString->Length();
+ }
+ return size;
+ }
+
+EXPORT_C void RRemConGetPlayerApplicationTextResponse::Close()
+ {
+ for (TInt i = 0; i < iAttributes.Count(); i++)
+ {
+ iAttributes[i].Close();
+ }
+ iAttributes.Close();
+ RAvrcpIPC::Close();
+ }
+
+// --------------------------------------------------------------------------------
+// Used for constructing PDU 0x10 responses
+
+EXPORT_C void RRemConGetCapabilitiesResponse::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+ iCapabilityId = Read8L();
+ if ( iCapabilityId != ECapabilityIdCompanyID
+ && iCapabilityId != ECapabilityIdEventsSupported)
+ {
+ iReadStream.Close();
+ User::Leave(KErrNotSupported);
+ }
+
+ iCapabilityCount = Read8L();
+ for (TInt i = 0; i < iCapabilityCount; i++ )
+ {
+ if (iCapabilityId == ECapabilityIdCompanyID)
+ {
+ iCapabilities.AppendL(Read24L()); // Read 3 bytes
+ }
+ else
+ {
+ iCapabilities.AppendL(Read8L()); // Read 1 byte
+ }
+ }
+ iReadStream.Close();
+ }
+
+EXPORT_C void RRemConGetCapabilitiesResponse::WriteL(TDes8& aOutData)
+ {
+ if ( iCapabilityId != ECapabilityIdCompanyID
+ && iCapabilityId != ECapabilityIdEventsSupported)
+ {
+ User::Leave(KErrNotSupported);
+ }
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ Write32L(KErrNone); // Successful operation
+ Write8L(iCapabilityId);
+ Write8L(iCapabilityCount);
+ for (TInt i = 0; i < iCapabilityCount; i++ )
+ {
+ if (iCapabilityId == ECapabilityIdCompanyID)
+ {
+ Write24L(iCapabilities[i]); // Write 3 bytes
+ }
+ else
+ {
+ Write8L(iCapabilities[i]); // Write 1 byte
+ }
+ }
+ iStream.CommitL();
+ }
+
+// --------------------------------------------------------------------------------
+// Used for constructing and parsing PDU 0x13 (response) and PDU 0x14 (request)
+
+EXPORT_C void RRemConPlayerAttributeIdsAndValues::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+ iNumberAttributes = Read8L();
+ for (TInt i = 0; i < iNumberAttributes; i++ )
+ {
+ TInt attributeId = Read8L();
+ TInt attributeValue = Read8L();
+ iAttributeId.AppendL(attributeId);
+ iAttributeValue.AppendL(attributeValue);
+ }
+ iReadStream.Close();
+ }
+
+EXPORT_C void RRemConPlayerAttributeIdsAndValues::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ Write32L(KErrNone); // Successful operation
+ Write8L(iNumberAttributes);
+ for (TInt i = 0; i < iNumberAttributes; i++ )
+ {
+ Write8L(iAttributeId[i]);
+ Write8L(iAttributeValue[i]);
+ }
+ iStream.CommitL();
+ }
+
+// --------------------------------------------------------------------------------
+// Used for constructing PDU 0x11 and PDU 0x12 responses
+
+EXPORT_C void RRemConPlayerListOfAttributes::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+ iNumberAttributes = Read8L();
+ for (TInt i = 0; i < iNumberAttributes; i++ )
+ {
+ TInt attribute = Read8L();
+ iAttributes.AppendL(attribute);
+ }
+ iReadStream.Close();
+ }
+
+EXPORT_C void RRemConPlayerListOfAttributes::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ iAttributes.Sort();
+ Write32L(KErrNone); // Successful operation
+ Write8L(iNumberAttributes);
+ for (TInt i = 0; i < iNumberAttributes; i++ )
+ {
+ Write8L(iAttributes[i]);
+ }
+ iStream.CommitL();
+ }
+
+// --------------------------------------------------------------------------------
+// Used for parsing PDU 0x20 requests
+
+EXPORT_C void RRemConGetElementAttributesRequest::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+ iElement = Read64L();
+ iNumberAttributes = Read8L();
+
+ for (TInt i = 0; i < iNumberAttributes; i++ )
+ {
+ TInt attribute = Read32L();
+ iAttributes.AppendL(attribute);
+ }
+ iReadStream.Close();
+ }
+
+EXPORT_C void RRemConGetElementAttributesRequest::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ iAttributes.Sort();
+ Write32L(KErrNone); // Successful operation
+
+ // 64 bits of data
+ Write64L(iElement);
+ Write8L(iNumberAttributes);
+
+ for (TInt i = 0; i < iNumberAttributes; i++ )
+ {
+ Write32L(iAttributes[i]);
+ }
+ iStream.CommitL();
+ }
+
+// --------------------------------------------------------------------------------
+// Used for PDU 0x20 responses
+
+EXPORT_C void RRemConGetElementAttributesResponse::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+ iNumberAttributes = Read8L();
+
+ for (TInt i = 0; i < iNumberAttributes; i++ )
+ {
+ REAResponse eattr;
+ CleanupClosePushL(eattr);
+ eattr.iAttributeId = Read32L();
+ eattr.iCharset = Read16L();
+ eattr.iStringLen = Read16L();
+ eattr.iString = HBufC8::NewL(eattr.iStringLen);
+ TPtr8 ptr = eattr.iString->Des();
+ iReadStream.ReadL(ptr);
+ iAttributes.AppendL(eattr);
+ CleanupStack::Pop(&eattr);
+ }
+
+ }
+
+EXPORT_C void RRemConGetElementAttributesResponse::WriteL(TDes8& aOutData)
+ {
+ __ASSERT_DEBUG(aOutData.MaxLength() >= Size(), AvrcpIpcUtils::Panic(EAvrcpIpcCommandDataTooLong));
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ Write32L(KErrNone); // Successful operation
+
+ Write8L(iNumberAttributes);
+
+ for (TInt i = 0; i < iNumberAttributes; i++ )
+ {
+ Write32L(iAttributes[i].iAttributeId);
+ Write16L(iAttributes[i].iCharset);
+ Write16L(iAttributes[i].iStringLen);
+ iStream.WriteL(iAttributes[i].iString->Des());
+ }
+ iStream.CommitL();
+ }
+
+EXPORT_C TInt RRemConGetElementAttributesResponse::Size()
+ {
+ // Return the size that a buffer needs to be allocated to
+ // serialise the data encapsulated within this data structure.
+
+ TInt size = 5; // 5 bytes: status code + number attributes
+ for (TInt i = 0; i < iNumberAttributes; i++)
+ {
+ size += 4+2+2; // 8 bytes: attrId (4 bytes) + charset (2 bytes) + stringlen (2 bytes)
+ size += iAttributes[i].iString->Length();
+ }
+ return size;
+ }
+
+EXPORT_C void RRemConGetElementAttributesResponse::Close()
+ {
+ for (TInt i = 0; i < iAttributes.Count(); i++)
+ {
+ iAttributes[i].Close();
+ }
+ iAttributes.Close();
+ RAvrcpIPC::Close();
+ }
+
+// --------------------------------------------------------------------------------
+
+EXPORT_C void RRemConPlayerInformation8BitResponse::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+ iValue = Read8L();
+ iReadStream.Close();
+ }
+
+EXPORT_C void RRemConPlayerInformation8BitResponse::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ Write32L(KErrNone); // Successful operation
+
+ Write8L(iValue);
+ iStream.CommitL();
+ }
+
+// --------------------------------------------------------------------------------
+
+EXPORT_C void RRemConPlayerInformation32BitResponse::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+ iValue = Read32L();
+ iReadStream.Close();
+ }
+
+EXPORT_C void RRemConPlayerInformation32BitResponse::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ Write32L(KErrNone); // Successful operation
+
+ Write32L(iValue);
+ iStream.CommitL();
+ }
+
+// --------------------------------------------------------------------------------
+
+EXPORT_C void RRemConPlayerInformation64BitResponse::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+ iValue = Read64L();
+ iReadStream.Close();
+ }
+
+EXPORT_C void RRemConPlayerInformation64BitResponse::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ Write32L(KErrNone); // Successful operation
+
+ Write64L(iValue);
+ iStream.CommitL();
+ }
+
+// --------------------------------------------------------------------------------
+
+EXPORT_C void RSettingWithCharset::Close()
+ {
+ delete iString;
+ iString = NULL;
+ }
+
+EXPORT_C void REAResponse::Close()
+ {
+ delete iString;
+ iString = NULL;
+ }
+
+EXPORT_C void RRemConGetCapabilitiesResponse::Close()
+ {
+ iCapabilities.Close();
+ }
+
+EXPORT_C void RRemConPlayerListOfAttributes::Close()
+ {
+ iAttributes.Close();
+ }
+
+EXPORT_C void RRemConGetElementAttributesRequest::Close()
+ {
+ iAttributes.Close();
+ }
+
+EXPORT_C void RRemConPlayerAttributeIdsAndValues::Close()
+ {
+ iAttributeId.Close();
+ iAttributeValue.Close();
+ }
+
+EXPORT_C void RItem::Close()
+ {
+ delete iName;
+ for(TInt i = 0; i<iAttributes.Count(); i++)
+ {
+ iAttributes[i].Close();
+ }
+ }
+
+EXPORT_C TInt RItem::Size()
+ {
+ // Base size:
+ // type + length field + length
+ return 3 + iLength;
+ }
+
+EXPORT_C void RMediaPlayerItem::Close()
+ {
+ iName.Close();
+ }
+
+EXPORT_C TInt RMediaPlayerItem::Size()
+ {
+ // Base size:
+ // type + length field + length
+ return 3 + iLength;
+ }
+
+/**
+Parses PDU 0x74 and 0x90 requests.
+*/
+EXPORT_C void RRemConNowPlayingRequest::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+ iScope = static_cast<TRemConFolderScope>(Read8L());
+ iElement = Read64L();
+ iUidCounter = Read16L();
+ }
+
+/**
+Constructs PDU 0x74 and 0x90 requests.
+*/
+EXPORT_C void RRemConNowPlayingRequest::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ Write32L(KErrNone); // Successful operation
+ Write8L(iScope);
+ Write64L(iElement);
+ Write16L(iUidCounter);
+ iStream.CommitL();
+ }
+
+/**
+Parses PDU 0x74 and 0x90 responses
+*/
+EXPORT_C void RRemConNowPlayingResponse::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+ iStatus = Read8L();
+ }
+
+/**
+Constructs PDU 0x74 and 0x90 responses.
+*/
+EXPORT_C void RRemConNowPlayingResponse::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ if ((KErrAvrcpAirBase - KErrAvrcpAirSuccess) == iStatus)
+ {
+ Write32L(KErrNone); // Successful operation
+ Write8L(iStatus);
+ }
+ else
+ {
+ Write32L(KErrAvrcpAirBase - iStatus);
+ }
+ iStream.CommitL();
+ }
+
+// --------------------------------------------------------------------------------
+// Used for parsing PDU 0x71 requests
+EXPORT_C void RRemConGetFolderItemsRequest::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+
+ iScope = Read8L();
+ iStartItem = Read32L();
+ iEndItem = Read32L();
+ iNumberAttributes = Read8L();
+
+ if (iNumberAttributes == 0)
+ {
+ // spec says this is a request for all attribs
+ // current spec has 7 specified (0x01 to 0x07)
+ for (TInt i = 1; i <= KMaxMediaAttributeValue; i++)
+ {
+ iAttributes.AppendL(i);
+ }
+ }
+ else if (iNumberAttributes == 0xff)
+ {
+ // No attributes requested
+ }
+ else
+ {
+ for (TInt i = 0; i < iNumberAttributes; i++ )
+ {
+ TInt attribute = Read32L();
+ if (attribute > 0 && attribute <= KMaxMediaAttributeValue )
+ {
+ iAttributes.AppendL(attribute);
+ }
+ }
+ }
+
+ iReadStream.Close();
+ }
+
+EXPORT_C void RRemConGetFolderItemsRequest::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ iAttributes.Sort();
+ Write32L(KErrNone); // Successful operation
+
+ Write8L(iScope);
+ Write32L(iStartItem);
+ Write32L(iEndItem);
+ Write8L(iNumberAttributes);
+
+ for (TInt i = 0; i < iNumberAttributes; i++ )
+ {
+ Write32L(iAttributes[i]);
+ }
+
+ iStream.CommitL();
+ }
+
+EXPORT_C void RRemConGetFolderItemsRequest::Close()
+ {
+ iAttributes.Close();
+ }
+
+EXPORT_C TInt RRemConGetFolderItemsRequest::CopyAttributes(RArray<TMediaAttributeId>& aOutAttributes)
+ {
+ TInt result = KErrNone;
+ TMediaAttributeId attributeId;
+ TInt attributeCount = iAttributes.Count();
+ for (TInt i = 0; i < attributeCount; i++)
+ {
+ attributeId = static_cast<TMediaAttributeId>(iAttributes[i]);
+ result = aOutAttributes.Append(attributeId);
+ if (result != KErrNone)
+ {
+ break;
+ }
+ }
+ return result;
+ }
+// --------------------------------------------------------------------------------
+// Used for PDU 0x71 responses
+
+EXPORT_C void RRemConGetFolderItemsResponse::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+
+ iPduId = Read8L();
+ iParamLength = Read16L();
+ iStatus = Read8L();
+ iUidCounter = Read16L();
+ iNumberItems = Read16L();
+
+ for(TInt i = 0; i < iNumberItems; i++)
+ {
+ ReadItemL();
+ }
+
+ iReadStream.Close();
+ }
+
+void RRemConGetFolderItemsResponse::ReadItemL()
+ {
+ RItem item;
+ CleanupClosePushL(item);
+
+ item.iType = static_cast<AvrcpBrowsing::TItemType>(Read8L());
+ item.iLength = Read16L();
+ item.iUid = Read64L();
+
+ if(item.iType == AvrcpBrowsing::EFolderItem)
+ {
+ item.iFolderType = static_cast<AvrcpBrowsing::TFolderType>(Read8L());
+ item.iPlayable = Read8L();
+ }
+ else
+ {
+ item.iMediaType = Read8L();
+ }
+
+ item.iCharset = Read16L();
+ item.iNameLength = Read16L();
+ item.iName = HBufC8::NewL(item.iNameLength);
+ TPtr8 ptr = item.iName->Des();
+ iReadStream.ReadL(ptr);
+
+ if(item.iType == AvrcpBrowsing::EMediaElement)
+ {
+ item.iNumberAttributes = Read32L();
+
+ for (TInt i = 0; i < item.iNumberAttributes; i++ )
+ {
+ REAResponse eattr;
+ CleanupClosePushL(eattr);
+
+ eattr.iAttributeId = Read32L();
+ eattr.iCharset = Read16L();
+ eattr.iStringLen = Read16L();
+ eattr.iString = HBufC8::NewL(eattr.iStringLen);
+ TPtr8 ptr = eattr.iString->Des();
+ iReadStream.ReadL(ptr);
+
+ item.iAttributes.AppendL(eattr);
+ CleanupStack::Pop(&eattr);
+ }
+ }
+
+ iItems.AppendL(item);
+ CleanupStack::Pop(&item);
+ }
+
+EXPORT_C void RRemConGetFolderItemsResponse::WriteL(TDes8& aOutData)
+ {
+ __ASSERT_DEBUG(aOutData.MaxLength() >= Size(), AvrcpIpcUtils::Panic(EAvrcpIpcCommandDataTooLong));
+ aOutData.Zero();
+ iStream.Open(aOutData);
+
+ Write8L(iPduId);
+ Write16L(iParamLength);
+ Write8L(iStatus);
+
+ if(iStatus == 0x4)
+ {
+ Write16L(iUidCounter);
+ Write16L(iNumberItems);
+
+ for (TInt i = 0; i < iNumberItems; i++ )
+ {
+ WriteItemL(i);
+ }
+ }
+
+ iStream.CommitL();
+ }
+
+void RRemConGetFolderItemsResponse::WriteItemL(TInt aIndex)
+ {
+ RItem& item = iItems[aIndex];
+
+ Write8L(item.iType);
+ Write16L(item.iLength);
+ Write64L(item.iUid);
+
+ if(item.iType == AvrcpBrowsing::EFolderItem)
+ {
+ Write8L(item.iFolderType);
+ Write8L(item.iPlayable);
+ }
+ else
+ {
+ Write8L(item.iMediaType);
+ }
+
+ Write16L(item.iCharset);
+ Write16L(item.iNameLength);
+ iStream.WriteL(item.iName->Des());
+
+ if(item.iType == AvrcpBrowsing::EMediaElement)
+ {
+ Write8L(item.iNumberAttributes);
+
+ for(TInt i = 0; i < item.iNumberAttributes; i++)
+ {
+ Write32L(item.iAttributes[i].iAttributeId);
+ Write16L(item.iAttributes[i].iCharset);
+ Write16L(item.iAttributes[i].iStringLen);
+ iStream.WriteL(item.iAttributes[i].iString->Des());
+ }
+ }
+ }
+
+EXPORT_C TInt RRemConGetFolderItemsResponse::Size()
+ {
+ // Return the size that a buffer needs to be allocated to
+ // serialise the data encapsulated within this data structure.
+
+ // base size
+ // pduid + paramlength + status + uidcount + number items
+ TInt size = KGetFolderItemsResponseBaseSize;
+
+ for (TInt i = 0; i < iNumberItems; i++)
+ {
+ size += iItems[i].Size();
+ }
+ return size;
+ }
+
+EXPORT_C void RRemConGetFolderItemsResponse::Close()
+ {
+ for (TInt i = 0; i < iItems.Count(); i++)
+ {
+ iItems[i].Close();
+ }
+ iItems.Reset();
+ }
+
+EXPORT_C TInt RRemConGetFolderItemsResponse::CopyItems(
+ const TArray<TRemConItem>& aItems)
+ {
+ TInt err = KErrNone;
+ for(TInt i = 0; i < aItems.Count(); i++)
+ {
+ RItem item;
+ item.iName = NULL;
+ item.iUid = aItems[i].iUid;
+ item.iType = static_cast<AvrcpBrowsing::TItemType>(aItems[i].iType);
+
+ err = iItems.Append(item);
+ if(err)
+ {
+ break;
+ }
+ }
+ return err;
+ }
+
+EXPORT_C TBool RRemConGetFolderItemsResponse::RequestNextItem(TInt& aError,
+ RBuf8& aOutBuf, TUint16 aCookie)
+ {
+ aError = KErrNone;
+ // Work out if we have as many items as fit
+ TBool getMoreItems = ETrue;
+ iCurrentListingSize += (iCurrentItem + 1) ? iItems[iCurrentItem].Size() : 0;
+ if(iCurrentListingSize > iMaxResponse)
+ {
+ // We can't fit this item in the listing
+ iItems[iCurrentItem].Close();
+ getMoreItems = EFalse;
+ iItems.Remove(iCurrentItem);
+ }
+
+ if(getMoreItems && ++iCurrentItem < iItems.Count())
+ {
+ return ETrue;
+ }
+ else
+ {
+ // We have all items, send the response
+ iNumberItems = iCurrentItem;
+ if(aOutBuf.Create(Size()) != KErrNone)
+ {
+ aError = KErrGeneral;
+ return EFalse;
+ }
+
+ iPduId = AvrcpBrowsing::EGetFolderItems;
+ iStatus = KErrAvrcpAirBase - KErrAvrcpAirSuccess;//0x4
+ iUidCounter = aCookie;
+ TRAP(aError, WriteL(aOutBuf));
+ }
+ return EFalse;
+ }
+// --------------------------------------------------------------------------------
+// Used for parsing PDU 0x72 requests
+
+EXPORT_C void RRemConChangePathRequest::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+
+ iUidCounter = Read16L();
+ iDirection = Read8L();
+
+ if(iDirection == AvrcpBrowsing::KDown)
+ {
+ iElement = Read64L();
+ }
+
+ iReadStream.Close();
+ }
+
+EXPORT_C void RRemConChangePathRequest::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+
+ Write16L(iUidCounter);
+ Write8L(iDirection);
+ Write64L(iElement);
+
+ iStream.CommitL();
+ }
+
+// --------------------------------------------------------------------------------
+// Used for PDU 0x72 responses
+
+EXPORT_C void RRemConChangePathResponse::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+
+ iStatus = Read8L();
+ iNumberItems = Read32L();
+
+ iReadStream.Close();
+ }
+
+EXPORT_C void RRemConChangePathResponse::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+
+ Write8L(iPduId);
+ Write16L(iParamLength);
+ Write8L(iStatus);
+
+ if(iStatus == 0x4)
+ {
+ Write32L(iNumberItems);
+ }
+
+ iStream.CommitL();
+ }
+
+// --------------------------------------------------------------------------------
+// Used for parsing PDU 0x73 requests
+
+EXPORT_C void RRemConGetItemAttributesRequest::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+
+ iScope = Read8L();
+ iElement = Read64L();
+ iUidCounter = Read16L();
+ iNumberAttributes = Read8L();
+
+ for (TInt i = 0; i < iNumberAttributes; i++ )
+ {
+ TInt attribute = Read32L();
+ iAttributes.AppendL(attribute);
+ }
+
+ iReadStream.Close();
+ }
+
+EXPORT_C void RRemConGetItemAttributesRequest::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ iAttributes.Sort();
+ Write32L(KErrNone); // Successful operation
+
+ Write8L(iScope);
+ // 64 bits of data
+ Write64L(iElement);
+ Write16L(iUidCounter);
+ Write8L(iNumberAttributes);
+
+ for (TInt i = 0; i < iNumberAttributes; i++ )
+ {
+ Write32L(iAttributes[i]);
+ }
+ iStream.CommitL();
+ }
+
+EXPORT_C void RRemConGetItemAttributesRequest::Close()
+ {
+ iAttributes.Close();
+ }
+
+// --------------------------------------------------------------------------------
+// Used for PDU 0x73 responses
+
+EXPORT_C void RRemConGetItemAttributesResponse::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+
+ iStatus = Read8L();
+ iNumberAttributes = Read8L();
+
+ for (TInt i = 0; i < iNumberAttributes; i++ )
+ {
+ REAResponse eattr;
+ eattr.iAttributeId = Read32L();
+ eattr.iCharset = Read16L();
+ eattr.iStringLen = Read16L();
+ eattr.iString = HBufC8::NewL(eattr.iStringLen);
+ TPtr8 ptr = eattr.iString->Des();
+ iReadStream.ReadL(ptr);
+ iAttributes.AppendL(eattr);
+ }
+ iReadStream.Close();
+ }
+
+EXPORT_C void RRemConGetItemAttributesResponse::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+
+ Write8L(iPduId);
+ Write16L(iParamLength);
+ Write8L(iStatus);
+
+ if(iStatus == 0x4)
+ {
+ Write8L(iNumberAttributes);
+
+ for (TInt i = 0; i < iNumberAttributes; i++ )
+ {
+ Write32L(iAttributes[i].iAttributeId);
+ Write16L(iAttributes[i].iCharset);
+ Write16L(iAttributes[i].iStringLen);
+ iStream.WriteL(iAttributes[i].iString->Des());
+ }
+ }
+ iStream.CommitL();
+ }
+
+EXPORT_C TInt RRemConGetItemAttributesResponse::Size()
+ {
+ // Return the size that a buffer needs to be allocated to
+ // serialise the data encapsulated within this data structure.
+
+ TInt size = 9; // 6 bytes: error + pduid + paramlength + status code + number attributes
+ for (TInt i = 0; i < iAttributes.Count(); i++)
+ {
+ size += 4+2+2; // 8 bytes: attrId (4 bytes) + charset (2 bytes) + stringlen (2 bytes)
+ size += iAttributes[i].iString->Length();
+ }
+ return size;
+ }
+
+EXPORT_C void RRemConGetItemAttributesResponse::Close()
+ {
+ for (TInt i = 0; i < iAttributes.Count(); i++)
+ {
+ iAttributes[i].Close();
+ }
+ iAttributes.Close();
+ }
+
+// --------------------------------------------------------------------------------
+// Used for parsing PDU 0x80 requests
+
+EXPORT_C void RRemConSearchRequest::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+
+ iCharset = Read16L();
+ iStringLen = Read16L();
+
+ TInt dataLength = aData.Length();
+ TPtrC8 pString = aData.Right(dataLength - 2*sizeof(TUint16));
+ if (pString.Length() != iStringLen)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ RBuf8 searchBuf;
+ searchBuf.CreateL(iStringLen);
+ CleanupClosePushL(searchBuf);
+
+ iReadStream.ReadL(searchBuf);
+
+ CleanupStack::Pop(&searchBuf);
+ iSearchString.Assign(searchBuf);
+
+ iReadStream.Close();
+ }
+
+EXPORT_C void RRemConSearchRequest::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+
+ Write16L(iCharset);
+ Write16L(iStringLen);
+ WriteL(iSearchString);
+
+ iStream.CommitL();
+ }
+
+EXPORT_C TInt RRemConSearchRequest::Size()
+ {
+ // Return the size that a buffer needs to be allocated to
+ // serialise the data encapsulated within this data structure.
+ TInt size = sizeof(iCharset) + sizeof(iStringLen) + iSearchString.Length();
+
+ return size;
+ }
+
+EXPORT_C void RRemConSearchRequest::Close()
+ {
+ iSearchString.Close();
+ }
+
+// --------------------------------------------------------------------------------
+// Used for PDU 0x80 responses
+
+EXPORT_C void RRemConSearchResponse::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+
+ iStatus = Read8L();
+ iUidCounter = Read16L();
+ iNumberItems = Read32L();
+
+ iReadStream.Close();
+ }
+
+EXPORT_C void RRemConSearchResponse::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+
+ Write8L(iPduId);
+ Write16L(iParamLength);
+ Write8L(iStatus);
+
+ if(iStatus == 0x4)
+ {
+ Write16L(iUidCounter);
+ Write32L(iNumberItems);
+ }
+
+ iStream.CommitL();
+ }
+
+// --------------------------------------------------------------------------------
+// Used for parsing SetBrowsedPlayer requests
+
+EXPORT_C void RRemConSetBrowsedPlayerRequest::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+
+ // iMaxResponse is little endian
+ iMaxResponse = iReadStream.ReadInt32L();
+ iPlayerId = Read16L();
+
+ iReadStream.Close();
+ }
+
+EXPORT_C void RRemConSetBrowsedPlayerRequest::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+
+ // Use little endian on iMaxResponse
+ iStream.WriteInt32L(iMaxResponse);
+ Write16L(iPlayerId);
+
+ iStream.CommitL();
+ }
+
+// --------------------------------------------------------------------------------
+// Used for SetBrowsedPlayer responses
+
+EXPORT_C void RRemConGetPathResponse::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+
+ iStatus = Read8L();
+ iUidCounter = Read16L();
+ iNumberItems = Read32L();
+
+ iReadStream.Close();
+ }
+
+EXPORT_C void RRemConGetPathResponse::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+
+ Write8L(iPduId);
+ Write16L(iParamLength);
+ Write8L(iStatus);
+
+ if(iStatus != 0x4)
+ {
+ iStream.CommitL();
+ return;
+ }
+
+ // The depth is equal to the number of items in the array.
+ iFolderDepth = iPath.Count();
+ Write16L(iUidCounter);
+ Write32L(iNumberItems);
+ Write16L(KUtf8MibEnum);
+ Write8L(iFolderDepth);
+
+ for(TInt i = 0; i < iFolderDepth; i++)
+ {
+ Write16L((iPath[i])->Length());
+ iStream.WriteL(*(iPath[i]));
+ }
+
+ iStream.CommitL();
+ }
+
+EXPORT_C TInt RRemConGetPathResponse::Size()
+ {
+ // Return the size that a buffer needs to be allocated to
+ // serialise the data encapsulated within this data structure.
+ iFolderDepth = iPath.Count();
+ TInt size = 13 + (iFolderDepth*2);
+
+ for(TInt i = 0; i < iFolderDepth; i++)
+ {
+ size += (iPath[i])->Length();
+ }
+
+ return size;
+ }
+
+EXPORT_C void RRemConGetPathResponse::Close()
+ {
+ iPath.ResetAndDestroy();
+ }
+
+// --------------------------------------------------------------------------------
+// Used for parsing SetAddressedPlayer requests
+
+EXPORT_C void RAvrcpSetAddressedPlayerRequest::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+
+ iPlayerId = Read16L();
+
+ iReadStream.Close();
+ }
+
+EXPORT_C void RAvrcpSetAddressedPlayerRequest::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+
+ Write16L(iPlayerId);
+
+ iStream.CommitL();
+ }
+
+// --------------------------------------------------------------------------------
+// Used for SetAddressedPlayer responses
+
+EXPORT_C void RAvrcpSetAddressedPlayerResponse::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+
+ iStatus = Read8L();
+
+ iReadStream.Close();
+ }
+
+EXPORT_C void RAvrcpSetAddressedPlayerResponse::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+
+ Write32L(KErrNone); // Successful operation
+ Write8L(iStatus);
+
+ iStream.CommitL();
+ }
+
+// --------------------------------------------------------------------------------
+// Used for parsing PDU 0x71 requests with media player list scope
+
+EXPORT_C void RAvrcpGetFolderItemsRequest::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+
+ iScope = Read8L();
+ iStartItem = Read32L();
+ iEndItem = Read32L();
+ }
+
+EXPORT_C void RAvrcpGetFolderItemsRequest::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ Write32L(KErrNone); // Successful operation
+
+ Write8L(iScope);
+ Write32L(iStartItem);
+ Write32L(iEndItem);
+
+ iStream.CommitL();
+ }
+
+EXPORT_C void RAvrcpGetFolderItemsRequest::Close()
+ {
+ RAvrcpIPC::Close();
+ }
+
+// --------------------------------------------------------------------------------
+// Used for PDU 0x71 responses with media player list scope
+
+EXPORT_C void RAvrcpGetFolderItemsResponse::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+
+ iPduId = Read8L();
+ iParamLength = Read16L();
+ iStatus = Read8L();
+ iUidCounter = Read16L();
+ iNumberItems = Read16L();
+
+ for(TInt i = 0; i < iNumberItems; i++)
+ {
+ ReadItemL();
+ }
+
+ iReadStream.Close();
+ }
+
+void RAvrcpGetFolderItemsResponse::ReadItemL()
+ {
+ RMediaPlayerItem item;
+ CleanupClosePushL(item);
+
+ item.iType = static_cast<AvrcpBrowsing::TItemType>(Read8L());
+ item.iLength = Read16L();
+ item.iPlayerId = Read16L();
+
+ item.iPlayerType = Read8L();
+ item.iPlayerSubType = Read32L();
+ item.iPlayStatus = Read8L();
+ iReadStream.ReadL(item.iFeatureBitmask);
+
+ item.iCharset = Read16L();
+ item.iNameLength = Read16L();
+
+ item.iName.CreateL(item.iNameLength);
+ iReadStream.ReadL(item.iName);
+
+ iItems.AppendL(item);
+ CleanupStack::Pop(&item);
+ }
+
+EXPORT_C void RAvrcpGetFolderItemsResponse::WriteL(TDes8& aOutData)
+ {
+ __ASSERT_DEBUG(aOutData.MaxLength() >= Size(), AvrcpIpcUtils::Panic(EAvrcpIpcCommandDataTooLong));
+ aOutData.Zero();
+ iStream.Open(aOutData);
+
+ Write8L(iPduId);
+ Write16L(iParamLength);
+ Write8L(iStatus);
+
+ if(iStatus == 0x4)
+ {
+ Write16L(iUidCounter);
+ Write16L(iNumberItems);
+
+ for (TInt i = 0; i < iNumberItems; i++ )
+ {
+ WriteItemL(i);
+ }
+ }
+
+ iStream.CommitL();
+ }
+
+void RAvrcpGetFolderItemsResponse::WriteItemL(TInt aIndex)
+ {
+ RMediaPlayerItem& item = iItems[aIndex];
+
+ Write8L(item.iType);
+ Write16L(item.iLength);
+ Write16L(item.iPlayerId);
+
+ Write8L(item.iPlayerType);
+ Write32L(item.iPlayerSubType);
+ Write8L(item.iPlayStatus);
+ iStream.WriteL(item.iFeatureBitmask);
+
+ Write16L(item.iCharset);
+ Write16L(item.iNameLength);
+ iStream.WriteL(item.iName);
+ }
+
+EXPORT_C TInt RAvrcpGetFolderItemsResponse::Size()
+ {
+ // Return the size that a buffer needs to be allocated to
+ // serialise the data encapsulated within this data structure.
+
+ // base size
+ // pduid + paramlength + status + uidcount + number items
+ TInt size = KGetFolderItemsResponseBaseSize;
+
+ for (TInt i = 0; i < iNumberItems; i++)
+ {
+ size += iItems[i].Size();
+ }
+ return size;
+ }
+
+EXPORT_C void RAvrcpGetFolderItemsResponse::Close()
+ {
+ for (TInt i = 0; i < iNumberItems; i++)
+ {
+ iItems[i].Close();
+ }
+ iItems.Reset();
+ }
+
+// --------------------------------------------------------------------------------
+// Used for PDU 0x30 responses with event addressed player changed
+
+EXPORT_C void RAvrcpAddressedPlayerNotificationResponse::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+ iPlayerId = Read16L();
+ iUidCounter = Read16L();
+ iReadStream.Close();
+ }
+
+EXPORT_C void RAvrcpAddressedPlayerNotificationResponse::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ Write32L(KErrNone); // Successful operation
+
+ Write16L(iPlayerId);
+ Write16L(iUidCounter);
+ iStream.CommitL();
+ }
+
+EXPORT_C void RAvrcpUidCounterNotificationResponse::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+ iUidCounter = Read16L();
+ iReadStream.Close();
+ }
+
+EXPORT_C void RAvrcpUidCounterNotificationResponse::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ Write32L(KErrNone); // Successful operation
+
+ Write16L(iUidCounter);
+ iStream.CommitL();
+ }
+
+EXPORT_C void RRemConMediaErrorResponse::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+ iPduId = Read8L();
+ iLength = Read16L();
+ iStatus = Read8L();
+ iReadStream.Close();
+ }
+
+EXPORT_C void RRemConMediaErrorResponse::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ Write8L(iPduId);
+ Write16L(KErrResponseParameterLength);
+ Write8L(iStatus);
+ iStream.CommitL();
+ }
+
+EXPORT_C TUint8 RAvrcpIPC::SymbianErrToStatus(TInt aErr)
+ {
+ return KErrAvrcpAirBase - SymbianErrorCheck(aErr);
+ }
+
+/**
+Ensure we get a known error.
+*/
+EXPORT_C TInt RAvrcpIPC::SymbianErrorCheck(TInt aError)
+ {
+ TInt error = aError;
+
+ switch (error)
+ {
+ case KErrNone:
+ error = KErrAvrcpAirSuccess;
+ break;
+ case KErrAvrcpAirInvalidCommand:
+ case KErrAvrcpAirInvalidParameter:
+ case KErrAvrcpAirParameterNotFound:
+ case KErrAvrcpAirInternalError:
+ case KErrAvrcpAirSuccess:
+ case KErrAvrcpAirUidChanged:
+ case KErrAvrcpAirReserved:
+ case KErrAvrcpAirInvalidDirection:
+ case KErrAvrcpAirNotADirectory:
+ case KErrAvrcpAirDoesNotExist:
+ case KErrAvrcpAirInvalidScope:
+ case KErrAvrcpAirRangeOutOfBounds:
+ case KErrAvrcpAirUidIsADirectory:
+ case KErrAvrcpAirMediaInUse:
+ case KErrAvrcpAirNowPlayingListFull:
+ case KErrAvrcpAirSearchNotSupported:
+ case KErrAvrcpAirSearchInProgress:
+ case KErrAvrcpAirInvalidPlayerId:
+ case KErrAvrcpAirPlayerNotBrowesable:
+ case KErrAvrcpAirPlayerNotAddressed:
+ case KErrAvrcpAirNoValidSearchResults:
+ case KErrAvrcpAirNoAvailablePlayers:
+ case KErrAvrcpAirAddressedPlayerChanged:
+ case KErrAvrcpInvalidScope:
+ break;
+ default:
+ error = KErrAvrcpAirInternalError;
+ }
+
+ return error;
+ }
+
+EXPORT_C void RRemConUidsChangedRequest::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+ iInitialUidCounter = Read16L();
+ }
+
+EXPORT_C void RRemConUidsChangedRequest::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ Write16L(iInitialUidCounter);
+ iStream.CommitL();
+ }
+
+EXPORT_C void RRemConUidsChangedResponse::ReadL(const TDesC8& aData)
+ {
+ iReadStream.Open(aData);
+ iUidCounter = Read16L();
+ }
+
+EXPORT_C void RRemConUidsChangedResponse::WriteL(TDes8& aOutData)
+ {
+ aOutData.Zero();
+ iStream.Open(aOutData);
+ Write16L(iUidCounter);
+ iStream.CommitL();
+ }