diff -r 000000000000 -r 29b1cd4cb562 bluetoothmgmt/btmgr/BTManClient/BTManClient.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetoothmgmt/btmgr/BTManClient/BTManClient.cpp Fri Jan 15 08:13:17 2010 +0200 @@ -0,0 +1,1315 @@ +// Copyright (c) 1999-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: +// + +#include +#include +#include +#include "btmanclientserver.h" +#include "s32strm.h" +#include + +#ifdef __FLOG_ACTIVE +_LIT8(KLogComponent, LOG_COMPONENT_BT_MANAGER_CLIENT); +#endif + +const TInt KServerRetries = 2; +const TUint8 KDummyDevicePointer = 0xff; + +/** +Start the btmanserver +@return Systemwide error code +@internalComponent +@released +*/ +static TInt StartServer() + { + LOG_STATIC_FUNC + + const TUidType serverUid(KNullUid,KNullUid,KBTManServerUid3); + +#ifdef __BTMANSERVER_NO_PROCESSES__ + // + // In EKA1 WINS the server is a DLL, the exported entrypoint returns a TInt + // which represents the real entry-point for the server thread + // + RLibrary lib; + TInt r=lib.Load(KBTManServerImg,serverUid); + if (r!=KErrNone) + return r; + TLibraryFunction ordinal1=lib.Lookup(1); + TThreadFunction serverFunc=reinterpret_cast(ordinal1()); + // + // To deal with the unique thread (+semaphore!) naming in EPOC, and that we may + // be trying to restart a server that has just exited we attempt to create a + // unique thread name for the server. + // This uses Math::Random() to generate a 32-bit random number for the name + // + TName name(KBTManServerName); + _LIT(KHexString, "0x"); + name.Append(KHexString()); + name.AppendNum(Math::Random(),EHex); + RThread server; + r=server.Create(name,serverFunc, + KBTManServerStackSize, + NULL,&lib,NULL, + KBTManServerInitHeapSize,KBTManServerMaxHeapSize,EOwnerProcess); + lib.Close(); // if successful, server thread has handle to library now +#else + // + // EPOC and EKA2 is easy, we just create a new server process. Simultaneous + // launching of two such processes should be detected when the second one + // attempts to create the server object, failing with KErrAlreadyExists. + // + RProcess server; + TInt r=server.Create(KBTManServerImg,KNullDesC,serverUid); +#endif + + LOG1(_L("BTMan Server created, code %d"), r); + + if (r!=KErrNone) + return r; + TRequestStatus stat; + server.Rendezvous(stat); + if (stat!=KRequestPending) + { + server.Kill(0); // abort startup + } + else + { + server.Resume(); // logon OK - start the server + LOG(_L("BTMan Server Resumed")); + } + + User::WaitForRequest(stat); // wait for start or death + // we can't use the 'exit reason' if the server panicked as this + // is the panic 'reason' and may be '0' which cannot be distinguished + // from KErrNone + LOG1(_L("BTMan Server started, code %d (0=>success)"), stat.Int()); + r=(server.ExitType()==EExitPanic) ? KErrGeneral : stat.Int(); + + server.Close(); + LOG(_L("BTMan Server Closed")); + + return r; + } + + +/** +Default Constructor. +@publishedAll +@released +*/ +EXPORT_C RBTMan::RBTMan() + { + LOG_FUNC + } + + +/** +Connects to the btman server. +@return systemwide error code +@publishedAll +@released +*/ +EXPORT_C TInt RBTMan::Connect() + { + LOG_FUNC + TInt retry=KServerRetries; + for (;;) + { + TInt r=CreateSession(KBTManServerName,Version()); //gives MessageSlots of -1 + //this uses global pool rather + //than local pool + if (r!=KErrNotFound && r!=KErrServerTerminated) + return r; + if (--retry==0) + return r; + r=StartServer(); + if (r!=KErrNone && r!=KErrAlreadyExists) + return r; + } + } + +/** +Returns the version of the server. +@return version of btmanserver +*/ +EXPORT_C TVersion RBTMan::Version() const +/** +**/ + { + LOG_FUNC + return TVersion(KBTManServerMajorVersionNumber, + KBTManServerMinorVersionNumber, + KBTManServerBuildVersionNumber); + } + + +/** +Default constructor of base class for subsessions +@publishedAll +@released +*/ +EXPORT_C RBTManSubSession::RBTManSubSession() +: iClientServerMsg() + { + LOG_FUNC + iClientServerMsg().iClientBusy = EFalse; + iClientServerMsg().iClientStatusToCancel = NULL; + } + +/** +Cancel an outstanding request on btmanserver +@param aStatus the status of active object that made the original request +@publishedAll +@released +*/ +EXPORT_C void RBTManSubSession::CancelRequest(TRequestStatus& aStatus) + { + LOG_FUNC + if (SubSessionHandle()) + { + SendReceive(EBTManCancelRequest, TIpcArgs(&aStatus)); + } + else + { + //Client has a bad handle therefore complete the call from here + LocalComplete(aStatus, KErrBadHandle); + } + } + +/** +Completes a request locally without involving the server. +Called when a client-side error occurs. +@param aStatus: The TRequestStatus of the active object that made the request that needs to be completed. +@param aErr: The reason for completion. aErr will be written into the TRequestStatus of the active object. +@internalComponent +@released +**/ +void RBTManSubSession::LocalComplete(TRequestStatus& aStatus, TInt aErr) + { + LOG_FUNC + aStatus = KRequestPending; + TRequestStatus* pS = &aStatus; + User::RequestComplete(pS, aErr); + } + + +TBool RBTManSubSession::IsBusy() const + { + LOG_FUNC + return iClientServerMsg().iClientBusy; + } + +/** +To prevent clients using the server more than once +Business is cleared once the server has completed the job +@param aStatus the status of the client AO making a request on the server. this will can be used for cancelling later +@internalComponent +@released +**/ +void RBTManSubSession::SetBusy(TRequestStatus& aStatus) + { + LOG_FUNC + iClientServerMsg().iClientBusy = ETrue; + iClientServerMsg().iClientStatusToCancel = &aStatus; + } + +/** +Default constructor of registry session +@publishedAll +@released +*/ +EXPORT_C RBTRegServ::RBTRegServ() + { + LOG_FUNC + } + + +/** +Connect to Registry Server +@return System-wide error code +@publishedAll +@released +@capability LocalServices +*/ +EXPORT_C TInt RBTRegServ::Connect() + { + LOG_FUNC + // we provide the standard RBTMan session for now, but the client doesnt know this! + TInt r=RBTMan::Connect(); + return r; + } + +/** +Close session on Registry Server +@publishedAll +@released +*/ +EXPORT_C void RBTRegServ::Close() + { + LOG_FUNC + RBTMan::Close(); + } + +/** +Return reference to the server session +@return reference to btman session +@publishedAll +@released +*/ +EXPORT_C RBTMan& RBTRegServ::Session() + { + LOG_STATIC_FUNC + return static_cast(*this); + } + +#ifndef _DEBUG +EXPORT_C TInt RBTRegServ::SetHeapFailure(TInt /*aType*/,TInt /*aRate*/) +#else +EXPORT_C TInt RBTRegServ::SetHeapFailure(TInt aType,TInt aRate) +#endif +/** +Send a message to the server to fail memory allocations (in debug builds) +@internalAll +@released +*/ + { + LOG_FUNC +#ifdef _DEBUG + return SendReceive(EBTManSetHeapFailure,TIpcArgs(static_cast(aType), aRate)); +#else + return KErrNotSupported; +#endif + } + + +/** +Returns the number of open subsessions. +This should be used by clients to do resource leakage debugging checks +@publishedAll +@released +*/ +EXPORT_C TInt RBTRegServ::ResourceCount() + { + LOG_FUNC + TInt count = 0; + TPckg pckg(count); + SendReceive(EBTManSubSessionCount, TIpcArgs(&pckg)); + return count; + } + +/** +Default constructor for registry subsession +@publishedAll +@released +*/ +EXPORT_C RBTRegistry::RBTRegistry() +: RBTManSubSession(), iDevicePckg(*reinterpret_cast(KDummyDevicePointer)) + { + LOG_FUNC + } + +/** +Open a Bluetooth device subsession. +@param aSession The BTManager session to which this subsession is to be attached. +@return An error code depicting the outcome of the "open". +@publishedAll +@released +@capability LocalServices +*/ +EXPORT_C TInt RBTRegistry::Open(RBTRegServ& aSession) + { + LOG_FUNC + iSendBuffer = NULL; + return CreateSubSession(aSession.Session(), EBTManCreateRegistrySubSession, TIpcArgs(NULL)); + } + +/** Create a constrained view of devices on the remote device table of the registry server. + +This is in effect a registry search facility. +It is needed if the user wishes find data in the registry of uncertain size. +For example:- +1) a list of remote devices. +2) full details of a remote device including its name and/or friendly name. +Note 1: Some methods in the API (e.g. UnpairAllInView) require a view to have been created prior to their use. +Note 2: When a view has been generated, if details of the device(s) found are needed, these should be obtained using an instance of CBTRegistryResponse. +Note 3: A view must be closed before a new view can be created. + +@see UnpairAllInView +@see DeleteAllInView +@see CloseView +@see NotifyViewChange +@see TBTRegistrySearch +@see CBTRegistryResponse +@param aSearch A search struct with details of devices to be contained in the result set +@param aStatus TRequestStatus supplied by caller +@return systemwide error +@publishedAll +@released +@capability LocalServices +@capability ReadDeviceData (LocalServices only if link key is not needed) +*/ +EXPORT_C void RBTRegistry::CreateView(const TBTRegistrySearch& aSearch, TRequestStatus& aStatus) + { + LOG_FUNC + if (IsBusy()) + { + LocalComplete(aStatus, KErrInUse); + } + else + { + if (SubSessionHandle()) + { + SetBusy(aStatus); + iSearchPckg = aSearch; + SendReceive(EBTManRegistrySearch, TIpcArgs(&iSearchPckg, NULL, &iClientServerMsg), aStatus); + } + else + { + //Client has a bad handle therefore complete the call from here + LocalComplete(aStatus, KErrBadHandle); + } + } + } + +/** +Close the subsession. Removes all server side resources pertaining to this subsession +@publishedAll +@released +*/ +EXPORT_C void RBTRegistry::Close() + { + LOG_FUNC + delete iSendBuffer; + iSendBuffer = NULL; + RSubSessionBase::CloseSubSession(EBTManCloseSubSession); + } + + +/** +Close a previously created view on the registry. +Allows an app to use this subsession for other view or non-view operations +@return Systemwide error +@post Subsession is left open for further use - eg to create another view, or perform a viewless operation +@publishedAll +@released +*/ +EXPORT_C TInt RBTRegistry::CloseView() + { + LOG_FUNC + if (SubSessionHandle()) + { + return SendReceive(EBTRegistryCloseView, TIpcArgs(NULL, NULL, NULL)); // synchronous + } + else + { + return KErrBadHandle; + } + } + + +/** +Unpair a device in the registry +@param aAddress The device to unpair +@param aStatus reference to client AO's TRequestStatus +@publishedPartner +@released +@capability LocalServices +@capability WriteDeviceData +*/ +EXPORT_C void RBTRegistry::UnpairDevice(const TBTDevAddr& aAddress, TRequestStatus& aStatus) + { + LOG_FUNC + if (IsBusy()) + { + LocalComplete(aStatus, KErrInUse); + } + else + { + if (SubSessionHandle()) + { + SetBusy(aStatus); + iAddrBuf = aAddress; + SendReceive(EBTRegistryDeleteLinkKey, TIpcArgs(&iAddrBuf, NULL, &iClientServerMsg), aStatus); + } + else + { + //Client has a bad handle therefore complete the call from here + LocalComplete(aStatus, KErrBadHandle); + } + } + } + +/** +Unpair all the devices in the view - useful to unbond eg all devices (create a View with search All), or eg unbond all headsets +@param aStatus reference to client AO's TRequestStatus +@publishedPartner +@released +@capability LocalServices +@capability WriteDeviceData +*/ +EXPORT_C void RBTRegistry::UnpairAllInView(TRequestStatus& aStatus) + { + LOG_FUNC + if (SubSessionHandle()) + { + iClientServerMsg().iClientStatusToCancel = &aStatus; + SendReceive(EBTRegistryUnpairView, TIpcArgs(NULL, NULL, &iClientServerMsg), aStatus); + } + else + { + //Client has a bad handle therefore complete the call from here + LocalComplete(aStatus, KErrBadHandle); + } + } + + +/** +Add device to the registry +@leave OOM +@param aDevice reference to CBTDevice of details of device to add +@param aStatus reference to client AO's TRequestStatus +@publishedAll +@released +@capability LocalServices +*/ +EXPORT_C void RBTRegistry::AddDeviceL(const CBTDevice& aDevice, TRequestStatus& aStatus) + { + LOG_FUNC + if (IsBusy()) + { + LocalComplete(aStatus, KErrInUse); + } + else + { + if (SubSessionHandle()) + { + if (iSendBuffer) + { + delete iSendBuffer; + iSendBuffer = NULL; + } + // need to contiguate CBTDevice into a buffer + SetBusy(aStatus); + iSendBuffer = CBufFlat::NewL(sizeof(CBTDevice)); //granularity + + RBufWriteStream stream; + stream.Open(*iSendBuffer); + CleanupClosePushL(stream); + + aDevice.ExternalizeL(stream); + const TPtr8 ptr=iSendBuffer->Ptr(0); + iSendBufferPtr.Set(ptr); + // now we can give the buffer to BTMan + SendReceive(EBTRegistryAddDevice, TIpcArgs(&iSendBufferPtr, NULL, &iClientServerMsg), aStatus); + + CleanupStack::PopAndDestroy(1); // stream + } + else + { + //Client has a bad handle therefore complete the call from here + LocalComplete(aStatus, KErrBadHandle); + } + } + } + +/** +Get a *nameless* device to the registry. To retrieve a full device with names a view should be created +@see CreateView +@pre Clients must ensure that they do not call this method while the same operation is already outstanding on the same RBTRegistry subsession +@param aDevice reference to TBTDevice (used as input and output). The input MUST contain the device address - this is used as the key. Once the method completes the reference will contain all other details found from the registry +@param aStatus reference to client AO's TRequestStatus +@publishedPartner +@released +@capability LocalServices +@capability ReadDeviceData (LocalServices only if link key is not needed) +*/ +EXPORT_C void RBTRegistry::GetDevice(TBTNamelessDevice& aDevice, TRequestStatus& aStatus) + { + LOG_FUNC + if (IsBusy()) + { + LocalComplete(aStatus, KErrInUse); + } + else + { + if (SubSessionHandle()) + { + SetBusy(aStatus); + TPckg temp(aDevice); + iDevicePckg.Set(temp); + SendReceive(EBTRegistryGetNamelessDevice, TIpcArgs(&iDevicePckg, NULL, &iClientServerMsg), aStatus); + } + else + { + //Client has a bad handle therefore complete the call from here + LocalComplete(aStatus, KErrBadHandle); + } + } + } + + +/** +Modify the friendly name of a device +@leave OOM +@param aAddress The address of the device of which to change the name +@param aName The new name (note - not an 8bit descriptor) +@param aStatus reference to client AO's TRequestStatus +@publishedAll +@released +@capability LocalServices +*/ +EXPORT_C void RBTRegistry::ModifyFriendlyDeviceNameL(const TBTDevAddr& aAddress, + const TDesC& aName, + TRequestStatus& aStatus) + { + LOG_FUNC + if (IsBusy()) + { + LocalComplete(aStatus, KErrInUse); + } + else + { + if (SubSessionHandle()) + { + SetBusy(aStatus); + TBuf8 tempBuf; + tempBuf.Zero(); + if (CnvUtfConverter::ConvertFromUnicodeToUtf8(tempBuf, aName) != KErrNone) + { + LocalComplete(aStatus, KErrBadName); + return; + } + + if (iSendBuffer) + { + delete iSendBuffer; + iSendBuffer = NULL; + } + + iSendBuffer = CBufFlat::NewL(sizeof(TBuf8)); //granularity + + iSendBuffer->Reset(); + iSendBuffer->InsertL(0, tempBuf); + + const TPtr8 ptr=iSendBuffer->Ptr(0); + iSendBufferPtr.Set(ptr); + + iAddrBuf = aAddress; + + SendReceive(EBTRegistryModifyFriendlyName, + TIpcArgs(&iAddrBuf, &iSendBufferPtr, &iClientServerMsg), aStatus); + } + else + { + //Client has a bad handle therefore complete the call from here + LocalComplete(aStatus, KErrBadHandle); + } + } + } + + + +/** +Modify the Bluetooth name of a device. This is not used beyond the stack +@param aAddress The address of the device of which to change the name +@param aName The new name (note - this is an 8bit descriptor) +@param aStatus reference to client AO's TRequestStatus +@internalAll +@released +@capability LocalServices +@capability WriteDeviceData (localServices only if friendly device name) +*/ +EXPORT_C void RBTRegistry::ModifyBluetoothDeviceNameL(const TBTDevAddr& aAddress, + const TDesC8& aName, + TRequestStatus& aStatus) + { + LOG_FUNC + if (IsBusy()) + { + LocalComplete(aStatus, KErrInUse); + } + else + { + if (SubSessionHandle()) + { + SetBusy(aStatus); + + if (iSendBuffer) + { + delete iSendBuffer; + iSendBuffer = NULL; + } + + iSendBuffer = CBufFlat::NewL(sizeof(TBuf8)); //granularity + + iSendBuffer->Reset(); + iSendBuffer->InsertL(0, aName); + + const TPtr8 ptr=iSendBuffer->Ptr(0); + iSendBufferPtr.Set(ptr); + + iAddrBuf = aAddress; + + SendReceive(EBTRegistryModifyBluetoothName, + TIpcArgs(&iAddrBuf, &iSendBufferPtr, &iClientServerMsg), aStatus); + } + else + { + //Client has a bad handle therefore complete the call from here + LocalComplete(aStatus, KErrBadHandle); + } + } + } + + +/** +Update details of a device - other than its names: Not used beyond stack +@param aDeviceDetails The new details - the device address MUST be present in aDeviceDetails is used as the key +@param aStatus reference to client AO's TRequestStatus +@internalTechnology +@released +@capability LocalServices +@capability WriteDeviceData +*/ +EXPORT_C void RBTRegistry::ModifyDevice(const TBTNamelessDevice& aDeviceDetails, TRequestStatus& aStatus) + { + LOG_FUNC + if (IsBusy()) + { + LocalComplete(aStatus, KErrInUse); + } + else + { + if (SubSessionHandle()) + { + SetBusy(aStatus); + TPckg temp(aDeviceDetails); + iDevicePckg.Set(temp); + SendReceive(EBTRegistryModifyNamelessDevice, TIpcArgs(&iDevicePckg, NULL, &iClientServerMsg), aStatus); + } + else + { + //Client has a bad handle therefore complete the call from here + LocalComplete(aStatus, KErrBadHandle); + } + } + } + +/** +Notifies the client when a change has been made to the registry that affects the currently open view of devices. +@see CreateView +@see CloseView +@param aStatus reference to client AO's TRequestStatus +@publishedAll +@released +*/ +EXPORT_C void RBTRegistry::NotifyViewChange(TRequestStatus& aStatus) + { + LOG_FUNC + if (SubSessionHandle()) + { + // We don't set the session as busy because then no other commands can be sent + iClientServerMsg().iClientStatusToCancel = &aStatus; + SendReceive(EBTRegistryNotifyViewChange, TIpcArgs(NULL, NULL, &iClientServerMsg), aStatus); + } + else + { + //Client has a bad handle therefore complete the call from here + LocalComplete(aStatus, KErrBadHandle); + } + } + +/** +@internalComponent +*/ +void RBTRegistry::PreLoad(TRequestStatus& aStatus) + { + LOG_FUNC + if (SubSessionHandle()) + { + iClientServerMsg().iClientStatusToCancel = &aStatus; + SendReceive(EBTManExtractRegistryDataIntoServer, TIpcArgs(NULL, NULL, &iClientServerMsg), aStatus); + } + else + { + //Client has a bad handle therefore complete the call from here + LocalComplete(aStatus, KErrBadHandle); + } + } + + + +/** +@internalComponent +**/ +void RBTRegistry::GetResults(TPtr8& aResults, TRequestStatus& aStatus) + { + LOG_FUNC + if (SubSessionHandle()) + { + iClientServerMsg().iClientStatusToCancel = &aStatus; + SendReceive(EBTManRetrieveRegistryData, TIpcArgs(&aResults, NULL, &iClientServerMsg), aStatus); + } + else + { + //Client has a bad handle therefore complete the call from here + LocalComplete(aStatus, KErrBadHandle); + } + } + +/** +Remove all devices in the view from the Registry +@pre View must be created first by client +@see CreateView +@param aStatus a TRequestStatus passed in by the caller +@publishedPartner +@released +@capability LocalServices +@capability WriteDeviceData (Only if different process than the one that created the device) +*/ +EXPORT_C void RBTRegistry::DeleteAllInView(TRequestStatus& aStatus) + { + LOG_FUNC + if (SubSessionHandle()) + { + iClientServerMsg().iClientStatusToCancel = &aStatus; + SendReceive(EBTRegistryDeleteDevices, TIpcArgs(NULL, NULL, &iClientServerMsg), aStatus); + } + else + { + //Client has a bad handle therefore complete the call from here + LocalComplete(aStatus, KErrBadHandle); + } + } + +/** +default c'tor +@publishedAll +@released +*/ +EXPORT_C RBTLocalDevice::RBTLocalDevice() +:RBTManSubSession(), iLocalDevicePckg(*reinterpret_cast(KDummyDevicePointer)) + { + LOG_FUNC + } + + +/** +Open a local device subsession on the server, used for manipulating settings about the local device +@param aSession A server session +@return systemwide error +@publishedAll +@released +*/ +EXPORT_C TInt RBTLocalDevice::Open(RBTRegServ& aSession) + { + LOG_FUNC + return CreateSubSession(aSession.Session(), EBTManCreateLocalDeviceSubSession, TIpcArgs(NULL)); + } + + +/** +Close the subsession on the server +@publishedAll +@released +*/ +EXPORT_C void RBTLocalDevice::Close() + { + LOG_FUNC + RSubSessionBase::CloseSubSession(EBTManCloseSubSession); + } + + +/** +Retrieve the local device details. Synchronous - intended mainly for Bluetooth stack use on startup + +@param aLocalDeviceResult a reference to a TBTLocalDevice to store the results from the Registry +@return SystemWide error +@publishedAll +@released +*/ +EXPORT_C TInt RBTLocalDevice::Get(TBTLocalDevice& aLocalDeviceResult) + { + LOG_FUNC + if (SubSessionHandle()) + { + TPckg pckg(aLocalDeviceResult); + return SendReceive(EBTRegistryGetLocalDevice, TIpcArgs(&pckg, NULL, NULL)); // synchronous + } + else + { + //Client has a bad handle therefore complete the call from here + return KErrBadHandle; + } + } + +/** +Update the details about the local Bluetooth device +@param aLocalDevice New settings for local device +@param aStatus reference Client AO's TRequestStatus +@publishedPartner +@released +@capability LocalServices +@capability WriteDeviceData +*/ +EXPORT_C void RBTLocalDevice::Modify(const TBTLocalDevice& aLocalDevice, TRequestStatus& aStatus) + { + LOG_FUNC + if (IsBusy()) + { + LocalComplete(aStatus, KErrInUse); + } + else + { + if (SubSessionHandle()) + { + SetBusy(aStatus); + TPckg pckg(aLocalDevice); + iLocalDevicePckg.Set(pckg); + SendReceive(EBTRegistryUpdateLocalDevice, TIpcArgs(&iLocalDevicePckg, NULL, &iClientServerMsg), aStatus); + } + else + { + //Client has a bad handle therefore complete the call from here + LocalComplete(aStatus, KErrBadHandle); + } + } + } + +/** +Synchronous overload of Modify (primarily for stack operations) +@see RBTLocalDevice::Modify(const TBTLocalDevice& aLocalDevice, TRequestStatus& aStatus) +@publishedPartner +@released +@capability LocalServices +@capability WriteDeviceData +*/ +EXPORT_C TInt RBTLocalDevice::Modify(const TBTLocalDevice& aLocalDevice) + { + LOG_FUNC + // synchronous version for stack on close-down + TRequestStatus status; + Modify(aLocalDevice, status); + User::WaitForRequest(status); + return status.Int(); + } + + +/** +Two-phase constructor to create a helper class to retrieve a set of results (a view) from the Registry +@leave OOM +@pre A non-empty view on the Registry task has been created +@param aView the Registry subsession that has had a View created on it +@return pointer to allocated object +@see CreateView() +@publishedAll +@released +*/ +EXPORT_C CBTRegistryResponse* CBTRegistryResponse::NewL(RBTRegistry& aView) + { + LOG_STATIC_FUNC + return new (ELeave) CBTRegistryResponse(aView); + } + + +/** +Start fetching results from the Registry Server. When the request is complete, the results can be obtained via the Results() method. +@param aClientStatus a TRequestStatus passed in by the caller +@publishedAll +@released +*/ +EXPORT_C void CBTRegistryResponse::Start(TRequestStatus& aClientStatus) + { + LOG_FUNC + // we do late construction on the heap buffer + __ASSERT_DEBUG(!IsActive(), User::Panic(KBTManClientPanic, EBTManClientResultRetrieveAlreadyActive)); + + iClientStatus = &aClientStatus; + *iClientStatus = KRequestPending; + CActiveScheduler::Add(this); + DoGet(); + } + +/** Get Results previously fetched from the Registry Server. + +@pre The method Start needs to have been called, and notification of its completion received. +@return reference to the array of results +@publishedAll +@released +*/ +EXPORT_C RBTDeviceArray& CBTRegistryResponse::Results() + { + LOG_FUNC + return iArray; + } + +CBTRegistryResponse::CBTRegistryResponse(RBTRegistry& aView) +: CActive(EPriorityStandard), iView(aView), iResponsePtr(NULL,0) + { + LOG_FUNC + } + +/** +Destructor +*/ +EXPORT_C CBTRegistryResponse::~CBTRegistryResponse() + { + LOG_FUNC + Cancel(); + + iArray.ResetAndDestroy(); + delete iResponseBuf; + } + +void CBTRegistryResponse::DoGet() + { + LOG_FUNC +// create RPointerArray to point to n CBTDevices +// ask server async size of result set - this causes BTMan to extract from DBMS and return size +// we then allocate and in 2nd phase get the stuff from the server (could be synchronous +// we could wrap all this up in a helper object for client to use: CBTRegistryResponder + + iArray.ResetAndDestroy(); + iState = EGettingSize; + // Get the size of the entry + iView.PreLoad(iStatus); + SetActive(); + } + +void CBTRegistryResponse::DoCancel() + { + LOG_FUNC + //cancel the server + iView.CancelRequest(iStatus); + //notify our user + User::RequestComplete(iClientStatus, KErrCancel); + } + +void CBTRegistryResponse::RunL() + { + LOG_FUNC + switch (iState) + { + case EGettingSize: + { + // get the results + if (iStatus.Int() >= KErrNone) + { + // we have a byte count of the response size + iResponseBuf = HBufC8::NewMaxL(iStatus.Int()); + iResponsePtr.Set(iResponseBuf->Des()); + iView.GetResults(iResponsePtr, iStatus); + iState = EGettingResults; + SetActive(); + } + else + { + User::Leave(iStatus.Int()); + } + } + break; + case EGettingResults: + { + if (iStatus.Int() >= KErrNone) + { + // got n CBTDevices to return + TInt c = iStatus.Int(); + RDesReadStream stream(iResponsePtr); + CleanupClosePushL(stream); + while (c-->0) + { + CBTDevice* device = CBTDevice::NewLC(); + device->InternalizeL(stream); + // place it into the result array + User::LeaveIfError(iArray.Append(device)); + CleanupStack::Pop(); //device - don't destroy as 'owned' by array + } + CleanupStack::PopAndDestroy(); //stream + // free up memory: + delete iResponseBuf; + iResponseBuf = NULL; + + User::RequestComplete(iClientStatus, KErrNone); + } // if + else + { + User::Leave(iStatus.Int()); + } + break; + } // case + default: + User::Panic(KBTManClientPanic, EBTManClientBadResultRetrieveState); + } + + } + +TInt CBTRegistryResponse::RunError(TInt aError) + { + LOG_FUNC + //complete request if its pending + if (*iClientStatus == KRequestPending) + { + User::RequestComplete(iClientStatus, aError); + } + return KErrNone; + } + +/** +Default constructor +@publishedAll +@released +*/ +EXPORT_C TBTRegistrySearch::TBTRegistrySearch() + { + LOG_FUNC + Reset(); + } + +/** +Resets the search criteria +@publishedAll +@released +*/ +EXPORT_C void TBTRegistrySearch::Reset() + { + LOG_FUNC + iSearchMask =0; + } + +/** +Copy Constructor +@publishedAll +@released +*/ +EXPORT_C TBTRegistrySearch::TBTRegistrySearch(const TBTRegistrySearch& aSearch) + { + LOG_FUNC + iSearchMask = aSearch.iSearchMask; + iDeviceClass = aSearch.iDeviceClass; + iDeviceAddress = aSearch.iDeviceAddress; + iLastSeen = aSearch.iLastSeen; + iLastUsed = aSearch.iLastUsed; + iCurrentProcessSID = aSearch.iCurrentProcessSID; + iBluetoothName.Set(aSearch.iBluetoothName); + iFriendlyName.Set(aSearch.iFriendlyName); + } + + +/** +Add search criterion for bonded devices +@publishedAll +@released +*/ +EXPORT_C void TBTRegistrySearch::FindBonded() + { + LOG_FUNC + iSearchMask |= EBonded; + } + + +/** +Add search criterion for trusted devices +@publishedAll +@released +*/ +EXPORT_C void TBTRegistrySearch::FindTrusted() + { + LOG_FUNC + iSearchMask |= ETrusted; + } + +/** +Add search criterion to search for specific CoD +@param aClass The CoD to search +@see TBTDeviceClass +@publishedAll +@released +*/ +EXPORT_C void TBTRegistrySearch::FindCoD(const TBTDeviceClass& aClass) + { + LOG_FUNC + iDeviceClass = aClass; + iSearchMask |= ECoD; + } + + +/** +Add search criterion to search for certain classes of device +@param aClass the device class to search for +@param aPref describes the type of device search to perform +@see TBTDeviceClass +@see enum TBTDeviceClassSearch +@publishedAll +@released +*/ +EXPORT_C void TBTRegistrySearch::FindCoD(const TBTDeviceClass& aClass, TBTDeviceClassSearch aPref) + { + LOG_FUNC + iDeviceClass = aClass; + iSearchMask |= (aPref & EMajorDevice ? ECoDMajorDev : 0); + iSearchMask |= (aPref & EMinorDevice ? ECoDMinorDev : 0); + } + +/** +Add search criterion to search for given device +@param aAddress address of device to search for +@publishedAll +@released +*/ +EXPORT_C void TBTRegistrySearch::FindAddress(const TBTDevAddr& aAddress) + { + LOG_FUNC + iDeviceAddress = aAddress; + iSearchMask |= EAddress; + } + + +/** +Add search criterion to search for devices seen since given date +NOTE not currently implemented +@param aLastSeen date from which to find devices +@publishedAll +@released +*/ +EXPORT_C void TBTRegistrySearch::FindSinceSeen(const TTime& aLastSeen) + { + LOG_FUNC + iLastSeen = aLastSeen; + iSearchMask |= ELastSeen; + } + +/** +Add search criterion to search for devices used since given date +@param aLastUsed date from which to find devices +@publishedAll +@released +*/ +EXPORT_C void TBTRegistrySearch::FindSinceUsed(const TTime& aLastUsed) + { + LOG_FUNC + iLastUsed = aLastUsed; + iSearchMask |= ELastUsed; + } + + + +/** +Add search criterion to search for devices with some Bluetooth device name +@param aName device name to search for +@publishedAll +@released +*/ +EXPORT_C void TBTRegistrySearch::FindBluetoothName(const TDesC8& aName) +/** + Add search criteria of specific Bluetooth name +*/ + { + LOG_FUNC + iBluetoothName.Set(aName); + iSearchMask |= EBTName; + } + +/** +Add search criterion to search for devices with some friendly name +@param aName device name to search for +@publishedAll +@released +*/ +EXPORT_C void TBTRegistrySearch::FindFriendlyName(const TDesC& aName) + { + LOG_FUNC + iFriendlyName.Set(aName); + iSearchMask |= EFriendlyName; + } + +/** +Add search criterion to search for finding all devices +@publishedAll +@released +*/ +EXPORT_C void TBTRegistrySearch::FindAll() + { + LOG_FUNC + iSearchMask |= EAll; + } + +/** +Add search criterion to search for devices added by the current process +@publishedAll +@released +*/ +EXPORT_C void TBTRegistrySearch::FindCurrentProcessOwned() + { + LOG_FUNC + iCurrentProcessSID = User::Identity(); + iSearchMask |= EProcess; + } + +/** +Add search criterion to search for devices with a particular UI Cookie value. +@param aUiCookie The particular UI cookie value to search on. +@publishedPartner +@released +*/ +EXPORT_C void TBTRegistrySearch::FindUiCookie(TUint32 aUiCookie) + { + LOG_FUNC + static const TUint32 KAllBitsMasked = 0xffffffff; + FindUiCookie(aUiCookie, KAllBitsMasked); + } + +/** +Add search criterion to search for devices with a particular UI Cookie value. +@param aUiCookie The particular UI cookie value to search on. +@param aUiCookieMask The mask to indicate which bits of the cookie value are to be searched on. +@publishedPartner +@released +*/ +EXPORT_C void TBTRegistrySearch::FindUiCookie(TUint32 aUiCookie, TUint32 aUiCookieMask) + { + LOG_FUNC + iUiCookie = aUiCookie; + iUiCookieMask = aUiCookieMask; + iSearchMask |= EUiCookie; + } + +/** +Assignment operator +@param aSearch the search pattern to which to assign this +@publishedAll +@released +*/ +EXPORT_C TBTRegistrySearch& TBTRegistrySearch::operator=(const TBTRegistrySearch& aSearch) + { + LOG_FUNC + if (this != &aSearch) + { + iSearchMask = aSearch.iSearchMask; + iDeviceClass = aSearch.iDeviceClass; + iDeviceAddress = aSearch.iDeviceAddress; + iLastSeen = aSearch.iLastSeen; + iLastUsed = aSearch.iLastUsed; + iCurrentProcessSID = aSearch.iCurrentProcessSID; + iUiCookie = aSearch.iUiCookie; + iUiCookieMask = aSearch.iUiCookieMask; + iBluetoothName.Set(aSearch.iBluetoothName); + iFriendlyName.Set(aSearch.iFriendlyName); + } + return *this; + } + +