--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaextensions/bluetooth/bluetoothcommons/src.s60/servicerecord.cpp Mon May 03 12:27:20 2010 +0300
@@ -0,0 +1,1651 @@
+/*
+* Copyright (c) 2008 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:
+*
+*/
+
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "fs_methodcall.h"
+#include "javajniutils.h"
+#include "servicerecord.h"
+#include "logger.h"
+#include "javasymbianoslayer.h"
+#include "bluetoothconsts.h"
+#include "applicationinfo.h"
+#include "fileutilities.h"
+#include "javaoslayer.h"
+#include "javacommonutils.h"
+#include "btservicerecordpopulator.h"
+#include "serviceclasshandler.h"
+#include "fileutilities.h"
+#include "exceptionbase.h"
+
+using namespace java::util;
+using namespace java::fileutils;
+
+namespace java
+{
+namespace bluetooth
+{
+
+#define SERVICE_AVAILABLE 0xFF
+#define KGOEP 0x0008 // This is the fixed Id. Should not be modified at any time.
+#define SERVICE_CLASSES_BITS_POS 13
+
+// Permission: Read,Write,Execute for both Owner & Group
+#define BT_DIR_PERM 0777
+
+/**
+ * Returns the new ServiceRecord object.
+ */
+OS_EXPORT ServiceRecord* ServiceRecord::NewL(BluetoothFunctionServer* aServer)
+{
+ JELOG2(EJavaBluetooth);
+ ServiceRecord* servRec = new ServiceRecord(aServer);
+ CleanupStack::PushL(servRec);
+
+ servRec->ConstructL();
+
+ CleanupStack::Pop(servRec);
+
+ return servRec;
+}
+
+OS_EXPORT void ServiceRecord::cleanup(ServiceRecord*& aServer)
+{
+ JELOG2(EJavaBluetooth);
+ if (aServer)
+ {
+ aServer->cleanUp();
+ delete aServer;
+ aServer = NULL;
+ }
+}
+
+void ServiceRecord::ConstructL()
+{
+ JELOG2(EJavaBluetooth);
+
+ mInitializedByPush = false;
+ mRestoredFromPersistentFile = false;
+
+ // Open sdp session
+ User::LeaveIfError(mSdp.Connect());
+
+ // Open sdp database session
+ User::LeaveIfError(mSdpDB.Open(mSdp));
+
+ mRecordState = 0;
+}
+
+ServiceRecord::ServiceRecord(BluetoothFunctionServer* aServer)
+{
+ JELOG2(EJavaBluetooth);
+ mFunctionServer = aServer;
+ mRecord = 0;
+ mSrvRecFd = 0;
+}
+
+ServiceRecord::~ServiceRecord()
+{
+ JELOG2(EJavaBluetooth);
+ mFunctionServer = NULL;
+}
+
+void ServiceRecord::cleanUp()
+{
+ JELOG2(EJavaBluetooth);
+ if (mRecord)
+ {
+ TRAP_IGNORE(mSdpDB.DeleteRecordL(mRecord));
+ mRecord = 0;
+ }
+ mSdpDB.Close();
+ mSdp.Close();
+}
+
+/**
+ * Used in case there is no persistence storage of service record
+ * On success returns 0; otherwise err number.
+ *
+ * Creates and initializes the Service record.
+ * aProtocol: One among the PROTOCOL_L2CAP, PROTOCOL_RFCOMM, PROTOCOL_GOEP
+ * aPSMValue: In case of L2CAP it should be PSM Value;
+ * In case of RFComm it should be channel number.
+ * aUuid: UUID string of the current service
+ * aServiceName: Name of the current service.
+ */
+
+OS_EXPORT int ServiceRecord::initializeRecord(int aProtocol, int aPSMValue,
+ std::wstring aUuid, std::wstring aServiceName)
+{
+ JELOG2(EJavaBluetooth);
+
+ int uuidByteLength = 0;
+ TUint8* uuidBytes = uuidToByteArray(aUuid, uuidByteLength);
+
+ TUUID uuid;
+
+ TPtrC8 uuidDes(uuidBytes, uuidByteLength);
+ TRAPD(err, uuid.SetL(uuidDes));
+
+ delete uuidBytes;
+ uuidBytes = NULL;
+
+ if (KErrNone != err)
+ {
+ LOG2(EJavaBluetooth, EInfo,
+ "- ServiceRecord::initializeRecord Error SetL:%d [UUID:%S]",
+ err, aUuid.c_str());
+ return err;
+ }
+
+ HBufC* nameString = wstringToBuf(aServiceName);
+ TPtrC nameBufPointer(nameString->Des());
+
+ HBufC8* utf8NameBuffer = HBufC8::NewMax(aServiceName.length() + 1);
+ TPtr8 utf8NameBufferPtr(utf8NameBuffer->Des());
+
+ utf8NameBufferPtr.Copy(nameBufPointer);
+
+ TRAP(err, initializeRecordL(aProtocol, aPSMValue, uuid, utf8NameBufferPtr));
+
+ return err;
+}
+
+/**
+ * Used in case of persistence storage of updated service record
+ */
+OS_EXPORT int ServiceRecord::restorePersistentRecord()
+{
+ JELOG2(EJavaBluetooth);
+ int ret = 0;
+
+ CallMethod(ret, this, &ServiceRecord::restorePersistentRecordFs,
+ mFunctionServer);
+ return ret;
+}
+
+int ServiceRecord::restorePersistentRecordFs()
+{
+ JELOG2(EJavaBluetooth);
+
+ // Can set this flag as this function will get called
+ // only in case of push invocation
+ mInitializedByPush = true;
+
+ std::wstring persistentFileName = getPersistentFileName();
+ int persistentRecFd = -1;
+ int ret = 0;
+ int err = 0;
+
+ if (persistentFileName.length() > 0)
+ {
+ try
+ {
+ char *fileName = java::util::JavaCommonUtils::wstringToUtf8(
+ persistentFileName);
+ persistentRecFd = open(fileName, O_RDONLY);
+ delete fileName;
+ }
+ catch (ExceptionBase ex)
+ {
+ ELOG1(
+ EJavaBluetooth,
+ "- ServiceRecord::restorePersistentRecordFs exception Caught: %S",
+ ex.toString().c_str());
+ }
+ }
+
+ if (persistentRecFd < 0)
+ return errno;
+
+ // Reading and restoring the DeviceServiceClasses bits
+ int devServClass = 0;
+ ret = read(persistentRecFd, &devServClass, sizeof(devServClass));
+
+ if (ret <= 0)
+ return errno;
+
+ if (devServClass != 0)
+ {
+ LOG1(EJavaBluetooth, EInfo,
+ " ServiceRecord::restorePersistentRecordFs Setting COD:0x%X",
+ devServClass);
+ ret = ServiceClassHandler::setDeviceServiceClass(devServClass, true);
+ LOG1(EJavaBluetooth, EInfo,
+ " ServiceRecord::restorePersistentRecordFs Set COD Return:%d",
+ ret);
+ }
+
+ // Restoring all other service record data
+ int attrId = 0;
+ while ((ret = read(persistentRecFd, &attrId, sizeof(attrId))) > 0)
+ {
+ int dataType = 0;
+
+ ret = read(persistentRecFd, &dataType, sizeof(dataType));
+ if (ret <= 0)
+ break;
+
+ LOG2(EJavaBluetooth, EInfo, " ServiceRecord reading %X, %X", attrId,
+ dataType);
+
+ switch (dataType)
+ {
+ case DataElement_DATSEQ:
+ case DataElement_DATALT:
+ {
+ err = attributeListStartFs(attrId, dataType, EFalse);
+ break;
+ }
+ case DataElement_EndList:
+ {
+ err = attributeListEndFs(attrId, EFalse);
+ break;
+ }
+ case DataElement_NULL:
+ {
+ err = setAttributeNilFs(attrId, EFalse);
+ break;
+ }
+ case DataElement_BOOL:
+ {
+ TUint8 val = 0;
+ ret = read(persistentRecFd, &val, sizeof(val));
+ if (ret <= 0)
+ break;
+
+ LOG1(EJavaBluetooth, EInfo, " ServiceRecord reading Bool %X", val);
+ err = setAttributeBoolFs(attrId, (val) ? ETrue : EFalse, EFalse);
+ break;
+ }
+ case DataElement_INT_1:
+ case DataElement_INT_2:
+ case DataElement_INT_4:
+ {
+ int len = 0;
+ ret = read(persistentRecFd, &len, sizeof(len));
+ if (ret <= 0)
+ break;
+
+ TUint8 buf[20] = { 0 };
+ ret = read(persistentRecFd, buf, len);
+ if (ret <= 0)
+ break;
+ std::auto_ptr<HBufC8> val(convertIntToDesC(buf, dataType));
+ err = setAttributeIntFs(attrId, dataType, *val, EFalse);
+ break;
+ }
+ case DataElement_INT_8:
+ case DataElement_INT_16:
+ {
+ int len = 0;
+ ret = read(persistentRecFd, &len, sizeof(len));
+ if (ret <= 0)
+ break;
+
+ TUint8 buf[20] = { 0 };
+ ret = read(persistentRecFd, buf, len);
+ if (ret <= 0)
+ break;
+ TPtrC8 val(buf, len);
+ err = setAttributeIntFs(attrId, dataType, val, EFalse);
+ break;
+ }
+ case DataElement_U_INT_1:
+ case DataElement_U_INT_2:
+ case DataElement_U_INT_4:
+ {
+ int len = 0;
+ ret = read(persistentRecFd, &len, sizeof(len));
+ if (ret <= 0)
+ break;
+
+ TUint8 buf[20] = { 0 };
+ ret = read(persistentRecFd, buf, len);
+ if (ret <= 0)
+ break;
+
+ LOG2(EJavaBluetooth, EInfo, " ServiceRecord reading INT8 %X, %S",
+ len, buf);
+
+ std::auto_ptr<HBufC8> val(convertIntToDesC(buf, dataType));
+ err = setAttributeUintFs(attrId, dataType, *val, EFalse);
+ break;
+ }
+ case DataElement_U_INT_8:
+ case DataElement_U_INT_16:
+ {
+ int len = 0;
+ ret = read(persistentRecFd, &len, sizeof(len));
+ if (ret <= 0)
+ break;
+
+ TUint8 buf[20] = { 0 };
+ ret = read(persistentRecFd, buf, len);
+ if (ret <= 0)
+ break;
+
+ LOG2(EJavaBluetooth, EInfo, " ServiceRecord reading INT16 %X, %S",
+ len, buf);
+
+ TPtrC8 val(buf, len);
+ err = setAttributeUintFs(attrId, dataType, val, EFalse);
+ break;
+ }
+ case DataElement_UUID:
+ {
+ int len = 0;
+ ret = read(persistentRecFd, &len, sizeof(len));
+ if (ret <= 0)
+ break;
+
+ TUint8 buf[256] = { 0 };
+ ret = read(persistentRecFd, buf, len);
+ if (ret <= 0)
+ break;
+
+ LOG2(EJavaBluetooth, EInfo, " ServiceRecord reading UUID %X, %S",
+ len, buf);
+
+ TPtrC8 uuidDes(buf, len);
+
+ TUUID val;
+ TRAP(err, val.SetL(uuidDes));
+
+ if (KErrNone == err)
+ {
+ err = setAttributeUUIDFs(attrId, val, EFalse);
+ }
+ break;
+ }
+ case DataElement_STRING:
+ {
+ int len = 0;
+ ret = read(persistentRecFd, &len, sizeof(len));
+ if (ret <= 0)
+ break;
+
+ TUint8 buf[1024] = {0};
+ ret = read(persistentRecFd, buf, len);
+ if (ret <= 0)
+ break;
+
+ LOG1(EJavaBluetooth, EInfo, " ServiceRecord reading STRING %X",
+ len);
+
+ TPtrC8 val(buf, len);
+ err = setAttributeStringFs(attrId, val, EFalse);
+ break;
+ }
+ case DataElement_URL:
+ {
+ int len = 0;
+ ret = read(persistentRecFd, &len, sizeof(len));
+ if (ret <= 0)
+ break;
+
+ TUint8 buf[1024] = {0};
+ ret = read(persistentRecFd, buf, len);
+ if (ret <= 0)
+ break;
+
+ LOG2(EJavaBluetooth, EInfo, " ServiceRecord reading URL %X, %S",
+ len, buf);
+
+ TPtrC8 val(buf, len);
+ err = setAttributeUrlFs(attrId, val, EFalse);
+ break;
+ }
+ default:
+ break;
+ }
+
+ // Treated as EOF reached.
+ if (ret <= 0)
+ break;
+ }
+
+ // Indicates a successful retrieval
+ // of the service record from the persistent file
+ mRestoredFromPersistentFile = true;
+
+ return ret;
+}
+
+/**
+ * Creates and initializes the Service record.
+ * aProtocol: One among the PROTOCOL_L2CAP, PROTOCOL_RFCOMM, PROTOCOL_GOEP
+ * aPSMValue: In case of L2CAP it should be PSM Value;
+ * In case of RFComm it should be channel number.
+ * aServiceUUID: UUID of the current service
+ * aServiceName: Name of the current service.
+ */
+OS_EXPORT void ServiceRecord::initializeRecordL(TInt aProtocol, TInt aPsmValue,
+ TUUID &aServiceUUID, TDesC8 &aServiceName)
+{
+ JELOG2(EJavaBluetooth);
+ CallMethodL(this, &ServiceRecord::initializeRecordFsL, aProtocol,
+ aPsmValue, aServiceUUID, aServiceName, mFunctionServer);
+}
+
+/**
+ * Returns the service record handle.
+ */
+OS_EXPORT int ServiceRecord::getServiceRecordID()
+{
+ return mRecord;
+}
+
+void ServiceRecord::initializeRecordFsL(TInt aProtocol, TInt aPsmValue,
+ TUUID &aServiceUUID, TDesC8 &aServiceName)
+{
+ JELOG2(EJavaBluetooth);
+ // Open sdp session
+ User::LeaveIfError(mSdp.Connect());
+ // Open sdp database session
+ User::LeaveIfError(mSdpDB.Open(mSdp));
+
+ LOG1(
+ EJavaBluetooth,
+ EInfo,
+ " ServiceRecord::initializeRecordFsL: After registering to SDPDB: %S",
+ aServiceUUID.Des().Ptr());
+
+ // Creating proper ServiceClassID list
+ CSdpAttrValueDES *serviceClassIds = CSdpAttrValueDES::NewDESL(NULL);
+ serviceClassIds->BuildUUIDL(aServiceUUID);
+ if (PROTOCOL_RFCOMM == aProtocol)
+ {
+ LOG(EJavaBluetooth, EInfo,
+ " ServiceRecord::initializeRecordFsL: Adding KSerialPortUUID");
+
+ serviceClassIds->BuildUUIDL(TUUID(KSerialPortUUID));
+ }
+
+ // Create a record of the correct service class
+ mSdpDB.CreateServiceRecordL(*serviceClassIds, mRecord);
+
+ // Add a protocol to the record
+ mSdpAttrValueList = CSdpAttrValueDES::NewDESL(NULL);
+ mLastSdpAttr = mSdpAttrValueList;
+ CleanupStack::PushL(mSdpAttrValueList);
+
+ // Getting port number
+ TSdpIntBuf<TUint> portBuf(aPsmValue);
+ LOG1(EJavaBluetooth, EInfo,
+ " ServiceRecord::initializeRecordFsL: port value : %d", aPsmValue);
+
+ LOG(EJavaBluetooth, EInfo,
+ " ServiceRecord::initializeRecordFsL: Creating protocol list");
+
+ // Create protocol list for our service
+
+ switch (aProtocol)
+ {
+ case PROTOCOL_L2CAP:
+ LOG(EJavaBluetooth, EInfo,
+ " ServiceRecord::initializeRecordFsL: PROTOCOL_L2CAP");
+ mLastSdpAttr = mLastSdpAttr -> StartListL();
+ mLastSdpAttr = mLastSdpAttr -> BuildDESL();
+ mLastSdpAttr = mLastSdpAttr -> StartListL();
+ mLastSdpAttr = mLastSdpAttr -> BuildUUIDL(KL2CAP);
+ mLastSdpAttr = mLastSdpAttr -> BuildUintL(portBuf);
+ mLastSdpAttr = mLastSdpAttr -> EndListL();
+ mLastSdpAttr = mLastSdpAttr -> EndListL();
+ break;
+ case PROTOCOL_RFCOMM:
+ LOG(EJavaBluetooth, EInfo,
+ " ServiceRecord::initializeRecordFsL: PROTOCOL_RFCOMM");
+ mLastSdpAttr = mLastSdpAttr -> StartListL();
+ mLastSdpAttr = mLastSdpAttr -> BuildDESL();
+ mLastSdpAttr = mLastSdpAttr -> StartListL();
+ mLastSdpAttr = mLastSdpAttr -> BuildUUIDL(KL2CAP);
+ mLastSdpAttr = mLastSdpAttr -> EndListL();
+ mLastSdpAttr = mLastSdpAttr -> BuildDESL();
+ mLastSdpAttr = mLastSdpAttr -> StartListL();
+ mLastSdpAttr = mLastSdpAttr -> BuildUUIDL(KRFCOMM);
+ mLastSdpAttr = mLastSdpAttr -> BuildUintL(portBuf);
+ mLastSdpAttr = mLastSdpAttr -> EndListL();
+ mLastSdpAttr = mLastSdpAttr -> EndListL();
+ break;
+ case PROTOCOL_GOEP:
+ LOG(EJavaBluetooth, EInfo,
+ " ServiceRecord::initializeRecordFsL: PROTOCOL_GOEP");
+ mLastSdpAttr = mLastSdpAttr -> StartListL();
+ mLastSdpAttr = mLastSdpAttr -> BuildDESL();
+ mLastSdpAttr = mLastSdpAttr -> StartListL();
+ mLastSdpAttr = mLastSdpAttr -> BuildUUIDL(KL2CAP);
+ mLastSdpAttr = mLastSdpAttr -> EndListL();
+ mLastSdpAttr = mLastSdpAttr -> BuildDESL();
+ mLastSdpAttr = mLastSdpAttr -> StartListL();
+ mLastSdpAttr = mLastSdpAttr -> BuildUUIDL(KRFCOMM);
+ mLastSdpAttr = mLastSdpAttr -> BuildUintL(portBuf);
+ mLastSdpAttr = mLastSdpAttr -> EndListL();
+ mLastSdpAttr = mLastSdpAttr -> BuildDESL();
+ mLastSdpAttr = mLastSdpAttr -> StartListL();
+ mLastSdpAttr = mLastSdpAttr -> BuildUUIDL(KGOEP);
+ mLastSdpAttr = mLastSdpAttr -> EndListL();
+ mLastSdpAttr = mLastSdpAttr -> EndListL();
+ break;
+ }
+
+ LOG(EJavaBluetooth, EInfo,
+ " ServiceRecord::initializeRecordFsL: Set protocol list to the record");
+ // Set protocol list to the record
+ mSdpDB.UpdateAttributeL(mRecord, KSdpAttrIdProtocolDescriptorList,
+ *mSdpAttrValueList);
+ CleanupStack::PopAndDestroy(mSdpAttrValueList);
+
+ mSdpAttrValueList = NULL;
+ mLastSdpAttr = NULL;
+
+ LOG(EJavaBluetooth, EInfo,
+ " ServiceRecord::initializeRecordFsL: Update attribute");
+
+ if (aServiceName.Size() > 0)
+ {
+ // Add a name to the record
+ mSdpDB.UpdateAttributeL(mRecord, KSdpAttrIdBasePrimaryLanguage
+ + KSdpAttrIdOffsetServiceName, aServiceName);
+ LOG1(EJavaBluetooth, EInfo,
+ " ServiceRecord::initializeRecordFsL: Update Name: %d",
+ KSdpAttrIdBasePrimaryLanguage + KSdpAttrIdOffsetServiceName);
+ }
+
+ mOrigUuid = uuidToWstring(aServiceUUID);
+
+ LOG1(EJavaBluetooth, EInfo,
+ " ServiceRecord::initializeRecordFsL mOrigUuid = %S",
+ mOrigUuid.c_str());
+
+ mProtocol = aProtocol;
+}
+
+/**
+ * Opens the persistent file. Called when Update Record triggered.
+ * And stores the DeviceServiceClasses bits (32 bit) in the persistent file
+ * While retrieving the service record back from the file, it is must to read first
+ * one integer which depicts this DeviceServiceClasses. If the service classes is not
+ * set for the corresponding service, then the value 0(32 bits) is stored in place of the
+ * DeviceServiceClasses bits.
+ *
+ */
+OS_EXPORT void ServiceRecord::initializeUpdateRecord(int aDeviceServiceClasses)
+{
+ JELOG2(EJavaBluetooth);
+ std::wstring persistentFileName;
+
+ persistentFileName = getPersistentFileName();
+
+ if (persistentFileName.length() > 0)
+ {
+ try
+ {
+ char *fileName = java::util::JavaCommonUtils::wstringToUtf8(
+ persistentFileName);
+ mSrvRecFd = open(fileName, O_CREAT | O_WRONLY | O_TRUNC, 0666);
+
+ if (mSrvRecFd < 0)
+ {
+ ELOG1(
+ EJavaBluetooth,
+ "- ServiceRecord::initializeUpdateRecord Err while file open. %d",
+ errno);
+ return;
+ }
+ // Storing the Current DeviceClass (32 bits)
+ write(mSrvRecFd, (char *) &aDeviceServiceClasses,
+ sizeof(aDeviceServiceClasses));
+
+ delete fileName;
+ }
+ catch (ExceptionBase ex)
+ {
+ ELOG1(
+ EJavaBluetooth,
+ "- ServiceRecord::initializeUpdateRecord exception Caught: %S",
+ ex.toString().c_str());
+ }
+ }
+}
+
+/**
+ * Closes the persistent file.
+ */
+OS_EXPORT void ServiceRecord::completesUpdateRecord()
+{
+ JELOG2(EJavaBluetooth);
+ if (0 != mSrvRecFd)
+ {
+ close(mSrvRecFd);
+ mSrvRecFd = 0;
+ }
+}
+
+/**
+ * Gets the persistent file name. This function returns the file name pattern
+ * srv_rec_<uuid>_<protocol>.txt And also, the srv_rec_XXX.txt
+ * file name will be prepended with midlet's private directory for
+ * bluetooth. That is, the final outcome of this function may be something
+ * like, <midlet_private_dir>/bt/srv_rec_XXX.txt
+ *
+ * @param aUuid
+ * uuid string
+ * @param aProtocol
+ * protocol name
+ * @return Null when connection not registered for push;
+ * otherwise srv_rec_XXX file name
+ */
+std::wstring ServiceRecord::getPersistentFileName()
+{
+ JELOG2(EJavaBluetooth);
+ std::wstring noFileName;
+ std::wstring srvRecFile;
+
+ LOG1(EJavaBluetooth, EInfo, "+ ServiceRecord:getPersistentFileName %d",
+ mProtocol);
+
+ const java::runtime::ApplicationInfo& appInf =
+ java::runtime::ApplicationInfo::getInstance();
+ const std::wstring btFilesPath = appInf.getRootPath() + L"bt\\";
+
+ if (false == FileUtilities::exists(btFilesPath))
+ {
+ try
+ {
+ LOG1(EJavaBluetooth, EInfo,
+ " ServiceRecord:getPersistentFileName mkdir:%S",
+ btFilesPath.c_str());
+
+ char *dirName = JavaCommonUtils::wstringToUtf8(btFilesPath);
+ if (mkdir(dirName, BT_DIR_PERM) < 0)
+ {
+ ELOG1(EJavaBluetooth,
+ "- ServiceRecord:getPersistentFileName Err, mkdir:%d",errno);
+ delete[] dirName;
+ return noFileName;
+ }
+ delete[] dirName;
+ }
+ catch (ExceptionBase ex)
+ {
+ ELOG1(EJavaBluetooth,
+ "- ServiceRecord::getPersistentFileName exception Caught: %S",
+ ex.toString().c_str());
+ return noFileName;
+ }
+ }
+
+ srvRecFile = btFilesPath + L"srv_rec_";
+
+ switch (mProtocol)
+ {
+ case PROTOCOL_L2CAP:
+ srvRecFile += mOrigUuid + L"_btl2cap.txt";
+ break;
+ case PROTOCOL_RFCOMM:
+ srvRecFile += mOrigUuid + L"_btspp.txt";
+ break;
+ case PROTOCOL_GOEP:
+ srvRecFile += mOrigUuid + L"_btgoep.txt";
+ break;
+ }
+
+ LOG1(EJavaBluetooth, EInfo,
+ "- ServiceRecord:getPersistentFileName %S", srvRecFile.c_str());
+ return srvRecFile;
+}
+
+/**
+ * Exporting this function only for the use of ServerConnection::AcceptL
+ * and ServerConnection::HandleAcceptL methods. In rest of the cases,
+ * this method should be called via setAdvertise()
+ */
+OS_EXPORT int ServiceRecord::setAdvertiseFs(TBool aAvailable)
+{
+ LOG1(EJavaBluetooth, EInfo, "+ ServiceRecord::setAdvertise %s",
+ (aAvailable)?"True":"False");
+ int err = 0;
+
+ TInt state = aAvailable ? SERVICE_AVAILABLE : !SERVICE_AVAILABLE;
+
+ // Set availability
+ TRAP(err,
+ {
+ mSdpDB.UpdateAttributeL(mRecord,
+ KSdpAttrIdServiceAvailability, state);
+
+ mSdpDB.UpdateAttributeL(mRecord,
+ KSdpAttrIdServiceRecordState, ++mRecordState);
+ }
+ );
+ return err;
+}
+
+/**
+ * Creates and starts the new list (DEA/DES)
+ * On success returns 0; otherwise err number.
+ */
+OS_EXPORT int ServiceRecord::attributeListStart(int aAttrId, int aAttrType)
+{
+ JELOG2(EJavaBluetooth);
+ int ret = 0;
+ TBool persistentReq = ETrue;
+
+ CallMethod(ret, this, &ServiceRecord::attributeListStartFs,
+ aAttrId, aAttrType, persistentReq, mFunctionServer);
+ return ret;
+}
+
+int ServiceRecord::attributeListStartFs(int aAttrId, int aAttrType, TBool isPersistenceRequired)
+{
+ JELOG2(EJavaBluetooth);
+ LOG1(EJavaBluetooth, EInfo, "+ ServiceRecord::attributeListStart %d", aAttrId);
+
+ TRAPD(err,
+ {
+ if (aAttrId >= 0)
+ {
+ switch (aAttrType)
+ {
+ case DataElement_DATSEQ:
+ mSdpAttrValueList = CSdpAttrValueDES::NewDESL(NULL);
+ break;
+ case DataElement_DATALT:
+ mSdpAttrValueList = CSdpAttrValueDEA::NewDEAL(NULL);
+ break;
+ default:
+ break;
+ }
+ mLastSdpAttr = mSdpAttrValueList;
+ }
+ else
+ {
+ switch (aAttrType)
+ {
+ case DataElement_DATSEQ:
+ if (mLastSdpAttr)
+ mLastSdpAttr = mLastSdpAttr -> BuildDESL();
+ break;
+ case DataElement_DATALT:
+ if (mLastSdpAttr)
+ mLastSdpAttr = mLastSdpAttr -> BuildDESL();
+ break;
+ default:
+ break;
+ }
+ }
+ mLastSdpAttr = mLastSdpAttr -> StartListL();
+ }
+ );
+
+ // Writing into persistent file for further usage
+ if (0 != mSrvRecFd && isPersistenceRequired)
+ {
+ LOG2(EJavaBluetooth, EInfo, " ServiceRecord Writing %d, %d",
+ aAttrId, aAttrType);
+ write(mSrvRecFd, (char *)&aAttrId, sizeof(aAttrId));
+ write(mSrvRecFd, (char *)&aAttrType, sizeof(aAttrType));
+ }
+ return err;
+}
+
+/**
+ * Ends the list (DEA/DES), and update the attribute list of SDP database
+ * On success returns 0; otherwise err number.
+ */
+OS_EXPORT int ServiceRecord::attributeListEnd(int aAttrId)
+{
+ JELOG2(EJavaBluetooth);
+ int ret = 0;
+ TBool persistentReq = ETrue;
+
+ CallMethod(ret, this, &ServiceRecord::attributeListEndFs,
+ aAttrId, persistentReq, mFunctionServer);
+ return ret;
+}
+
+int ServiceRecord::attributeListEndFs(int aAttrId, TBool isPersistenceRequired)
+{
+ JELOG2(EJavaBluetooth);
+ LOG1(EJavaBluetooth, EInfo, "+ ServiceRecord::attributeListEnd %d", aAttrId);
+ int err = 0;
+
+ if (mLastSdpAttr)
+ TRAP(err, mLastSdpAttr = mLastSdpAttr -> EndListL());
+ if (KErrNone == err && aAttrId >= 0)
+ {
+ LOG1(EJavaBluetooth, EInfo, "* ServiceRecord::attributeListEnd %d", aAttrId);
+ TRAP(err, mSdpDB.UpdateAttributeL(mRecord, aAttrId, *mSdpAttrValueList));
+ LOG1(EJavaBluetooth, EInfo, "x ServiceRecord::attributeListEnd %d", aAttrId);
+ delete mSdpAttrValueList;
+ mSdpAttrValueList = NULL;
+ mLastSdpAttr = NULL;
+ }
+
+ // Writing into persistent file for further usage
+ if (0 != mSrvRecFd && isPersistenceRequired)
+ {
+ int type = DataElement_EndList;
+ LOG2(EJavaBluetooth, EInfo, " ServiceRecord Writing %d, %d",
+ aAttrId, type);
+ write(mSrvRecFd, (char *)&aAttrId, sizeof(aAttrId));
+ write(mSrvRecFd, (char *)&type, sizeof(type));
+ }
+ return err;
+}
+
+/**
+ * Adds unsigned integer to the list (DEA/DES),
+ * or update the attribute list of SDP database
+ * On success returns 0; otherwise err number.
+ */
+OS_EXPORT int ServiceRecord::setAttributeUint(int aAttrId, int aAttrType, TDesC8 &aNumVal)
+{
+ JELOG2(EJavaBluetooth);
+ int ret = 0;
+ TBool persistentReq = ETrue;
+
+ CallMethod(ret, this, &ServiceRecord::setAttributeUintFs,
+ aAttrId, aAttrType, aNumVal, persistentReq, mFunctionServer);
+ return ret;
+}
+
+int ServiceRecord::setAttributeUintFs(int aAttrId, int aAttrType, TDesC8 &aNumVal, TBool isPersistenceRequired)
+{
+ JELOG2(EJavaBluetooth);
+ LOG1(EJavaBluetooth, EInfo, "+ ServiceRecord::setAttributeUint %d", aAttrId);
+
+ TRAPD(err,
+ {
+ if (aAttrId < 0)
+ {
+ if (mLastSdpAttr)
+ mLastSdpAttr = mLastSdpAttr -> BuildUintL(aNumVal);
+ }
+ else
+ {
+ CSdpAttrValueUint *val = NULL;
+ val = CSdpAttrValueUint::NewUintL(aNumVal);
+ mSdpDB.UpdateAttributeL(mRecord, aAttrId, *val);
+ delete val;
+ }
+ }
+ );
+
+ // Writing into persistent file for further usage
+ if (0 != mSrvRecFd && isPersistenceRequired)
+ {
+ int size = aNumVal.Size();
+ const TUint8 *ptr = aNumVal.Ptr();
+
+ LOG4(EJavaBluetooth, EInfo," ServiceRecord Writing %d, %d, %d, [%S]",
+ aAttrId, aAttrType, size, ptr);
+
+ write(mSrvRecFd, (char *)&aAttrId, sizeof(aAttrId));
+ write(mSrvRecFd, (char *)&aAttrType, sizeof(aAttrType));
+ write(mSrvRecFd, (char *)&size, sizeof(size));
+ write(mSrvRecFd, (char *)ptr, size);
+ }
+ return err;
+}
+
+/**
+ * Adds integer to the list (DEA/DES),
+ * or update the attribute list of SDP database
+ * On success returns 0; otherwise err number.
+ */
+OS_EXPORT int ServiceRecord::setAttributeInt(int aAttrId, int aAttrType, TDesC8 &aNumVal)
+{
+ JELOG2(EJavaBluetooth);
+ int ret = 0;
+ TBool persistentReq = ETrue;
+
+ CallMethod(ret, this, &ServiceRecord::setAttributeIntFs,
+ aAttrId, aAttrType, aNumVal, persistentReq, mFunctionServer);
+ return ret;
+}
+
+int ServiceRecord::setAttributeIntFs(int aAttrId, int aAttrType, TDesC8 &aNumVal, TBool isPersistenceRequired)
+{
+ JELOG2(EJavaBluetooth);
+ LOG1(EJavaBluetooth, EInfo, "+ ServiceRecord::setAttributeInt %d", aAttrId);
+
+ TRAPD(err,
+ {
+ if (aAttrId < 0)
+ {
+ if (mLastSdpAttr)
+ mLastSdpAttr = mLastSdpAttr -> BuildIntL(aNumVal);
+ }
+ else
+ {
+ CSdpAttrValueInt *val = NULL;
+ val = CSdpAttrValueInt::NewIntL(aNumVal);
+ mSdpDB.UpdateAttributeL(mRecord, aAttrId, *val);
+ delete val;
+ }
+ }
+ );
+
+ // Writing into persistent file for further usage
+ if (0 != mSrvRecFd && isPersistenceRequired)
+ {
+ int size = aNumVal.Size();
+ const TUint8 *ptr = aNumVal.Ptr();
+
+ LOG4(EJavaBluetooth, EInfo," ServiceRecord Writing %d, %d, %d, [%S]",
+ aAttrId, aAttrType, size, ptr);
+
+ write(mSrvRecFd, (char *)&aAttrId, sizeof(aAttrId));
+ write(mSrvRecFd, (char *)&aAttrType, sizeof(aAttrType));
+ write(mSrvRecFd, (char *)&size, sizeof(size));
+ write(mSrvRecFd, (char *)ptr, size);
+ }
+ return err;
+}
+
+/**
+ * Adds boolean value to the list (DEA/DES),
+ * or update the attribute list of SDP database
+ * On success returns 0; otherwise err number.
+ */
+OS_EXPORT int ServiceRecord::setAttributeBool(int aAttrId, TBool aBoolVal)
+{
+ JELOG2(EJavaBluetooth);
+ int ret = 0;
+ TBool persistentReq = ETrue;
+
+ CallMethod(ret, this, &ServiceRecord::setAttributeBoolFs,
+ aAttrId, aBoolVal, persistentReq, mFunctionServer);
+ return ret;
+}
+
+int ServiceRecord::setAttributeBoolFs(int aAttrId, TBool aBoolVal, TBool isPersistenceRequired)
+{
+ JELOG2(EJavaBluetooth);
+ LOG1(EJavaBluetooth, EInfo, "+ ServiceRecord::setAttributeBool %d", aAttrId);
+
+ TRAPD(err,
+ {
+ if (aAttrId < 0)
+ {
+ if (mLastSdpAttr)
+ mLastSdpAttr = mLastSdpAttr -> BuildBooleanL(aBoolVal);
+ }
+ else
+ {
+ CSdpAttrValueBoolean *val = NULL;
+ val = CSdpAttrValueBoolean::NewBoolL(aBoolVal);
+ mSdpDB.UpdateAttributeL(mRecord, aAttrId, *val);
+ delete val;
+ }
+ }
+ );
+
+ // Writing into persistent file for further usage
+ if (0 != mSrvRecFd && isPersistenceRequired)
+ {
+ // Taking largest type for storage
+ int type = DataElement_BOOL;
+ TUint8 val = (aBoolVal) ? 1 : 0;
+
+ LOG3(EJavaBluetooth, EInfo," ServiceRecord Writing %d, %d, %d",
+ aAttrId, type, val);
+
+ write(mSrvRecFd, (char *)&aAttrId, sizeof(aAttrId));
+ write(mSrvRecFd, (char *)&type, sizeof(type));
+ write(mSrvRecFd, (char *)&val, 1);
+ }
+ return err;
+}
+
+/**
+ * Adds UUID to the list (DEA/DES),
+ * or update the attribute list of SDP database
+ * On success returns 0; otherwise err number.
+ */
+OS_EXPORT int ServiceRecord::setAttributeUUID(int aAttrId, TUUID &aUUIDVal)
+{
+ JELOG2(EJavaBluetooth);
+ int ret = 0;
+ TBool persistentReq = ETrue;
+
+ CallMethod(ret, this, &ServiceRecord::setAttributeUUIDFs,
+ aAttrId, aUUIDVal, persistentReq, mFunctionServer);
+ return ret;
+}
+
+int ServiceRecord::setAttributeUUIDFs(int aAttrId, TUUID &aUUIDVal, TBool isPersistenceRequired)
+{
+ JELOG2(EJavaBluetooth);
+ LOG1(EJavaBluetooth, EInfo, "+ ServiceRecord::setAttributeUUID %d", aAttrId);
+
+ TRAPD(err,
+ {
+ if (aAttrId < 0)
+ {
+ if (mLastSdpAttr)
+ mLastSdpAttr = mLastSdpAttr -> BuildUUIDL(aUUIDVal);
+ }
+ else
+ {
+ CSdpAttrValueUUID *val = NULL;
+ val = CSdpAttrValueUUID::NewUUIDL(aUUIDVal);
+ mSdpDB.UpdateAttributeL(mRecord, aAttrId, *val);
+ delete val;
+ }
+ }
+ );
+
+ // Writing into persistent file for further usage
+ if (0 != mSrvRecFd && isPersistenceRequired)
+ {
+ int type = DataElement_UUID;
+ int size = aUUIDVal.Des().Size();
+ const TUint8 *ptr = aUUIDVal.Des().Ptr();
+
+ LOG4(EJavaBluetooth, EInfo," ServiceRecord Writing %d, %d, %d, [%S]",
+ aAttrId, type, size, ptr);
+
+ write(mSrvRecFd, (char *)&aAttrId, sizeof(aAttrId));
+ write(mSrvRecFd, (char *)&type, sizeof(type));
+ write(mSrvRecFd, (char *)&size, sizeof(size));
+ write(mSrvRecFd, (char *)ptr, size);
+ }
+ return err;
+}
+
+/**
+ * Adds string to the list (DEA/DES),
+ * or update the attribute list of SDP database
+ * On success returns 0; otherwise err number.
+ */
+OS_EXPORT int ServiceRecord::setAttributeString(int aAttrId, TDesC8 &aStrVal)
+{
+ JELOG2(EJavaBluetooth);
+ int ret = 0;
+ TBool persistentReq = ETrue;
+
+ CallMethod(ret, this, &ServiceRecord::setAttributeStringFs,
+ aAttrId, aStrVal, persistentReq, mFunctionServer);
+ return ret;
+}
+
+int ServiceRecord::setAttributeStringFs(int aAttrId, TDesC8 &aStrVal, TBool isPersistenceRequired)
+{
+ JELOG2(EJavaBluetooth);
+ LOG1(EJavaBluetooth, EInfo,
+ "+ ServiceRecord::setAttributeString %d", aAttrId);
+
+ TRAPD(err,
+ {
+ if (aAttrId < 0)
+ {
+ if (mLastSdpAttr)
+ mLastSdpAttr = mLastSdpAttr -> BuildStringL(aStrVal);
+ }
+ else
+ {
+ CSdpAttrValueString *val = NULL;
+ val = CSdpAttrValueString::NewStringL(aStrVal);
+ mSdpDB.UpdateAttributeL(mRecord, aAttrId, *val);
+ delete val;
+ }
+ }
+ );
+
+ // Writing into persistent file for further usage
+ if (0 != mSrvRecFd && isPersistenceRequired)
+ {
+ int type = DataElement_STRING;
+ int size = aStrVal.Size();
+ const TUint8 *ptr = aStrVal.Ptr();
+
+ LOG3(EJavaBluetooth, EInfo," ServiceRecord Writing %d, %d, %d",
+ aAttrId, type, size);
+
+ write(mSrvRecFd, (char *)&aAttrId, sizeof(aAttrId));
+ write(mSrvRecFd, (char *)&type, sizeof(type));
+ write(mSrvRecFd, (char *)&size, sizeof(size));
+ write(mSrvRecFd, (char *)ptr, size);
+ }
+ return err;
+}
+
+/**
+ * Adds URL to the list (DEA/DES),
+ * or update the attribute list of SDP database
+ * On success returns 0; otherwise err number.
+ */
+OS_EXPORT int ServiceRecord::setAttributeUrl(int aAttrId, TDesC8 &aUrlVal)
+{
+ JELOG2(EJavaBluetooth);
+ int ret = 0;
+ TBool persistentReq = ETrue;
+
+ CallMethod(ret, this, &ServiceRecord::setAttributeUrlFs,
+ aAttrId, aUrlVal, persistentReq, mFunctionServer);
+ return ret;
+}
+
+int ServiceRecord::setAttributeUrlFs(int aAttrId, TDesC8 &aUrlVal, TBool isPersistenceRequired)
+{
+ JELOG2(EJavaBluetooth);
+ LOG1(EJavaBluetooth, EInfo, "+ ServiceRecord::setAttributeUrl %d", aAttrId);
+
+ TRAPD(err,
+ {
+ if (aAttrId < 0)
+ {
+ if (mLastSdpAttr)
+ mLastSdpAttr = mLastSdpAttr -> BuildURLL(aUrlVal);
+ }
+ else
+ {
+ CSdpAttrValueURL *val = NULL;
+ val = CSdpAttrValueURL::NewURLL(aUrlVal);
+ mSdpDB.UpdateAttributeL(mRecord, aAttrId, *val);
+ delete val;
+ }
+ }
+ );
+ // Writing into persistent file for further usage
+ if (0 != mSrvRecFd && isPersistenceRequired)
+ {
+ int type = DataElement_URL;
+ int size = aUrlVal.Size();
+ const TUint8 *ptr = aUrlVal.Ptr();
+
+ LOG4(EJavaBluetooth, EInfo," ServiceRecord Writing %d, %d, %d, [%S]",
+ aAttrId, type, size, ptr);
+
+ write(mSrvRecFd, (char *)&aAttrId, sizeof(aAttrId));
+ write(mSrvRecFd, (char *)&type, sizeof(type));
+ write(mSrvRecFd, (char *)&size, sizeof(size));
+ write(mSrvRecFd, (char *)ptr, size);
+ }
+ return err;
+}
+
+/**
+ * Adds NIL to the list (DEA/DES),
+ * or update the attribute list of SDP database
+ * On success returns 0; otherwise err number.
+ */
+OS_EXPORT int ServiceRecord::setAttributeNil(int aAttrId)
+{
+ JELOG2(EJavaBluetooth);
+ int ret = 0;
+ TBool persistentReq = ETrue;
+
+ CallMethod(ret, this, &ServiceRecord::setAttributeNilFs,
+ aAttrId, persistentReq, mFunctionServer);
+ return ret;
+}
+
+int ServiceRecord::setAttributeNilFs(int aAttrId, TBool isPersistenceRequired)
+{
+ JELOG2(EJavaBluetooth);
+ LOG1(EJavaBluetooth, EInfo, "+ ServiceRecord::setAttributeNil %d", aAttrId);
+
+ TRAPD(err,
+ {
+ if (aAttrId < 0)
+ {
+ if (mLastSdpAttr)
+ mLastSdpAttr = mLastSdpAttr -> BuildNilL();
+ }
+ else
+ {
+ CSdpAttrValueNil *val = NULL;
+ val = CSdpAttrValueNil::NewNilL();
+ mSdpDB.UpdateAttributeL(mRecord, aAttrId, *val);
+ delete val;
+ }
+ }
+ );
+
+ // Writing into persistent file for further usage
+ if (0 != mSrvRecFd && isPersistenceRequired)
+ {
+ // Taking largest type for storage
+ int type = DataElement_NULL;
+
+ LOG2(EJavaBluetooth, EInfo, " ServiceRecord Writing %d, %d",
+ aAttrId, type);
+
+ write(mSrvRecFd, (char *)&aAttrId, sizeof(aAttrId));
+ write(mSrvRecFd, (char *)&type, sizeof(type));
+ }
+ return err;
+}
+
+/*
+ * This function is used to restore the Java Service Record by reading the
+ * persistent file. This function will work only once after midlet took
+ * the server connection handle from the Push framework.
+ * This function tries to populate Java Service record only when there is a
+ * successful retrieval of persistent storage exists.
+ */
+
+OS_EXPORT void ServiceRecord::restoreJavaServiceRecordL(
+ JNIEnv *aJni, jobject aServiceRecordImpl)
+{
+ JELOG2(EJavaBluetooth);
+
+ if (false == mInitializedByPush)
+ {
+ // No need of restoring anything since it is not a push service
+ return;
+ }
+
+ // Setting service record handle.
+ BTServiceRecordPopulator* srvRecPopulator =
+ BTServiceRecordPopulator::New(aJni, aServiceRecordImpl);
+
+ srvRecPopulator->SetServiceRecordHandle(mRecord);
+
+ if (false == mRestoredFromPersistentFile)
+ {
+ // No need of restoring anything from persistent file.
+ delete srvRecPopulator;
+ return;
+ }
+
+ std::wstring persistentFileName = getPersistentFileName();
+
+ int persistentRecFd = -1;
+ int ret = 0;
+
+ if (persistentFileName.length()> 0)
+ {
+ try
+ {
+ char *fileName =
+ java::util::JavaCommonUtils::wstringToUtf8(persistentFileName);
+ persistentRecFd = open(fileName, O_RDONLY);
+ delete fileName;
+ }
+ catch (ExceptionBase ex)
+ {
+ ELOG1(EJavaBluetooth,
+ "- ServiceRecord::restoreJavaServiceRecord exception caught: %S",
+ ex.toString().c_str());
+ }
+ }
+
+ if (persistentRecFd < 0)
+ {
+ // Nothing else to be done, as persistent file can not be opened or
+ // it is empty.
+ delete srvRecPopulator;
+ return;
+ }
+
+ MSdpElementBuilder* elementBuilder = (MSdpElementBuilder*) srvRecPopulator;
+
+ // Reading and restoring the DeviceServiceClasses bits (If any)
+ unsigned int devServClass = 0;
+ ret = read(persistentRecFd, &devServClass, sizeof(devServClass));
+ if (ret <= 0)
+ return;
+
+ elementBuilder = srvRecPopulator->SetDeviceServiceClass(devServClass);
+
+
+ // Calling first BuildDESL, is mandatory
+ elementBuilder = elementBuilder->BuildDESL();
+ elementBuilder = elementBuilder->StartListL();
+
+ int attrId = 0;
+ while ((ret = read(persistentRecFd, &attrId, sizeof(attrId))) > 0)
+ {
+ int dataType = 0;
+
+ ret = read(persistentRecFd, &dataType, sizeof(dataType));
+ if (ret <= 0)
+ break;
+
+ if (attrId > 0 && DataElement_EndList != dataType)
+ {
+ TSdpIntBuf<TUint> attrIdBuf(attrId);
+ elementBuilder = elementBuilder->BuildUintL(attrIdBuf);
+ }
+
+ LOG2(EJavaBluetooth, EInfo,
+ " ServiceRecord reading %X, %X", attrId, dataType);
+
+ switch (dataType)
+ {
+ case DataElement_DATSEQ:
+ {
+ elementBuilder = elementBuilder->BuildDESL();
+ elementBuilder = elementBuilder->StartListL();
+ break;
+ }
+ case DataElement_DATALT:
+ {
+ elementBuilder = elementBuilder->BuildDEAL();
+ elementBuilder = elementBuilder->StartListL();
+ break;
+ }
+ case DataElement_EndList:
+ {
+ elementBuilder = elementBuilder->EndListL();
+ break;
+ }
+ case DataElement_NULL:
+ {
+ elementBuilder = elementBuilder->BuildNilL();
+ break;
+ }
+ case DataElement_BOOL:
+ {
+ TUint8 val = 0;
+ ret = read(persistentRecFd, &val, sizeof(val));
+ if (ret <= 0)
+ break;
+
+ LOG1(EJavaBluetooth, EInfo,
+ " ServiceRecord reading Bool %X", val);
+ elementBuilder =
+ elementBuilder->BuildBooleanL((val) ? ETrue : EFalse);
+ break;
+ }
+ case DataElement_U_INT_1:
+ case DataElement_U_INT_2:
+ case DataElement_U_INT_4:
+ {
+ int len = 0;
+ ret = read(persistentRecFd, &len, sizeof(len));
+ if (ret <= 0)
+ break;
+
+ TUint8 bytes[20] = {0};
+ ret = read(persistentRecFd, bytes, len);
+ if (ret <= 0)
+ break;
+
+ LOG2(EJavaBluetooth, EInfo, " ServiceRecord reading INT 0x%X, 0x%X", len, bytes);
+
+ std::auto_ptr<HBufC8> buf(convertIntToDesC(bytes, dataType));
+ elementBuilder = elementBuilder->BuildUintL(*buf);
+ break;
+ }
+ case DataElement_U_INT_8:
+ case DataElement_U_INT_16:
+ {
+ int len = 0;
+ ret = read(persistentRecFd, &len, sizeof(len));
+ if (ret <= 0)
+ break;
+
+ TUint8 buf[20] = {0};
+ ret = read(persistentRecFd, buf, len);
+ if (ret <= 0)
+ break;
+
+ LOG2(EJavaBluetooth, EInfo, " ServiceRecord reading INT 0x%X, %S", len, buf);
+
+ TPtrC8 val(buf, len);
+ elementBuilder = elementBuilder->BuildUintL(val);
+ break;
+ }
+ case DataElement_INT_1:
+ case DataElement_INT_2:
+ case DataElement_INT_4:
+ {
+ int len = 0;
+ ret = read(persistentRecFd, &len, sizeof(len));
+ if (ret <= 0)
+ break;
+
+ TUint8 bytes[20] = {0};
+ ret = read(persistentRecFd, bytes, len);
+ if (ret <= 0)
+ break;
+
+ LOG2(EJavaBluetooth, EInfo, " ServiceRecord reading INT 0x%X, %S", len, bytes);
+
+ std::auto_ptr<HBufC8> buf(convertIntToDesC(bytes, dataType));
+ elementBuilder = elementBuilder->BuildIntL(*buf);
+ break;
+ }
+ case DataElement_INT_8:
+ case DataElement_INT_16:
+ {
+ int len = 0;
+ ret = read(persistentRecFd, &len, sizeof(len));
+ if (ret <= 0)
+ break;
+
+ TUint8 buf[20] = {0};
+ ret = read(persistentRecFd, buf, len);
+ if (ret <= 0)
+ break;
+
+ LOG2(EJavaBluetooth, EInfo, " ServiceRecord reading INT %X, %S", len, buf);
+
+ TPtrC8 val(buf, len);
+ elementBuilder = elementBuilder->BuildIntL(val);
+ break;
+ }
+ case DataElement_UUID:
+ {
+ int len = 0;
+ ret = read(persistentRecFd, &len, sizeof(len));
+ if (ret <= 0)
+ break;
+
+ TUint8 buf[256] = {0};
+ ret = read(persistentRecFd, buf, len);
+ if (ret <= 0)
+ break;
+
+ LOG2(EJavaBluetooth, EInfo, " ServiceRecord reading UUID %X, %S", len, buf);
+
+ TPtrC8 uuidDes(buf, len);
+
+ TUUID val;
+ val.SetL(uuidDes);
+
+ elementBuilder = elementBuilder->BuildUUIDL(val);
+ break;
+ }
+ case DataElement_STRING:
+ {
+ int len = 0;
+ ret = read(persistentRecFd, &len, sizeof(len));
+ if (ret <= 0)
+ break;
+
+ TUint8 buf[1024] = {0};
+ ret = read(persistentRecFd, buf, len);
+ if (ret <= 0)
+ break;
+
+ LOG1(EJavaBluetooth, EInfo,
+ " ServiceRecord reading STRING %X", len);
+
+ TPtrC8 val(buf, len);
+ LOG(EJavaBluetooth, EInfo,
+ " ServiceRecord::RestoreJavaServiceRecord BuildStringL");
+ elementBuilder = elementBuilder->BuildStringL(val);
+ break;
+ }
+ case DataElement_URL:
+ {
+ int len = 0;
+ ret = read(persistentRecFd, &len, sizeof(len));
+ if (ret <= 0)
+ break;
+
+ TUint8 buf[1024] = {0};
+ ret = read(persistentRecFd, buf, len);
+ if (ret <= 0)
+ break;
+
+ LOG2(EJavaBluetooth, EInfo,
+ " ServiceRecord reading URL %X, %S", len, buf);
+
+ TPtrC8 val(buf, len);
+ elementBuilder = elementBuilder->BuildURLL(val);
+ break;
+ }
+ default:
+ break;
+ }
+ if (0 == ret)
+ break;
+ }
+
+ delete srvRecPopulator;
+
+ return;
+}
+
+// Helper function
+HBufC8* ServiceRecord::convertIntToDesC(TUint8 *aBytes, int aDataType)
+{
+ JELOG2(EJavaBluetooth);
+ HBufC8* descBytes = NULL;
+ switch (aDataType)
+ {
+ case DataElement_INT_1:
+ case DataElement_U_INT_1:
+ {
+ descBytes = HBufC8::New(sizeof(TUint8) + 1);
+ TPtr8 ptr = descBytes->Des();
+ TUint value = *(TUint *)aBytes;
+ value=ByteOrder::Swap32(value);
+
+ TSdpIntBuf<TUint8> buf(value);
+ ptr.Copy(buf);
+ break;
+ }
+ case DataElement_INT_2:
+ case DataElement_U_INT_2:
+ {
+ descBytes = HBufC8::New(sizeof(TUint16) + 1);
+ TPtr8 ptr = descBytes->Des();
+ TUint value = *(TUint *)aBytes;
+ value=ByteOrder::Swap32(value);
+
+ TSdpIntBuf<TUint16> buf(value);
+ ptr.Copy(buf);
+ break;
+ }
+ case DataElement_INT_4:
+ case DataElement_U_INT_4:
+ {
+ descBytes = HBufC8::New(sizeof(TUint32) + 1);
+ TPtr8 ptr = descBytes->Des();
+ TUint value = *(TUint *)aBytes;
+ value=ByteOrder::Swap32(value);
+
+ TSdpIntBuf<TUint32> buf(value);
+ ptr.Copy(buf);
+ break;
+ }
+ default:
+ {
+ descBytes = HBufC8::New(sizeof(TUint64) + 1);
+ TPtr8 ptr = descBytes->Des();
+
+ TSdpIntBuf<TUint64> buf(*(TUint64 *)aBytes);
+ ptr.Copy(buf);
+ break;
+ }
+ }
+
+ return descBytes;
+}
+
+TUint8 *ServiceRecord::uuidToByteArray(std::wstring aUuid,
+ int &aUuidByteLength)
+{
+ JELOG2(EJavaBluetooth);
+
+ int len = aUuid.length();
+ int resultLen = (len/2) + 1;
+ TUint8 *result = new TUint8[resultLen];
+ int index = 0;
+ int byteIndex = 0;
+
+ LOG1(EJavaBluetooth, EInfo, " ServiceRecord::uuidToByteArray Length:%d", len);
+
+ if ((len % 2) != 0)
+ {
+ int charPos = charToInt(aUuid[index]);
+ index += 1;
+ result[byteIndex ++] = charPos;
+ }
+
+ while (index < len)
+ {
+ result[byteIndex ++] = (charToInt(aUuid[index]) << 4) |
+ charToInt(aUuid[index + 1]);
+ index += 2;
+ }
+ aUuidByteLength = (len /2) + (len %2);
+
+ return result;
+}
+
+TInt8 ServiceRecord::charToInt(wchar_t ch)
+{
+ std::wstring validUpperChars(L"0123456789ABCDEF"); // Never change this.
+ std::wstring validLowerChars(L"0123456789abcdef"); // Never change this.
+ TInt8 result = -1;
+ if ((result = validUpperChars.find(ch)) == std::wstring::npos)
+ {
+ result = validLowerChars.find(ch);
+ }
+ return result;
+}
+
+std::wstring ServiceRecord::uuidToWstring(TUUID aUuid)
+{
+ JELOG2(EJavaBluetooth);
+
+ std::wstring validChars(L"0123456789ABCDEF"); // Never change this.
+ std::wstring result;
+
+ int len = aUuid.Des().Size();
+ const TUint8 *ptr = aUuid.Des().Ptr();
+
+ for (int i = 0; i < len; i ++, ptr ++)
+ {
+ result += validChars[((*ptr) >> 4)];
+ result += validChars[((*ptr) & 0x0F)];
+ LOG1(EJavaBluetooth, EInfo,
+ " ServiceRecord::uuidToWstring %S", result.c_str());
+ }
+
+ return result;
+}
+
+} //end namespace bluetooth
+} //end namespace java