Main Page | Class Hierarchy | Data Structures | File List | Data Fields | Globals

btdiscoverer.cpp

Go to the documentation of this file.
00001 /*
00002  * btdiscoverer.cpp,v 1.18 2004/01/10 14:27:10 mattid Exp
00003  *
00004  * COBAIN - Communications API for EPOC Environments
00005  * Copyright (C) 2002-2003 Matti Dahlbom, Matti Kokkola
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  *
00021  * Contact: Matti Dahlbom <matti@777-team.org>
00022  *          Matti Kokkola <matti.kokkola@iki.fi>
00023  */
00024 
00025 #include <es_sock.h>
00026 #include <bt_sock.h>
00027 
00028 #include "bluetoothcommunicator.h"
00029 #include "btdiscoverer.h"
00030 #include "cobainserver.h"
00031 #include "serversession.h"
00032 #include "Log.h"
00033 
00034 CBTDiscoverer::CBTDiscoverer(RMessage &aMessage, CServerSession &aSession) 
00035     : CActive(CActive::EPriorityStandard), 
00036       iMessage(aMessage), 
00037       iSession(aSession),
00038       iCurrentDeviceIndex(-1)
00039 {
00040 }
00041 
00042 CBTDiscoverer::~CBTDiscoverer()
00043 {
00044     iDeviceAddresses.ResetAndDestroy();
00045     delete iSdpPattern;
00046     delete iAgent;
00047     delete iAttrMatchList;
00048 }
00049 
00050 CBTDiscoverer * CBTDiscoverer::NewL(RMessage &aMessage, CServerSession &aSession)
00051 {
00052     CBTDiscoverer *d = new (ELeave) CBTDiscoverer(aMessage, aSession);
00053     CleanupStack::PushL(d);
00054     d->ConstructL();
00055     CleanupStack::Pop(); // d
00056 
00057     return d;
00058 }
00059 
00060 void CBTDiscoverer::ConstructL()
00061 {
00062     // create SDP search pattern
00063     delete iSdpPattern;
00064     iSdpPattern = NULL;
00065     iSdpPattern = CSdpSearchPattern::NewL();
00066 
00067     // create attribute match list for looking up service descriptor + name
00068     iAttrMatchList = CSdpAttrIdMatchList::NewL();
00069     iAttrMatchList->AddL(TAttrRange(KSdpAttrIdProtocolDescriptorList));
00070     TSdpAttributeID attr_id = KSdpAttrIdOffsetServiceName + 
00071                               KSdpAttrIdBasePrimaryLanguage;
00072     iAttrMatchList->AddL(TAttrRange(attr_id));
00073 
00074     // extract service id (UUID) of the service being discovered. if 0, all services
00075     // get discovered
00076     TUint service_id = iMessage.Int2();
00077     if( service_id != 0 ) {
00078         // do a lookup by UUID
00079         iSdpPattern->AddL(service_id);
00080         Log::Print(_L("CBTDiscoverer::ConstructL() id: 0x%X"), service_id);
00081     } else {
00082         // lookup everything supporting RFCOMM/L2CAP
00083         iSdpPattern->AddL(KL2CAP);
00084         iSdpPattern->AddL(KRFCOMM);
00085         Log::Print(_L("CBTDiscoverer::ConstructL() looking up all"));
00086     }
00087 }
00088 
00089 void CBTDiscoverer::DoCancel()
00090 {
00091     // must close host resolver
00092     iHr.Close();
00093 
00094     delete iPeerList;
00095     iPeerList = NULL;
00096 }
00097 
00098 void CBTDiscoverer::StartL(RSocketServ &aSocketServ)
00099 {
00100     Log::Print(_L("CBTDiscoverer::StartL()"));
00101 
00102     // allocate new peer list
00103     delete iPeerList;
00104     iPeerList = NULL;
00105     iPeerList = new (ELeave) TPeerDataList();
00106 
00107     TProtocolDesc pInfo;
00108     User::LeaveIfError(aSocketServ.FindProtocol(_L("BTLinkManager"), pInfo));
00109 
00110     // create and initialise an RHostResolver
00111     User::LeaveIfError(iHr.Open(aSocketServ, pInfo.iAddrFamily, pInfo.iProtocol));
00112 
00113     // set up a discovery query 
00114     TInquirySockAddr addr;
00115     TNameEntry name;
00116     addr.SetIAC(KGIAC);
00117     addr.SetAction(KHostResName | KHostResInquiry);
00118 
00119     // add to active scheduler
00120     CActiveScheduler::Add(this);
00121 
00122     // initiate discovery of the first device
00123     TRequestStatus status;
00124     iHr.GetByAddress(addr, iNameEntry, iStatus);
00125 
00126     // wait for completion
00127     SetActive();
00128 }
00129 
00130 void CBTDiscoverer::DiscoverServices(TNameRecord &aNameRecord)
00131 {
00132     delete iAgent;
00133     iAgent = NULL;
00134 
00135     Log::Print(_L("DiscoverServices(): %S"), &(aNameRecord.iName));
00136 
00137     // extract bluetooth address
00138     TBTDevAddr btaddr = static_cast<TBTSockAddr>(aNameRecord.iAddr).BTAddr();
00139 
00140     TRAPD(err, (iAgent = CSdpAgent::NewL(*this, btaddr)));
00141     if( err != KErrNone ) {
00142         User::Panic(KBTDiscovererPanic, KErrBtdiscovererAllocFailed);
00143     }   
00144 
00145     iAgent->SetRecordFilterL(*iSdpPattern);
00146     iAgent->NextRecordRequestL(); // will result in NextRecordRequestComplete()
00147 }
00148 
00149 // initializes client's peer list and completes client call 
00150 void CBTDiscoverer::FinishDiscovery()
00151 {
00152     Log::Print(_L("FinishDiscovery()"));
00153 
00154     iCurrentDeviceIndex = -1;
00155 
00156     // give up peer list
00157     iSession.SetPeerList(iPeerList);
00158     iPeerList = NULL;
00159 
00160     // write number of peers and complete the original call
00161     TBuf8<sizeof(TInt)> buf;
00162     buf.Copy((const TUint8 *)(&iNumPeers), sizeof(TInt));
00163     iMessage.WriteL(iMessage.Ptr1(), buf);
00164 
00165     iMessage.Complete(KErrNone);
00166 
00167     // release memory
00168     iDeviceAddresses.ResetAndDestroy();
00169 }
00170 
00171 void CBTDiscoverer::DeviceDiscovered()
00172 {
00173     if( iStatus == KErrNone ) {
00174         TNameRecord record = iNameEntry();
00175 
00176   //      //Log::Print(_L("found device %S"), &(record.iName));
00177 
00178         // create new instance
00179         TNameRecord *new_record = NULL;
00180         TRAPD(err, (new_record = new (ELeave) TNameRecord()));
00181         if( err != KErrNone ) {
00182             User::Panic(KBTDiscovererPanic, KErrBtdiscovererAllocFailed);
00183         } 
00184 
00185         // initialize the new instance
00186         Mem::Copy(new_record, &record, sizeof(TNameRecord));
00187 
00188         // add the instance to device address list 
00189         iDeviceAddresses.Append(new_record);
00190 
00191         // discover next device
00192         iHr.Next(iNameEntry, iStatus);
00193         SetActive();
00194     } else {
00195         Log::Print(_L("** no more devices"));
00196 
00197         // no more devices; all done
00198         iHr.Close();
00199 
00200         // start discovering services
00201         if( iDeviceAddresses.Count() > 0 ) {
00202             // create service discover agent
00203             iCurrentDeviceIndex = 0;
00204             DiscoverServices(*iDeviceAddresses[iCurrentDeviceIndex]);
00205         } else {
00206             // no devices found! list is empty; allow client call return
00207             FinishDiscovery(); 
00208         }
00209     }
00210 }
00211 
00212 void CBTDiscoverer::RunL()
00213 {
00214   //  //Log::Print(_L("CBTDiscoverer::RunL()"));
00215 
00216     DeviceDiscovered();
00217 }
00218 
00219 TInt CBTDiscoverer::RunError(TInt aError)
00220 {
00221     //Log::Print(_L("RunError(): %d"), aError);
00222 
00223     return aError;
00224 }
00225 
00227 // from MSdpAgentNotifier
00229 
00230 void CBTDiscoverer::AttributeRequestComplete(TSdpServRecordHandle /*aHandle*/, 
00231                                              TInt aError)
00232 {
00233     //Log::Print(_L("AttributeRequestComplete()"));
00234 
00235     if( aError != KErrNone ) {
00236         //Log::Print(_L("AttributeRequestComplete(): %d"), aError);
00237         //##TODO## handle
00238     } else {
00239         // attributes for this service done - create a peer record
00240         TNameRecord *record = iDeviceAddresses[iCurrentDeviceIndex];
00241         TBTDevAddr btaddr = static_cast<TBTSockAddr>(record->iAddr).BTAddr();
00242         TPeerData *data = new (ELeave) TPeerData();
00243         data->iDeviceName = record->iName;
00244         data->iDeviceAddress = btaddr.Des();
00245         data->iServiceName = iServiceName;
00246         data->p.iBtProperties.iRfcommPort = iRfcommPort;
00247         data->p.iBtProperties.iL2capPort = iL2capPort;
00248         iPeerList->Append(data);
00249         iNumPeers++;
00250 
00251         Log::Print(_L("added peer: L: %d, R: %d"), iL2capPort, iRfcommPort);    
00252 
00253         // request next service record.
00254         // will result in call to NextRecordRequestComplete()
00255         TRAPD(err, iAgent->NextRecordRequestL());
00256         if( err != KErrNone ) {
00257             //Log::Print(_L("iAgent->NextRecordRequestL() error: %d"), err);
00258             //##TODO## handle
00259         }
00260     }
00261 }
00262 
00263 void CBTDiscoverer::AttributeRequestResult(TSdpServRecordHandle /*aHandle*/, 
00264                                            TSdpAttributeID /*aAttrID*/, 
00265                                            CSdpAttrValue* aAttrValue)
00266 {
00267     //Log::Print(_L("AttributeRequestResult()"));
00268 
00269     // parse through the attributes - will result in calls to 
00270     // VisitAttributeValueL()
00271     TRAPD(err, aAttrValue->AcceptVisitorL(*this));
00272 }
00273 
00274 // called when discovery of a advertised service completes
00275 void CBTDiscoverer::NextRecordRequestComplete(TInt aError, 
00276                                               TSdpServRecordHandle aHandle, 
00277                                               TInt aTotalRecordsCount)
00278 {
00279     TInt err;
00280     Log::Print(_L("NRRC(): error: %d, count: %d, handle: %d"), 
00281                   aError, aTotalRecordsCount, aHandle);
00282 
00283     if( (aError == KErrNone) && (aTotalRecordsCount > 0) ) {
00284         // services records left - reset service information for new service
00285         iRfcommPort = -1;
00286         iL2capPort = -1;
00287         iServiceName.Zero();
00288         iLastUuid32 = 0;
00289 
00290         // request protocol descriptor to get the service details including
00291         // the port the service is listening to and the service name. will result in 
00292         // call to AttributeRequestResult()
00293         TRAP(err, iAgent->AttributeRequestL(aHandle, *iAttrMatchList));
00294     } else {
00295         // no more services for this device - discover services of next device
00296         iCurrentDeviceIndex++;
00297 
00298         if( iCurrentDeviceIndex < iDeviceAddresses.Count() ) {
00299             DiscoverServices(*iDeviceAddresses[iCurrentDeviceIndex]);
00300         } else {
00301             // all devices processed - all done!
00302             FinishDiscovery();
00303         }
00304     }
00305 }
00306 
00308 // from MSdpAttributeValueVisitor
00310 
00311 void CBTDiscoverer::VisitAttributeValueL(CSdpAttrValue &aValue, 
00312                                          TSdpElementType aType)
00313 {
00314     TBuf<64> bufw;
00315     TInt index;
00316 
00317     if( aType != ETypeUint ) {
00318         // reset last 32bit uuid marker
00319         iLastUuid32 = 0;
00320     }
00321     
00322     switch( aType ) {
00323         case ETypeUUID:
00324             ParseUuid(bufw, aValue.UUID(), iLastUuid32);
00325             Log::Print(_L("UUID: %S"), &bufw);
00326             // add to a UUID list! (##TODO##)
00327             break;
00328         case ETypeUint:
00329             Log::Print(_L("Uint: %u"), aValue.Uint());
00330             if( iLastUuid32 == KRFCOMM ) {
00331                 iRfcommPort = aValue.Uint();
00332             } else if( iLastUuid32 == KL2CAP ) {
00333                 iL2capPort = aValue.Uint();
00334             }
00335             break;
00336         case ETypeDES:
00337             //Log::Print(_L("DES"));
00338             break;
00339         case ETypeNil:
00340             Log::Print(_L("Nil"));
00341             break;
00342         case ETypeInt:
00343             Log::Print(_L("Int: %d"), aValue.Int());
00344             break;
00345         case ETypeString:
00346             // the string is the service name
00347             iServiceName.Copy(aValue.Des());
00348             bufw.Copy(aValue.Des());
00349 
00350             // trim trailing zero(s)
00351             index = iServiceName.Locate(0x00);
00352             if( index != KErrNotFound ) {
00353                 iServiceName.SetLength(index);
00354             }
00355             
00356             // print last char value
00357             //Log::Print(_L("last char: %d"), (TInt)bufw[bufw.Length() - 1]);
00358             Log::Print(_L("String: %S"), &bufw);
00359             break;
00360         case ETypeBoolean:
00361             Log::Print(_L("Boolean"));
00362             break;
00363         case ETypeDEA:
00364             Log::Print(_L("DEA"));
00365             break;
00366         case ETypeURL:
00367             Log::Print(_L("URL"));
00368             break;
00369         case ETypeEncoded:
00370             Log::Print(_L("Encoded"));
00371             break;
00372         default:
00373             // dont really care..
00374             break;
00375     }
00376 }
00377 
00378 void CBTDiscoverer::StartListL(CSdpAttrValueList& /*aList*/)
00379 {
00380     // no implementation
00381 }
00382 
00383 void CBTDiscoverer::EndListL()
00384 {
00385     // no implementation
00386 }
00387 
00388 // util method for parsing an UUID into a hexstring
00389 void CBTDiscoverer::ParseUuid(TDes &aBuf, const TUUID &aUuid, TUint32 &aUuid32)
00390 {
00391     TPtrC8 uuid(aUuid.ShortestForm());
00392     TInt len = uuid.Length();
00393 
00394 //    Log::Print(_L("ParseUuid(): UUID len: %d"), len);
00395 
00396     switch( len ) {
00397         case 2:
00398             aUuid32 = (TUint)BigEndian::Get16(uuid.Ptr());
00399             aBuf.Format(_L("0x%X"), aUuid32);
00400             break;
00401         case 4:
00402             aUuid32 = BigEndian::Get32(uuid.Ptr());
00403             aBuf.Format(_L("0x%X"), aUuid32);
00404             break;
00405         case 16:
00406             aUuid32 = 0;
00407             //##TODO##
00408             break;
00409     }
00410 }

Generated on Tue Jan 13 15:47:06 2004 for CobainAPIImplementation by doxygen 1.3.5