diff -r 000000000000 -r 29b1cd4cb562 bluetooth/btexample/testui/BTTextNotifiers/src/BTManDeviceScanner.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btexample/testui/BTTextNotifiers/src/BTManDeviceScanner.cpp Fri Jan 15 08:13:17 2010 +0200 @@ -0,0 +1,533 @@ +// Copyright (c) 2000-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 +#include +#include +#include +#include + +#ifdef __FLOG_ACTIVE +_LIT8(KLogComponent, "TextNotifiers"); +#endif + +void CBTManDeviceScanner::NotifyErrorL(TRefByValue aErrorNotification) + { + LOG_FUNC + CConsoleBase* console = BTTextNotifiersConsole::AutoSizeNewL(_L("Device Selector"), TSize(50,2)); + CleanupStack::PushL(console); + console->Printf(aErrorNotification); + console->Printf(_L("\nPress any key to continue")); + console->Getch(); + CleanupStack::PopAndDestroy(); + } + +void CBTManDeviceScanner::ResetDeviceLists() + { + LOG_FUNC + iDevices.ResetAndDestroy(); + iDevices.Close(); + + iNoNameDevices.ResetAndDestroy(); + iNoNameDevices.Close(); + } + + +void CBTManDeviceScanner::EnsureConsoleExistsL() + { + LOG_FUNC + if(!iConsole) + { + StopWaitMessage(); + iConsole = BTTextNotifiersConsole::AutoSizeNewL(_L("Device Selector"), TSize(70, 6+KMaxDeviceRows)); + iConsole->Printf(iWaitMessage); + } + } + +void CBTManDeviceScanner::StartWaitMessageL() + { + LOG_FUNC + delete iWaitConsole; + iWaitConsole = 0; + iWaitConsole = BTTextNotifiersConsole::AutoSizeNewL(_L("Device Selector"), TSize(20,1)); + iWaitConsole->Printf(iWaitMessage); + } + +void CBTManDeviceScanner::StopWaitMessage() + { + LOG_FUNC + delete iWaitConsole; + iWaitConsole = 0; + } + +void CBTManDeviceScanner::AddDiscoveredDeviceL(RBTDevices& aDeviceArray, const TNameEntry& aNameEntry) + { + LOG_FUNC + TInquirySockAddr& sa = TInquirySockAddr::Cast(aNameEntry().iAddr); + const TBTDevAddr& bdaddr = sa.BTAddr(); + CBTDevice* device = CBTDevice::NewL(bdaddr); + CleanupStack::PushL(device); + + HBufC8* temp = HBufC8::NewLC(aNameEntry().iName.Length()); // to convert iName to narrow + TPtr8 ptr=temp->Des(); + ptr.Copy(aNameEntry().iName); + + device->SetDeviceNameL(*temp); + TBTDeviceClass devClass(sa.MajorServiceClass(), + sa.MajorClassOfDevice(), + sa.MinorClassOfDevice()); + device->SetDeviceClass(devClass); + User::LeaveIfError(aDeviceArray.Append(device)); + + CleanupStack::PopAndDestroy(1, temp); + CleanupStack::Pop(device); + } + +void CBTManDeviceScanner::SetupDeviceParams(RHostResolver aHr, TBTNamelessDevice& aDevInfo) + { + LOG_FUNC + SetupDeviceParams(_L(""), aDevInfo); + //iDevPms.SetDeviceAddress(aDevInfo.Addr()); + //iDevPms.SetDeviceClass(aDevInfo.Class()); + TInquirySockAddr addr; + addr.SetIAC(KGIAC); + TRequestStatus stat; + addr.SetAction(KHostResName); + addr.SetBTAddr(aDevInfo.Address()); + TNameEntry entry; + aHr.GetByAddress(addr, entry, stat); + User::WaitForRequest(stat); + if (stat == KErrNone) + { + iDevPms.SetDeviceName(entry().iName); + } + } + +void CBTManDeviceScanner::SetupDeviceParams(const THostName& aName, TBTNamelessDevice& aDevInfo) + { + LOG_FUNC + iDevPms.SetDeviceAddress(aDevInfo.Address()); + iDevPms.SetDeviceClass(aDevInfo.DeviceClass()); + iDevPms.SetDeviceName(aName); + } + +void CBTManDeviceScanner::RubOutWaitMessage() + { + LOG_FUNC + TBuf<1> character; + if(iConsole->WhereX()||iConsole->WhereY()) + { + TInt len = iWaitMessage.Length(); + for(TInt i=0;iPrintf(_L("%S"),&character); + } + } + } + +void CBTManDeviceScanner::PrintDiscoveredDevice() + { + LOG_FUNC + + RubOutWaitMessage(); + + const TBTDevAddr& bdaddr = iDevPms.BDAddr(); + iConsole->Printf(_L("%d.\t0x%02x%02x%02x%02x%02x%02x\t"), + ++iPrintedCounter,bdaddr[0],bdaddr[1],bdaddr[2],bdaddr[3], + bdaddr[4],bdaddr[5]); + if(!(iDevPms.DeviceName().Length())) + iConsole->Printf(_L("(No name found)\t")); + else + { + // need to widen it for displaying! just display 40 chars worth + TBuf<40> dispBuf; + dispBuf.Copy(iDevPms.DeviceName().Left(40)); + iConsole->Printf(_L("\"%S\"\t"), &dispBuf); + } + iConsole->Printf(_L("0x%04x-"),iDevPms.DeviceClass().MajorServiceClass()); + iConsole->Printf(_L("%02x-"),iDevPms.DeviceClass().MajorDeviceClass()); + iConsole->Printf(_L("%02x\n"),iDevPms.DeviceClass().MinorDeviceClass()); + iConsole->Printf(iWaitMessage); + } + +TBool CBTManDeviceScanner::DeviceNumberFromUserL(TBool allowMore) + { + LOG_FUNC + TBuf<3> numBuf; + TBuf<63> errStr; + errStr.SetLength(0); + numBuf.Zero(); + TKeyCode code; + TBuf<1> character; + + RubOutWaitMessage(); + + TBuf<0x100> prompt(_L("\nIf the device you require appears above,\n\ + \rselect the device number you require and THEN press 'Return'.\n\ + \rIf not, ")); + if(allowMore) + { + prompt.SetLength(prompt.Length()-2); + prompt.Append(_L("\npress 'Esc' to abort or 'Return' to seek more devices.\n")); + iConsole->Printf(prompt); + } + else + { + prompt.SetLength(prompt.Length()-2); + prompt.Append(_L(" - THERE ARE NO MORE DEVICES - so\n\ + \rpress 'Esc' to abort or 'Return' to ***REDO*** device inquiry.\n")); + iConsole->Printf(prompt); + } + FOREVER + { + code = iConsole->Getch(); + if(!(numBuf.Length())&&code==EKeyEnter) + { + // No device number entered so this must be a redo device inquiry + iScanState = EScanStateUnfinished; + break; + } + if(!(numBuf.Length())&&code==EKeyBackspace) + { + // No device number entered so nothing to delete, just continue looking for input + continue; + } + if(!(code>=0x30&&code<=0x39)&&code!=EKeyEscape&&code!=EKeyEnter&&code!=EKeyBackspace) + { + // Not a valid number and not escape, enter or backspace, just continue looking for input + continue; + } + if(code==EKeyEscape) + { + // Escape is always abort regardless if a number has been entered + iScanState = EScanStateCancelled; + break; + } + character.SetLength(0); + character.Append(code); + + if (code == EKeyEnter) + { + // We must have a number at this point otherwise the enter key would have forced a + // redo inquiry above + TLex lex(numBuf); + TInt err = lex.Val(iChosenDeviceIndex, EDecimal); + User::LeaveIfError(err); + if(iChosenDeviceIndex<=iPrintedCounter&& + iChosenDeviceIndex>=((iPrintedCounter-1)/KMaxDeviceRows)*KMaxDeviceRows+1) + { + iScanState = EScanStateSelected; + break; + } + else + { + while((numBuf.Length() != 0)) + { + character.SetLength(0); + character.Append(EKeyBackspace); + iConsole->Printf(_L("%S"),&character); + numBuf.SetLength((numBuf.Length()-1)); + } + while((errStr.Length() != 0)) + { + character.SetLength(0); + character.Append(EKeyBackspace); + iConsole->Printf(_L("%S"),&character); + errStr.SetLength((errStr.Length()-1)); + } + errStr.Format(_L("Device %d does not exist! Please re-enter...."), iChosenDeviceIndex); + iConsole->Printf(_L("%S"), &errStr); + } + } + else if (code == EKeyBackspace) + { + // We must have a number at this point otherwise we would have asked for another key press + // above + iConsole->Printf(_L("%S"),&character); + numBuf.SetLength((numBuf.Length()-1)); + } + else + { + if (numBuf.Length() < numBuf.MaxLength()) + { + // Store the number + iConsole->Printf(_L("%S"),&character); + numBuf.Append(code); + } + } + } + + delete iConsole; + iConsole = 0; + + //return FALSE if scan not terminated (by cancelation or selection) + if(iScanState == EScanStateUnfinished) + { + StartWaitMessageL(); + return EFalse; + } + return ETrue; + } + +TBool CBTManDeviceScanner::GetByScanL(TBTDevAddr& aBDAddr, + TBTDeviceName& aName, + TBTDeviceClass& aClass) + { + LOG_FUNC + StartWaitMessageL(); + RSocketServ ss; + TInt ret=ss.Connect(); + if(ret) + { + NotifyErrorL(_L("Internal error: unable to connect to outside socket.")); + return EFalse; + } + + RHostResolver hr; + + TProtocolDesc pInfo; + // List out all the protocols + ret=ss.FindProtocol(_L("BTLinkManager"),pInfo); + if(ret) + { + NotifyErrorL(_L("Internal error: unable to find Bluetooth.")); + ss.Close(); + return EFalse; + } + + ret = hr.Open(ss,pInfo.iAddrFamily,pInfo.iProtocol); + //ret = hr.Open(ss,KBTAddrFamily,KBTLinkManager); + if(ret) + { + NotifyErrorL(_L("Internal error: unable to find Bluetooth.")); + ss.Close(); + return EFalse; + } + + iScanState = EScanStateUnfinished; + while(iScanState==EScanStateUnfinished) + { + iResultCountNoName = 0; + iResultCountWithName = 0; + iChosenDeviceIndex = 0; + iPrintedCounter = 0; + ResetDeviceLists(); + + TInquirySockAddr addr; + addr.SetIAC(KGIAC); + TRequestStatus stat; + addr.SetAction(KHostResInquiry + KHostResName); // Default: Both + TNameEntry entry; + + hr.GetByAddress(addr, entry, stat); + User::WaitForRequest(stat); + + //Collect surrounding devices in a device array + iPrintedCounter = 0; + while (stat == KErrNone) + { + if(entry().iName.Length()) + { + EnsureConsoleExistsL(); + AddDiscoveredDeviceL(iDevices, entry); + SetupDeviceParams(entry().iName, (*iDevices[iResultCountWithName]).AsNamelessDevice()); + PrintDiscoveredDevice(); + iResultCountWithName++; + if(!(iPrintedCounter%KMaxDeviceRows)) + if(CBTManDeviceScanner::DeviceNumberFromUserL(ETrue)) + break; + } + else + { + // Don't add to the Devices list yet, add to a separate list for those + // who's name needs to be host resolve-d. + TNameEntry* copied = new(ELeave) TNameEntry(); + CleanupStack::PushL(copied); + + (*copied)().iName = entry().iName; // should be 0 length + (*copied)().iAddr = entry().iAddr; + (*copied)().iFlags = entry().iFlags; + + User::LeaveIfError(iNoNameDevices.Append(copied)); + CleanupStack::Pop(copied); + iResultCountNoName++; + } + if(iResultCountNoName+iResultCountWithName==999) + { + EnsureConsoleExistsL(); + if(CBTManDeviceScanner::DeviceNumberFromUserL(EFalse)) + //=>User has requested to see more devices + { + iScanState = EScanStateCancelled;//ensure do not search on unnamed devices + DisplayNoDeviceMessageL(ETrue); + } + break; + } + hr.Next(entry, stat); + User::WaitForRequest(stat); + } + + addr.SetAction( KHostResName ); + while(iResultCountNoName && iScanState==EScanStateUnfinished && + iPrintedCounter<(iResultCountWithName+iResultCountNoName)) + { + EnsureConsoleExistsL(); + //Should never happen.... + if(iPrintedCounter prompt(_L("Sorry! No")); + if(isMore) + prompt.Append(_L(" more")); + prompt.Append(_L(" devices could be found.\n\nPress any key.")); + console->Printf(prompt); + console->Getch(); + CleanupStack::PopAndDestroy();//console + } + + +void CBTManDeviceScanner::CheckUnfinishedL() + { + LOG_FUNC + if(iScanState!=EScanStateUnfinished|| + (iResultCountWithName+iResultCountNoName)%KMaxDeviceRows) + return; + + CConsoleBase* console = 0; + TRAPD(err, console = BTTextNotifiersConsole::AutoSizeNewL(_L("Device Selection"), TSize(70,3))); + if(err) + return; + CleanupStack::PushL(console); + + TBuf<0x100> prompt(_L("Sorry!")); + prompt.Append(_L(" - THERE ARE NO MORE DEVICES - so\n\ + \rpress 'Esc' to abort or 'Return' to ***REDO*** device inquiry.\n")); + console->Printf(prompt); + TKeyCode code = console->Getch(); + while(code!=0x1b&&code!=0x0d) + code = console->Getch(); + iScanState = code==0x0d?EScanStateUnfinished:EScanStateCancelled; + CleanupStack::PopAndDestroy();//console + } + + + +CBTManDeviceScanner* CBTManDeviceScanner::NewL() + { + LOG_STATIC_FUNC + CBTManDeviceScanner* self=new (ELeave) CBTManDeviceScanner(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +CBTManDeviceScanner::~CBTManDeviceScanner() + { + LOG_FUNC + delete iConsole; + ResetDeviceLists(); + iDevices.Close(); + iNoNameDevices.Close(); + } + +CBTManDeviceScanner::CBTManDeviceScanner() + : iWaitMessage(_L("Please wait...")) + { + LOG_FUNC + } + +void CBTManDeviceScanner::ConstructL() + { + LOG_FUNC + } + + + +