void CSocketEngine::DnsComplete(){ iNameRecord=iNameEntry(); iAddr.SetAddress(TInetAddr::Cast(iNameRecord.iAddr).Address()); iSocket.Connect(iAddr,iStatus); //在发起连接时,务必先转换iHostName: Domin:port为Ip:port SetStatus(EConnecting); iDownloading=ETrue; SetActive(); }
void CJavaDebugAgentConnector::RunL() { TInt err = iStatus.Int(); switch (iState) { case EStarting: if (err == KErrNone) { DoResolveL(); } else { iState = EFailed; LOG1("Connection error %d",err); iDriver->ConnectionFailed(); } break; case EResolving: if (err == KErrNone) { iAddress = iNameEntry().iAddr; DoConnectL(); } else { iState = EFailed; LOG1("Host name resolution error %d",err); iDriver->ConnectionFailed(); } break; case EConnecting: if (err == KErrNone) { iState = EConnected; // The ProcessRequest() call transfers ownership of the // CTcpServerHandler object to the driver in a rather // obscure way... Clear the pointer so that we don't // deallocate it twice. CTcpServerHandler* handler = iHandler; iHandler = NULL; handler->ProcessRequest(); } else { iState = EFailed; LOG1("Connection failed, error %d",err); iDriver->ConnectionFailed(); } break; } }
void CDnsResolver::Resolve(const TDesC& aHostName) { if (IsActive()) { User::Invariant(); return; } _LIT(KLocalHostName, "localhost"); if (aHostName == KLocalHostName) { const TUint32 KLocalIpAddr = INET_ADDR(127,0,0,1); TInetAddr localIpAddr; localIpAddr.SetAddress(KLocalIpAddr); iNameEntry().iAddr = localIpAddr; // copy iStatus = KRequestPending; SetActive(); TRequestStatus* status = &iStatus; User::RequestComplete(status, KErrNone); return; } // ensure that we have a resolver session we can use if (!IS_SUBSESSION_OPEN(iHostResolver)) { TInt error; if (iConnection) { error = iHostResolver.Open(iSocketServ, KAfInet, KProtocolInetUdp, *iConnection); } else { error = iHostResolver.Open(iSocketServ, KAfInet, KProtocolInetUdp); } if (error != KErrNone && error != KErrAlreadyExists) { iStatus = KRequestPending; SetActive(); TRequestStatus* status = &iStatus; User::RequestComplete(status, error); return; } } SET_SESSION_OPEN(iHostResolver); iHostResolver.GetByName(aHostName, iNameEntry, iStatus); SetActive(); }
void CFTPResolver::SetAddress(TInetAddr& aAddress) { // Get the 1st entry resolved iNameRecord = iNameEntry(); // Save the address (take care not to overwrite the port, might have been already set) if (TInetAddr::Cast(iNameRecord.iAddr).Family() == KAfInet) aAddress.SetAddress(TInetAddr::Cast(iNameRecord.iAddr).Address()); else aAddress.SetAddress(TInetAddr::Cast(iNameRecord.iAddr).Ip6Address()); #if defined(__FTPPROTDEBUG__) TBuf<512> debugBuffer; // A Buffer to output the resolved IP aAddress.Output(debugBuffer); debugBuffer.Append(_L(",")); debugBuffer.AppendNum(aAddress.Port(), EDecimal); debugBuffer.Append(_L("\n")); #endif FTPPROTDEBUG(_DBGResolver,_L("Resolved address is:")); FTPPROTDEBUG(_DBGResolver,debugBuffer); }
void CNtp::RunL(void) { TBool stop=ETrue; switch(iNtpState) { case ELookingUp: if(iStatus==KErrNone) { iAddress.SetPort(iPort); iAddress.SetAddress(TInetAddr::Cast(iNameEntry().iAddr).Address()); iSendBuffer.SetLength(0); iSendBuffer.Append((KNtpVersion<<3)|KNtpModeClient); for(TInt i=1;i<KNtpPacketMin;i++) iSendBuffer.Append(0); iSocket.SendTo(iSendBuffer,iAddress,0,iStatus); iNtpState=ESending; SetActive(); stop=EFalse; } break; case ESending: if(iStatus==KErrNone) { iSendStamp.HomeTime(); iSocket.RecvFrom(iReceiveBuffer,iAddress,0,iStatus); iNtpState=EReceiving; SetActive(); stop=EFalse; } break; case EReceiving: if(iStatus==KErrNone&&iReceiveBuffer.Length()>=KNtpPacketMin) { iReceiveStamp.HomeTime(); TInt status=(iReceiveBuffer[0]>>6)&KNtpStatusAlarm,mode=(iReceiveBuffer[0]&0x07); if(status||mode!=KNtpModeServer) { if(!status) status=KNtpModeServer; iStatus=KNtpErrorBase-status; } else { TInt64 stamp(0),base(0xd504a2,0xc672e000); for(TInt i=0;i<4;i++) { stamp=stamp*256+(TUint)iReceiveBuffer[i+32]; } stamp=stamp*1000000+base; iNewStamp=stamp; iNewStamp+=iTimeOffset; iNewStamp+=iCorrection; TTimeIntervalSeconds way; if(iReceiveStamp.SecondsFrom(iSendStamp,way)==KErrNone) { way=way.Int()/2; iNewStamp+=way; } User::SetHomeTime(iNewStamp); } } break; default: User::Invariant(); break; }
void CDnsResolver::GetResult(TSockAddr& aResult) const { TNameRecord record = iNameEntry(); TSockAddr& addr = record.iAddr; aResult = addr; // copy }
void CAzqBtGPSReader::RunL() { iCallbackTimer->Cancel(); switch(iState) { case ENoState: break; case EInquiringDevices: { if( iStatus !=KErrNone) { iHostResolver.Close(); if(iStatus == KErrHostResNoMoreResults) { { iGPSData.Reset(); _LIT(KGPSStateUpdate,"BT GPS Search finished..."); iObserver.OnGPSStateUpdate(KGPSStateUpdate,iGPSData ); } //choose and connect to BT GPS modules if(iBtGPSArray.Count()>0) { User::LeaveIfError(iSendingSocket.Open(iSocketServer,RFCOMM)); TBTSockAddr address; address.SetBTAddr(iBtGPSArray[0]); // GPS devices usually use port 1 as data channel // so we don't have to query it address.SetPort(1); { iGPSData.Reset(); iState = EConnecting; _LIT(KGPSStateUpdate,"Trying to connect to first device"); iObserver.OnGPSStateUpdate(KGPSStateUpdate,iGPSData ); } iSendingSocket.Connect(address, iStatus); SetActive(); ResetBtTimer(); } else { { iGPSData.Reset(); iState = ENoState; _LIT(KGPSStateUpdate,"No BT GPS. Retry press 9"); iObserver.OnGPSStateUpdate(KGPSStateUpdate,iGPSData ); } } } else { { iGPSData.Reset(); iState = ENoState; _LIT(KGPSStateUpdate,"Search failed. Retry press 9"); iObserver.OnGPSStateUpdate(KGPSStateUpdate,iGPSData ); } } } else { TInquirySockAddr &addr = TInquirySockAddr::Cast(iNameEntry().iAddr); if(addr.MajorClassOfDevice() == KBtGPSMajorClass) { //add to array... iBtGPSArray.AppendL(addr.BTAddr()); { iGPSData.Reset(); _LIT(KGPSStateUpdate,"Found %d BT GPS, Searching..."); TBuf<128> buf; buf.Format(KGPSStateUpdate, iBtGPSArray.Count()); iObserver.OnGPSStateUpdate(buf,iGPSData ); } } ///////////get next device iState = EInquiringDevices; iHostResolver.Next(iNameEntry, iStatus); SetActive(); ResetBtTimer(); /////////////////////////////////// } } break; case EConnecting: { if( iStatus !=KErrNone) { //remove previous device from array if(iBtGPSArray.Count()>0) { iBtGPSArray.Remove(0); } //if more gps devices remaining to try if(iBtGPSArray.Count()>0) { //socket alraedy opened... TBTSockAddr address; address.SetBTAddr(iBtGPSArray[0]); // GPS devices usually use port 1 as data channel // so we don't have to query it address.SetPort(1); iState = EConnecting; { iGPSData.Reset(); _LIT(KGPSStateUpdate,"Connecting next device"); iObserver.OnGPSStateUpdate(KGPSStateUpdate,iGPSData ); } iSendingSocket.Connect(address, iStatus); SetActive(); ResetBtTimer(); } else//finished list { { iGPSData.Reset(); iState = ENoState; _LIT(KGPSStateUpdate,"Connect GPS failed. Retry press 9"); iObserver.OnGPSStateUpdate(KGPSStateUpdate,iGPSData ); } iSendingSocket.Close(); } } else { iState = EReading; { _LIT(KGPSStateUpdate,"Reading GPS data..."); iObserver.OnGPSStateUpdate(KGPSStateUpdate,iGPSData ); } iWaitGPSReadyRetry = 0; //only related if iSyncTimeWhenValid is ETrue line.Zero(); iLineHeadReceivedTime = 0;//just to make sure it's fresh iSendingSocket.RecvOneOrMore(data, 0, iStatus, iReadDataLength); SetActive(); ResetBtTimer(); } } break; case EReading: { if( iStatus !=KErrNone) { { iGPSData.Reset(); iState = ENoState; _LIT(KGPSStateUpdate,"Read GPS failed. Retry press 9"); iObserver.OnGPSStateUpdate(KGPSStateUpdate,iGPSData ); } iSendingSocket.Close(); return; } iState = EReadComplete; iGPSData.Reset();//prepare for new data int rpos = 0; while ((rpos = data.Locate('\r')) != KErrNotFound) { TPtrC8 leftr(0,0); leftr.Set(data.Left(rpos)); TInt leftrlen = leftr.Length(); if(leftrlen + line.Length() < line.MaxLength()) { if(line.Length()==0) iLineHeadReceivedTime.HomeTime(); line.Append(leftr); } else { line.Zero(); if(leftrlen + line.Length() < line.MaxLength()) { //if(line.Length()==0) sure it is, see above lines iLineHeadReceivedTime.HomeTime(); line.Append(leftr); } } if(rpos+1<data.Length()) { data.Copy(data.Mid(rpos+1)); if(data[0] == '\n') data.Delete(0,1); } else { data.Zero(); } TGPSData gpsdata; TTimeIntervalMicroSeconds proctime; if(iLineHeadReceivedTime == TTime(0))//just in case... { iLineHeadReceivedTime.HomeTime(); CAknWarningNote* informationNote = new (ELeave) CAknWarningNote(ETrue); //informationNote->SetTimeout(CAknNoteDialog::EShortTimeout); _LIT(KConfirmText,"Warning: No read-offset time correction"); informationNote->ExecuteLD(KConfirmText); } if(gpsdata.ParseGPSInput(line,iLineHeadReceivedTime,proctime)) { if((gpsdata.POS_STAT.Length() == 0) || (gpsdata.POS_STAT.Length()>0 && gpsdata.POS_STAT[0]!='A'))//if data NOT valid { ///////////////BEGIN parsed but NOT valid data if(iSyncTimeWhenValid)//if the NetMonview is in the "Awaiting Fresh GPS Params State for the first time of session - needs time sync" { if(iWaitGPSReadyRetry>=KMaxWaitGPSReadyRetries) { //max retries finished, notify as in EReadcomplete state as set by above _LIT(KGPSStateUpdate,"GPS Connected but Not Ready"); iObserver.OnGPSStateUpdate(KGPSStateUpdate,iGPSData ); iSyncTimeWhenValid = EFalse; } else { //don't notify as in EReadcomplete state yet... iState = EReading; iWaitGPSReadyRetry++; TBuf<64> buf; _LIT(KGPSStateUpdateFormat,"GPS NotReady: TimeSync retry %d/%d"); buf.Format(KGPSStateUpdateFormat,iWaitGPSReadyRetry,KMaxWaitGPSReadyRetries); iObserver.OnGPSStateUpdate(buf,iGPSData ); } } else { _LIT(KGPSStateUpdate,"GPS Connected but Not Ready"); iObserver.OnGPSStateUpdate(KGPSStateUpdate,iGPSData ); } //latdeg = londeg = latmin = lonmin = latsec = lonsec = 0; line.Zero(); if(data.Length()>0) { if(line.Length() + data.Length() < line.MaxLength()) { iLineHeadReceivedTime.HomeTime(); line.Append(data); } else { line.Zero(); if(line.Length() + data.Length() < line.MaxLength()) { //line is zero len from line.Zero() above iLineHeadReceivedTime.HomeTime(); line.Append(data); } } } data.Zero(); iState = EReading; iSendingSocket.RecvOneOrMore(data, 0, iStatus, iReadDataLength); SetActive(); ResetBtTimer(); return; ///////////////END not valid } ////////// boyond here is the VALID case ////////////set device's UTC time if(iSyncTimeWhenValid) { TTime devTime; devTime.HomeTime(); TDateTime dt = devTime.DateTime(); if(gpsdata.POS_UTC.Length() < 6 || gpsdata.DATE.Length() < 6) { //line not ready/full... do nothing } else { //All NMEA chars are ASCII dt.SetHour((gpsdata.POS_UTC[0]-48)*10+(gpsdata.POS_UTC[1]-48)); dt.SetMinute((gpsdata.POS_UTC[2]-48)*10+(gpsdata.POS_UTC[3]-48)); dt.SetSecond((gpsdata.POS_UTC[4]-48)*10+(gpsdata.POS_UTC[5]-48)); dt.SetDay((gpsdata.DATE[0]-48)*10+(gpsdata.DATE[1]-48) -1); dt.SetMonth(TMonth((gpsdata.DATE[2]-48)*10+(gpsdata.DATE[3]-48) -1)); dt.SetYear((gpsdata.DATE[4]-48)*10+(gpsdata.DATE[5]-48)+KY2K); if(gpsdata.POS_UTC.Length()>9 && gpsdata.POS_UTC.Find(_L8("."))>0) { dt.SetMicroSecond((gpsdata.POS_UTC[7]-48)*KONEHUNDREDTHOUSAND+(gpsdata.POS_UTC[8]-48)*KTENTHOUSAND+(gpsdata.POS_UTC[9]-48)*1000); } devTime = dt; devTime += proctime; #ifdef EKA2 User::SetUTCTime(devTime); #else //TODO: detect timezone and add accordingly TTime hometime(devTime); hometime += TTimeIntervalHours(7); User::SetHomeTime(hometime); #endif iSyncTimeWhenValid = EFalse; CAknConfirmationNote* informationNote = new (ELeave) CAknConfirmationNote(EFalse); //informationNote->SetTimeout(CAknNoteDialog::EShortTimeout); _LIT(KConfirmText,"GPS TimeSync Successful"); informationNote->ExecuteLD(KConfirmText); //TODO: report to scheduler that device time has changed? OR let scheduler detect device time change? } } ///////////////////////// //SET LAT LON values... TBuf<1> ref; if(gpsdata.LAT.Length() < iGPSData.iLat.MaxLength() && gpsdata.LAT_REF.Length()==1) { iGPSData.iLat.Copy(gpsdata.LAT); ref.Zero(); ref.Copy(gpsdata.LAT_REF); iGPSData.iLat+=ref; } if(gpsdata.LON.Length() < iGPSData.iLon.MaxLength() && gpsdata.LON_REF.Length()==1) { iGPSData.iLon.Copy(gpsdata.LON); ref.Zero(); ref.Copy(gpsdata.LON_REF); iGPSData.iLon+=ref; } _LIT(KGPSStateUpdate,"Connected to GPS"); iObserver.OnGPSStateUpdate(KGPSStateUpdate,iGPSData ); }//END if gps parsed line.Zero(); } if(data.Length()>0) { if(line.Length() + data.Length() < line.MaxLength()) { if(line.Length()==0) //if not appending data to previous line iLineHeadReceivedTime.HomeTime(); line.Append(data); } else { line.Zero(); if(line.Length() + data.Length() < line.MaxLength()) { //if(line.Length()==0) sure it is, see above lines iLineHeadReceivedTime.HomeTime(); line.Append(data); } } } data.Zero(); iState = EReading; iSendingSocket.RecvOneOrMore(data, 0, iStatus, iReadDataLength); SetActive(); ResetBtTimer(); } break; } }
void CTcpSymbianEngine::RunL() { DBG("RunL, EngineState: %d, iStatus: %d", EngineState(), iStatus.Int()); iTimer->Cancel(); // Cancel TimeOut timer before handling completion switch(EngineState()){ case EConnecting: // IP connection request if (iStatus == KErrNone){ DBG("Connection completed Ok"); // Connection completed sucessfully iConsole.ConnectionNotify(isab::Module::CONNECTED, isab::Module::REQUESTED); SetEngineState(EConnected); Read(); //Start CTcpSymbianRead Active object } else { WARN("Unable to connect, removing host from cache."); iDNSCache.Remove(*iHostName); if (iStatus == KErrCouldNotConnect){ ResetL(EConnectFailed, isab::Module::NO_RESPONSE); } else if (iStatus == KErrTimedOut) { ResetL(ETimedOut, isab::Module::NO_RESPONSE); } else{ WARN("EConnectFailed, INTERNAL_ERROR"); ResetL(EConnectFailed, isab::Module::INTERNAL_ERROR); //XXX handle the different cases } } break; case ELookingUp: iResolver.Close(); if (iStatus == KErrNone) { DBG("Name lookup ok"); // DNS look up successful // Extract domain name and IP address from name record class TInetAddr addr = TInetAddr::Cast(iNameEntry().iAddr); //cache the ip for later. TInt cacheStat = iDNSCache.CacheHost(*iHostName, addr.Address()); DBG("Host cached with result %d", cacheStat); cacheStat = cacheStat; // And connect to the IP address Connect(addr.Address(), iPort); //setactive here } else { //includes KErrTimedOut WARN("Lookup failed"); ResetL(ELookUpFailed, isab::Module::LOOKUP_FAILED); } break; case ELinking: if(iStatus == KErrNone){ DBG("Link layer setup ok"); OpenSocketL(); //cannot open socket until here. We need RConnection. StartLookupL(); //setactive here } else { //includes KErrCanceled and KErrTimedOut WARN("Link layer setup failed"); ResetL(ELinkFailed, isab::Module::TRANSPORT_FAILED); } break; case EBroken: DBG("Broken"); ResetL( EngineState(), isab::Module::CHANNEL_FAILED ); break; case EClosing: if(iStatus == KErrNone){ DBG("Closing ok"); ResetL(EComplete, isab::Module::REQUESTED); } else if(iStatus == KErrTimedOut){ ResetL(ETimedOut); } else { ResetL(EngineState()); //XXX ??? } break; case ESwitching: if(iStatus == KErrNone){ //the connection has been closed, start a new connection //using the values in iHostName, iPort, and iIAP. SetEngineState(EComplete); ConnectL(); } else if(iStatus == KErrTimedOut){ ResetL(ETimedOut); } else { ResetL(EngineState()); } break; case EClosed: DBG("Closed"); ResetL( EngineState(), isab::Module::BY_PEER ); break; default: ERR("PANIC KEchoEngine EBadEngineState (%d)", TInt(EBadEngineState)); User::Panic(KEchoEngine, EBadEngineState); break; }; if(!IsActive()){ DBG("Signal OperationComplete"); iConsole.OperationComplete(); DBG("Signaled OperationComplete"); } }
void CGpsDataHandler::RunL() { #ifndef __SERIES60_3X__ TPtr8 pBuffer = iBuffer->Des(); THostName aHostName; TInquirySockAddr aInquiry; TInt aServiceClass; switch(iEngineStatus) { case EGpsResolving: if(iStatus == KErrNone) { // Next device found aHostName = iNameEntry().iName; aInquiry = TInquirySockAddr::Cast(iNameEntry().iAddr); aServiceClass = aInquiry.MajorServiceClass(); iBTAddr.SetBTAddr(aInquiry.BTAddr()); iBTAddr.SetPort(1); if(aServiceClass & 0x08 || aHostName.Find(_L("GPS")) != KErrNotFound || aHostName.Find(_L("gps")) != KErrNotFound) { // Found Positioning device if(iSocket.Open(iSocketServ, KBTAddrFamily, KSockStream, KRFCOMM) == KErrNone) { iEngineStatus = EGpsConnecting; //iResolver.Close(); iSocket.Connect(iBTAddr, iStatus); SetActive(); } else { iSocketServ.Close(); iEngineStatus = EGpsDisconnected; iObserver->GpsError(EGpsConnectionFailed); } } else { // Get next iResolver.Next(iNameEntry, iStatus); SetActive(); } // TODO - Is correct device? } else if(iStatus == KErrHostResNoMoreResults) { // No (more) devices found iSocketServ.Close(); iEngineStatus = EGpsDisconnected; iGpsDeviceResolved = false; iObserver->GpsError(EGpsDeviceUnavailable); } else { iSocketServ.Close(); iEngineStatus = EGpsDisconnected; iObserver->GpsError(EGpsDeviceUnavailable); } break; case EGpsConnecting: if(iStatus == KErrNone) { iEngineStatus = EGpsReading; iGpsDeviceResolved = true; iResolver.Close(); pBuffer.Zero(); iSocket.Recv(iChar, 0, iStatus); SetActive(); } else { if(iGpsDeviceResolved) { iSocket.Close(); iSocketServ.Close(); iEngineStatus = EGpsDisconnected; iObserver->GpsError(EGpsConnectionFailed); } else { // Get next iEngineStatus = EGpsResolving; iResolver.Next(iNameEntry, iStatus); SetActive(); } } break; case EGpsReading: if(iStatus == KErrNone) { iEngineStatus = EGpsConnected; if(pBuffer.Length() + iChar.Length() > pBuffer.MaxLength()) { iBuffer = iBuffer->ReAlloc(pBuffer.MaxLength()+iChar.Length()); pBuffer.Set(iBuffer->Des()); } pBuffer.Append(iChar); ProcessData(); } else { iSocket.Close(); iSocketServ.Close(); iEngineStatus = EGpsDisconnected; iObserver->GpsError(EGpsConnectionFailed); } break; case EGpsDisconnecting: iResolver.Close(); iSocket.Close(); iSocketServ.Close(); iEngineStatus = EGpsDisconnected; break; default:; } #else switch(iEngineStatus) { case EGpsReading: iEngineStatus = EGpsConnected; if(iStatus == KErrNone) { TPosition aPosition; iPositionInfo.GetPosition(aPosition); iObserver->GpsData(aPosition.Latitude(), aPosition.Longitude(), aPosition.HorizontalAccuracy()); if( !iGpsWarmedUp ) { iGpsWarmedUp = true; TPositionUpdateOptions aOptions; aOptions.SetUpdateTimeOut(30000000); aOptions.SetAcceptPartialUpdates(true); iPositioner.SetUpdateOptions(aOptions); } } else { iObserver->GpsError(EGpsDeviceUnavailable); } break; case EGpsDisconnecting: iPositioner.Close(); iPositionServ.Close(); iEngineStatus = EGpsDisconnected; break; default:; } #endif }
gboolean CSensor_btprox::HandleScanEventL(TInt errCode, GError** error) { if (errCode == KErrEof) // no more devices { guilogf("btprox: scan complete"); iNumScanFailures = 0; assert(iResult); SortResult(iResult); assert(iOldResult); if (CmpResults(iResult, iOldResult)) { // Log result. #if PRINT_ELEMENTS PrintElements(iResult); #endif if (!log_db_log_btprox(iLogDb, iResult, error)) { return FALSE; } } else { // There was some discussion as to whether something should be // logged even when there was no change, but is that really // necessary here; if there was no change, then the previous // result still stands. Is it necessary to know the time // of the attempt to scan a different set? guilogf("btprox: device set unchanged"); } iState = EScanWaiting; SetTimer(); // wait before scanning for more } else if (errCode) // some error { guilogf("btprox: scan failed"); iNumScanFailures++; dblogg("%dth consecutive failure in btprox: %s (%d)", iNumScanFailures, plat_error_strerror(errCode), errCode); iState = ERetryWaiting; SetTimer(); } else // no error { { // Add to result. TSockAddr& sockAddr = iNameEntry().iAddr; TBTDevAddr btDevAddr = static_cast<TBTSockAddr>(sockAddr).BTAddr(); /* TBuf<32> addrBuf; btDevAddr.GetReadable(addrBuf); // has no colons */ TBuf8<6*2+5+1> addrBuf8; BtDevAddrToString(addrBuf8, btDevAddr); THostName& hostName = iNameEntry().iName; btprox_item* item = g_try_new0(btprox_item, 1); User::LeaveIfNull(item); #define free_item_action FreeElement(item, NULL); User::Leave(KErrNoMemory); item->name = ConvToUtf8CString(hostName); if (!item->name) { free_item_action; } SET_TRAP_OOM(free_item_action); item->address = g_strdup((gchar*)(addrBuf8.PtrZ())); g_ptr_array_add(iResult, item); UNSET_TRAP_OOM(); guilogf("btprox: device '%s' '%s'", item->address, item->name); } BtNext(); } return TRUE; }