diff -r 000000000000 -r 29b1cd4cb562 bluetooth/btexample/testui/BTTextNotifiers/src/btpantextnotifier.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btexample/testui/BTTextNotifiers/src/btpantextnotifier.cpp Fri Jan 15 08:13:17 2010 +0200 @@ -0,0 +1,527 @@ +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include "BTTextNotifiers.h" +#include +#include +#include + +#ifdef __FLOG_ACTIVE +_LIT8(KLogComponent, "TextNotifiers"); +#endif + +_LIT(KBTPanDeviceSelectionNotifier, "PanDevSlctNotif"); // for panics +_LIT(KBTPanNotifierConsoleName, "PAN device selector"); + +// +// Notifier +// + +CBTPanDeviceSelectionNotifier* CBTPanDeviceSelectionNotifier::NewLC() + { + LOG_STATIC_FUNC + CBTPanDeviceSelectionNotifier* self = new(ELeave) CBTPanDeviceSelectionNotifier(); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +CBTPanDeviceSelectionNotifier::CBTPanDeviceSelectionNotifier() + { + LOG_FUNC + } + +void CBTPanDeviceSelectionNotifier::ConstructL() + { + LOG_FUNC + iEngine = CBTPanDeviceSelectionNotifierEngine::NewL(*this); + } + +CBTPanDeviceSelectionNotifier::~CBTPanDeviceSelectionNotifier() + { + LOG_FUNC + delete iEngine; + } + +void CBTPanDeviceSelectionNotifier::Release() + { + LOG_FUNC + Cancel(); + delete this; + } + +CBTPanDeviceSelectionNotifier::TNotifierInfo CBTPanDeviceSelectionNotifier::RegisterL() + { + LOG_FUNC + iInfo.iUid=KBTPanDeviceSelectionNotifierUid; + iInfo.iChannel=KScreenOutputChannel; + iInfo.iPriority=ENotifierPriorityVLow; + return iInfo; + } + +CBTPanDeviceSelectionNotifier::TNotifierInfo CBTPanDeviceSelectionNotifier::Info() const + { + LOG_FUNC + return iInfo; + } + +TPtrC8 CBTPanDeviceSelectionNotifier::StartL(const TDesC8& /*aBuffer*/) + { + LOG_FUNC + LOG(_L("The synchronous StartL overload is not used.")) + User::Panic(KBTPanDeviceSelectionNotifier, KErrNotSupported); + return KNullDesC8(); // should never be reached + } + +void CBTPanDeviceSelectionNotifier::StartL(const TDesC8& aBuffer, TInt aReplySlot, const RMessagePtr2& aMessage) + { + LOG_FUNC + iReplySlot = aReplySlot; + iMessage = RMessage2(aMessage); + iMessageOutstanding = ETrue; + + TRAPD(err, iEngine->PromptForDevicesL(aBuffer)); + FTRACE(FPrint(_L("RNot\tPAN device selection notifier completed with result %d"), err)); + if (err) + { + aMessage.Complete(err); + iMessageOutstanding = EFalse; + User::Leave(err); + } + } + +void CBTPanDeviceSelectionNotifier::Cancel() + { + LOG_FUNC + iEngine->Stop(); + + if (iMessageOutstanding) + { + iMessage.Complete(KErrCancel); + iMessageOutstanding = EFalse; + } + } + +TPtrC8 CBTPanDeviceSelectionNotifier::UpdateL(const TDesC8& /*aBuffer*/) +/** + +*/ + { + LOG_FUNC + return KNullDesC8(); + } + +void CBTPanDeviceSelectionNotifier::DeviceSelectionComplete(TBTDeviceList& aDevices) +/** +The user has selected the devices they want to connect to +*/ + { + LOG_FUNC + TInt err = iMessage.Write(iReplySlot, aDevices); + iMessage.Complete(err); + iMessageOutstanding = EFalse; + } + +void CBTPanDeviceSelectionNotifier::DeviceSelectionError(TInt aError) +/** +There was an error during device selection +*/ + { + LOG_FUNC + LOG1(_L("\taError = %d"), aError); + if(iMessageOutstanding) + { + iMessage.Complete(aError); + iMessageOutstanding = KErrNone; + } + } + +// +// Notifier engine +// + +_LIT(KNewline, "\n"); +_LIT(KBTPanDSNSelectedDevice, "-> "); +_LIT(KBTPanDSNNotSelectedDevice, " "); +_LIT(KBTPanDSNSelected, " * "); +_LIT(KBTPanDSNNotSelected, " "); +_LIT(KBTPanDSNDevAddrOpen, "["); +_LIT(KBTPanDSNDevAddrClose, "]"); +_LIT(KBTPanDeviceSelectionNotifierInstructions, "Use [up] and [down] arrow keys to move around; press [space] to select a device, press [return] to finish, [esc] to cancel:\nUp to 8 devices can be selected.\n"); +_LIT(KBTPanDSNNoMoreDevices, " --- Device discovery complete ---"); +const TUint KBTPanDSNDevNameMaxChars = 20; +const TUint KBTPanDSNMaxReadableBufLength = 12; +const TUint KBTPanDSNDeviceDisplayBufLength = (sizeof(KBTPanDSNSelected)/2)+KBTPanDSNDevNameMaxChars+(sizeof(KBTPanDSNDevAddrOpen)/2)+KBTPanDSNMaxReadableBufLength+(sizeof(KBTPanDSNDevAddrClose)/2); +const TUint KBTPanDSNInitialDeviceCount = KMaxDeviceRows; // start out by assuming we're going to discover this many devices - will realloc later if necessary +const TUint KBTPanDSNInitialBufSize = ((sizeof(KBTPanDeviceSelectionNotifierInstructions)/2)+(KBTPanDSNInitialDeviceCount*KBTPanDSNDeviceDisplayBufLength)); + +CBTPanDeviceSelectionNotifierEngine* CBTPanDeviceSelectionNotifierEngine::NewL(MBTPanDeviceSelectionNotify& aNotify) +/** + +*/ + { + LOG_STATIC_FUNC + CBTPanDeviceSelectionNotifierEngine* self = new(ELeave) CBTPanDeviceSelectionNotifierEngine(aNotify); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CBTPanDeviceSelectionNotifierEngine::CBTPanDeviceSelectionNotifierEngine(MBTPanDeviceSelectionNotify& aNotify) : + CActive(EPriorityStandard), iDevices(KMaxDeviceRows), iDisplayPtr(NULL, 0), iNotify(aNotify) +/** + +*/ + { + LOG_FUNC + CActiveScheduler::Add(this); + } + +void CBTPanDeviceSelectionNotifierEngine::ConstructL() +/** + +*/ + { + LOG_FUNC + iDisplayBuf = HBufC::NewL(KBTPanDSNInitialBufSize); + iDisplayPtr.Set(iDisplayBuf->Des()); + } + +CBTPanDeviceSelectionNotifierEngine::~CBTPanDeviceSelectionNotifierEngine() +/** + +*/ + { + LOG_FUNC + delete iDeviceDiscoverer; + iDeviceDiscoverer = NULL; + + delete iConsole; + iConsole = NULL; + + delete iDisplayBuf; + iDisplayBuf = NULL; + + iDevices.Close(); + } + +void CBTPanDeviceSelectionNotifierEngine::PromptForDevicesL(const TDesC8& /*aBuffer*/) +/** +Start a device discovery +TODO: Reset state each time this is called +*/ + { + LOG_FUNC + iDeviceDiscoverer = CBTPanDeviceSelectionNotifierDeviceDiscoverer::NewL(*this); + iConsole = Console::NewL(KBTPanNotifierConsoleName, TSize(KConsFullScreen,KConsFullScreen)); + Redraw(); + iDeviceDiscoverer->StartDeviceDiscovery(); + iConsole->Read(iStatus); + SetActive(); + } + +void CBTPanDeviceSelectionNotifierEngine::Stop() +/** +The notifier wants us to abort - stop everything +*/ + { + LOG_FUNC + AbortEverything(); + } + +void CBTPanDeviceSelectionNotifierEngine::RunL() +/** +Got input from the user +*/ + { + LOG_FUNC + TChar key = iConsole->KeyCode(); + switch(key) + { + case EKeyUpArrow: + { + if(iCurrentlySelectedDevice>0) + { + --iCurrentlySelectedDevice; + } + if(iCurrentlySelectedDevice=(iPositionOfTopDeviceInList+KMaxDeviceRows)) + { + ++iPositionOfTopDeviceInList; + } + break; + } + case EKeySpace: + { + if(iDevices.Count()) // make sure there's something in the array + { + if(iDevices[iCurrentlySelectedDevice]->iSelected) + { + iDevices[iCurrentlySelectedDevice]->iSelected = EFalse; + } + else + { + if(NumberOfDevicesSelected()iSelected = ETrue; + } + } + } + break; + } + case EKeyEnter: + { + PackageSelectedDevicesAndCompleteNotifier(); + return; + } + default: + // fall through + case EKeyEscape: + { + CompleteNotifierWithError(KErrCancel); + return; + } + } + + Redraw(); + iConsole->Read(iStatus); // post another read + SetActive(); + } + +void CBTPanDeviceSelectionNotifierEngine::DoCancel() +/** + +*/ + { + LOG_FUNC + iConsole->ReadCancel(); + } + +void CBTPanDeviceSelectionNotifierEngine::NewDeviceFoundL(TNameRecord& aNewDevice) +/** +Add the new device to the end of the list +*/ + { + LOG_FUNC + LOG1(_L("\tDevice Name = %S"), &(aNewDevice.iName)); + TBTDeviceSelectionInfo* devInfo = new(ELeave) TBTDeviceSelectionInfo(); + devInfo->iNameRecord = aNewDevice; + devInfo->iSelected = EFalse; + User::LeaveIfError(iDevices.Append(devInfo)); + + // check if we need to allocate bigger buffer + TUint instructions = sizeof(KBTPanDeviceSelectionNotifierInstructions)/2; + TUint devices = iDevices.Count(); + TUint devDisplay = KBTPanDSNDeviceDisplayBufLength; + TUint minRequiredBufSize = instructions+(devices*devDisplay); + if(iDisplayPtr.MaxLength() < minRequiredBufSize) + { + delete iDisplayBuf; + iDisplayBuf = NULL; + TUint size = (sizeof(KBTPanDeviceSelectionNotifierInstructions)/2)+2*iDevices.Count()*KBTPanDSNDeviceDisplayBufLength; + iDisplayBuf = HBufC::NewL( size ); + iDisplayPtr.Set(iDisplayBuf->Des()); + } + Redraw(); + } + +void CBTPanDeviceSelectionNotifierEngine::DeviceSearchComplete(TInt aError) +/** +No more devices can be found +*/ + { + LOG_FUNC + LOG1(_L("\taError = %d"), aError); + if(aError!=KErrEof) // there's a problem, so complete with an error + { + CompleteNotifierWithError(aError); + return; + } + else + { + iDeviceSearchComplete = ETrue; + Redraw(); + } + } + +TInt CBTPanDeviceSelectionNotifierEngine::DisplayDevice(TUint aDeviceNumber, TPtr& aDisplayBuf) +/** + +*/ + { + LOG_FUNC + //ASSERT(aDisplayBuf.Length()==KBTPanDSNDeviceDisplayBufLength); + if(aDeviceNumber>=iDevices.Count()) + { + return KErrNotFound; + } + else + { + if(iDevices[aDeviceNumber]->iSelected) + { + aDisplayBuf.Append(KBTPanDSNSelected); + } + else + { + aDisplayBuf.Append(KBTPanDSNNotSelected); + } + + aDisplayBuf.Append(iDevices[aDeviceNumber]->iNameRecord.iName.Left(KBTPanDSNDevNameMaxChars)); // append device name + aDisplayBuf.Append(KBTPanDSNDevAddrOpen); + TBuf readableDevAddrBuf; + static_cast(iDevices[aDeviceNumber]->iNameRecord.iAddr).BTAddr().GetReadable(readableDevAddrBuf); // append device address + aDisplayBuf.Append(readableDevAddrBuf); + aDisplayBuf.Append(KBTPanDSNDevAddrClose); + return KErrNone; + } + } + +void CBTPanDeviceSelectionNotifierEngine::DisplayInstructions(TPtr& aDisplayBuf) +/** +~130 chars +*/ + { + LOG_FUNC + aDisplayBuf.Append(KBTPanDeviceSelectionNotifierInstructions); + } + +void CBTPanDeviceSelectionNotifierEngine::Redraw() +/** +Redraw the console +*/ + { + LOG_FUNC + iDisplayPtr.Zero(); + iConsole->ClearScreen(); + + TInt err; + DisplayInstructions(iDisplayPtr); + for(TInt i = 0; i < KMaxDeviceRows; ++i) + { + if(iPositionOfTopDeviceInList+i==iCurrentlySelectedDevice) + { + iDisplayPtr.Append(KBTPanDSNSelectedDevice); + } + else + { + iDisplayPtr.Append(KBTPanDSNNotSelectedDevice); + } + + err = DisplayDevice(iPositionOfTopDeviceInList+i, iDisplayPtr); + if(err==KErrNotFound) // no more devices left + { + break; + } + iDisplayPtr.Append(KNewline); + } + + if(iDeviceSearchComplete) + { + iDisplayPtr.Append(KBTPanDSNNoMoreDevices); + } + + iConsole->Write(*iDisplayBuf); + } + +void CBTPanDeviceSelectionNotifierEngine::PackageSelectedDevicesAndCompleteNotifier() +/** +Package the selected device addresses into the device list and pass back to the notifier +*/ + { + LOG_FUNC + AbortEverything(); // stop inquiry and remove console + + TBTDeviceList deviceList; + for(TInt i = 0; i < iDevices.Count(); ++i) + { + if(iDevices[i]->iSelected) + { + TBTDevAddr devAddr = static_cast(iDevices[i]->iNameRecord.iAddr).BTAddr(); + deviceList.AddDevice(devAddr); + } + } + + iNotify.DeviceSelectionComplete(deviceList); + } + +void CBTPanDeviceSelectionNotifierEngine::CompleteNotifierWithError(TInt aError) +/** +An error occurred during device selection - cancel everything and complete the notifier with an error +*/ + { + LOG_FUNC + if(iAborting) + { + // do nothing, we're already aborting everything + } + else + { + iAborting = ETrue; // make a note that we're aborting + AbortEverything(); + iNotify.DeviceSelectionError(aError); + iAborting = EFalse; // reset flag + } + } + +void CBTPanDeviceSelectionNotifierEngine::AbortEverything() +/** +Common method to abort everything - called from both the notifier error path and our own +*/ + { + LOG_FUNC + if(iDeviceDiscoverer) + { + iDeviceDiscoverer->Cancel(); // cancel the device discovery, and delete the device discoverer + delete iDeviceDiscoverer; + iDeviceDiscoverer = NULL; + } + + Cancel(); // cancel the input from the console + if(iConsole) + { + delete iConsole; // remove the console from screen + iConsole = NULL; + } + } + +TInt CBTPanDeviceSelectionNotifierEngine::NumberOfDevicesSelected() +/** +Return the number of devices marked as selected in the array +*/ + { + LOG_FUNC + TInt count = 0; + for(TInt i=0; i < iDevices.Count(); ++i) + { + if(iDevices[i]->iSelected) + { + ++count; + } + } + return count; + } +