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.13 2003/11/25 19:29:56 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::NewL(RMessage &aMessage, CServerSession &aSession)
00035 {
00036     CBTDiscoverer *d = new (ELeave) CBTDiscoverer(aMessage, aSession);
00037     CleanupStack::PushL(d);
00038     d->ConstructL();
00039     CleanupStack::Pop(); // d
00040 
00041     return d;
00042 }
00043 
00044 void CBTDiscoverer::ConstructL()
00045 {
00046     // create the SDP search pattern
00047     iSdpPattern = CSdpSearchPattern::NewL();
00048 //    iSdpPattern->AddL(KL2CAP);
00049 //    iSdpPattern->AddL(KRFCOMM);
00050 
00051     // extract service class id from the message
00052     TUint aServiceClassID = iMessage.Int2();
00053     iSdpPattern->AddL(aServiceClassID);                        
00054 
00055     // create the attribute match list
00056 //    iMatchList = CSdpAttrIdMatchList::NewL();
00057 
00058     //iMatchList->AddL(TAttrRange(0x0000, 0xFFFF));
00059     //use here:
00060     //KSdpAttrIdProtocolDescriptorList instead of attr range
00061 }
00062 
00063 CBTDiscoverer::CBTDiscoverer(RMessage &aMessage, CServerSession &aSession) 
00064     : CActive(CActive::EPriorityStandard), 
00065       iMessage(aMessage), 
00066       iSession(aSession),
00067       iCurrentDeviceIndex(-1)
00068 {
00069 }
00070 
00071 CBTDiscoverer::~CBTDiscoverer()
00072 {
00073     iDeviceAddresses.ResetAndDestroy();
00074     delete iSdpPattern;
00075     delete iAgent;
00076 }
00077 
00078 void CBTDiscoverer::DoCancel()
00079 {
00080     // must close host resolver
00081     iHr.Close();
00082 
00083     delete iPeerList;
00084     iPeerList = NULL;
00085 }
00086 
00087 void CBTDiscoverer::StartL(RSocketServ &aSocketServ)
00088 {
00089    // //Log::Print(_L("CBTDiscoverer::StartL()"));
00090 
00091     iPeerList = new (ELeave) TPeerDataList();
00092 
00093     TProtocolDesc pInfo;
00094     User::LeaveIfError(aSocketServ.FindProtocol(_L("BTLinkManager"), pInfo));
00095 
00096     // create and initialise an RHostResolver
00097     User::LeaveIfError(iHr.Open(aSocketServ, pInfo.iAddrFamily, pInfo.iProtocol));
00098 
00099     // set up a discovery query 
00100     TInquirySockAddr addr;
00101     TNameEntry name;
00102     addr.SetIAC(KGIAC);
00103     addr.SetAction(KHostResName | KHostResInquiry);
00104 
00105     // add to active scheduler
00106     CActiveScheduler::Add(this);
00107 
00108     // initiate discovery of the first device
00109     TRequestStatus status;
00110     iHr.GetByAddress(addr, iNameEntry, iStatus);
00111 
00112     // wait for completion
00113     SetActive();
00114 }
00115 
00116 void CBTDiscoverer::DiscoverServices(TNameRecord &aNameRecord)
00117 {
00118     delete iAgent;
00119     iAgent = NULL;
00120 
00121     //Log::Print(_L("DiscoverServices(): %S"), &(aNameRecord.iName));
00122 
00123     // extract bluetooth address
00124     TBTDevAddr btaddr = static_cast<TBTSockAddr>(aNameRecord.iAddr).BTAddr();
00125 
00126     TRAPD(err, (iAgent = CSdpAgent::NewL(*this, btaddr)));
00127     if( err != KErrNone ) {
00128         User::Panic(KBTDiscovererPanic, KErrBtdiscovererAllocFailed);
00129     }   
00130 
00131     iAgent->SetRecordFilterL(*iSdpPattern);
00132     iAgent->NextRecordRequestL(); // will result in NextRecordRequestComplete()
00133 }
00134 
00135 // initializes client's peer list and completes client call 
00136 void CBTDiscoverer::FinishDiscovery()
00137 {
00138     //Log::Print(_L("FinishDiscovery()"));
00139 
00140     iCurrentDeviceIndex = -1;
00141 
00142     // give up peer list
00143     iSession.SetPeerList(iPeerList);
00144     iPeerList = NULL;
00145 
00146     // write number of peers and complete the original call
00147     TBuf8<sizeof(TInt)> buf;
00148     buf.Copy((const TUint8 *)(&iNumPeers), sizeof(TInt));
00149     iMessage.WriteL(iMessage.Ptr1(), buf);
00150 
00151     iMessage.Complete(KErrNone);
00152 
00153     // release memory
00154     iDeviceAddresses.ResetAndDestroy();
00155 }
00156 
00157 void CBTDiscoverer::DeviceDiscovered()
00158 {
00159     if( iStatus == KErrNone ) {
00160         TNameRecord record = iNameEntry();
00161 
00162   //      //Log::Print(_L("found device %S"), &(record.iName));
00163 
00164         // create new instance
00165         TNameRecord *new_record = NULL;
00166         TRAPD(err, (new_record = new (ELeave) TNameRecord()));
00167         if( err != KErrNone ) {
00168             User::Panic(KBTDiscovererPanic, KErrBtdiscovererAllocFailed);
00169         } 
00170 
00171         // initialize the new instance
00172         Mem::Copy(new_record, &record, sizeof(TNameRecord));
00173 
00174         // add the instance to device address list 
00175         iDeviceAddresses.Append(new_record);
00176 
00177         // discover next device
00178         iHr.Next(iNameEntry, iStatus);
00179         SetActive();
00180     } else {
00181 //        //Log::Print(_L("** no more devices"));
00182 
00183         // no more devices; all done
00184         iHr.Close();
00185 
00186         // start discovering services
00187         if( iDeviceAddresses.Count() > 0 ) {
00188             // create service discover agent
00189             iCurrentDeviceIndex = 0;
00190             DiscoverServices(*iDeviceAddresses[iCurrentDeviceIndex]);
00191         } else {
00192             // no devices found! list is empty; allow client call return
00193             FinishDiscovery(); 
00194         }
00195     }
00196 }
00197 
00198 void CBTDiscoverer::RunL()
00199 {
00200   //  //Log::Print(_L("CBTDiscoverer::RunL()"));
00201 
00202     DeviceDiscovered();
00203 }
00204 
00205 TInt CBTDiscoverer::RunError(TInt aError)
00206 {
00207     //Log::Print(_L("RunError(): %d"), aError);
00208 
00209     return aError;
00210 }
00211 
00213 // from MSdpAgentNotifier
00215 
00216 void CBTDiscoverer::AttributeRequestComplete(TSdpServRecordHandle /*aHandle*/, 
00217                                              TInt aError)
00218 {
00219     //Log::Print(_L("AttributeRequestComplete()"));
00220 
00221     if( aError != KErrNone ) {
00222         //Log::Print(_L("AttributeRequestComplete(): %d"), aError);
00223         //##TODO## handle
00224     } else {
00225         // attributes done - request next service record
00226         TRAPD(err, iAgent->NextRecordRequestL());
00227         if( err != KErrNone ) {
00228             //Log::Print(_L("iAgent->NextRecordRequestL() error: %d"), err);
00229             //##TODO## handle
00230         }
00231     }
00232 }
00233 
00234 void CBTDiscoverer::AttributeRequestResult(TSdpServRecordHandle /*aHandle*/, 
00235                                            TSdpAttributeID /*aAttrID*/, 
00236                                            CSdpAttrValue* aAttrValue)
00237 {
00238     // initiate attribute list traversal
00239     iAttrNum = 0;
00240     iPeerOk = ETrue;
00241 
00242     //Log::Print(_L("AttributeRequestResult()"));
00243 
00244     // parse through the attributes - will result in calls to 
00245     // VisitAttributeValueL()
00246     TRAPD(err, aAttrValue->AcceptVisitorL(*this));
00247     if( err != KErrNone )
00248     {
00249         //Log::Print(_L("aAttrValue->AcceptVisitorL() error: %d"), err);
00250             //##TODO## handle
00251     }
00252 }
00253 
00254 // called when discovery of a advertised service completes
00255 void CBTDiscoverer::NextRecordRequestComplete(TInt aError, 
00256                                               TSdpServRecordHandle aHandle, 
00257                                               TInt aTotalRecordsCount)
00258 {
00259     //Log::Print(_L("NRRC(): error: %d, count: %d, handle: %d"), 
00260    //                aError, aTotalRecordsCount, aHandle);
00261 
00262     if( (aError == KErrNone) && (aTotalRecordsCount > 0) ) {
00263         // retrieve the service attributes - will result in call to 
00264         // VisitAttributeValueL() for every attribute of the service
00265 
00266         // request protocol descriptor to get the port. will result in 
00267         // call to VisitAttributeValueL()
00268         TRAPD(err, iAgent->AttributeRequestL(aHandle, KSdpAttrIdProtocolDescriptorList));
00269         if( err != KErrNone ) {
00270             //Log::Print(_L("iAgent->AttributeRequestL() error: %d"), err);
00271             //##TODO## panic!
00272         }
00273     } else {
00274         // no more services for this device - discover the services of next device
00275         // if devicesw left
00276         iCurrentDeviceIndex++;
00277 
00278         if( iCurrentDeviceIndex < iDeviceAddresses.Count() ) {
00279             DiscoverServices(*iDeviceAddresses[iCurrentDeviceIndex]);
00280         } else {
00281             // all devices processed - all done!
00282             FinishDiscovery();
00283         }
00284     }
00285 }
00286 
00288 // from MSdpAttributeValueVisitor
00290 /*
00291 // cobain protocol stack resources
00292 const TInt KCobainProtocolStackSize = 6;
00293 
00294 static const TSdpElementType KCtalkStack[KCobainProtocolStackSize] = 
00295     { ETypeDES, ETypeDES, ETypeUUID, ETypeDES, ETypeUUID, ETypeUint };
00296 */
00297 // cobain protocol stack resources
00298 const TInt KCobainProtocolStackSize = 4;
00299 
00300 static const TSdpElementType KCtalkStack[KCobainProtocolStackSize] = 
00301     { ETypeDES, ETypeDES, ETypeUUID, ETypeUint };
00302 
00303 void CBTDiscoverer::VisitAttributeValueL(CSdpAttrValue &aValue, 
00304                                          TSdpElementType aType)
00305 {
00306     // check stack format
00307     if( !iPeerOk || 
00308         (iAttrNum >= KCobainProtocolStackSize) ||
00309         (KCtalkStack[iAttrNum++] != aType) ) {
00310         iPeerOk = EFalse;
00311 
00312         //Log::Print(_L("rejecting 1"));
00313         return;
00314     }
00315 
00316     TBuf<64> buf;
00317    // const TDesC8 *uuid;
00318     TBuf8<16> uuid;
00319     TUint *val;
00320 
00321     switch( aType ) {
00322         case ETypeUUID:
00323             //uuid = &(aValue.UUID().ShortestForm());
00324             uuid = aValue.UUID().ShortestForm();
00325             val = (TUint*)uuid.Ptr();
00326             //Log::Print(_L("UUID: %d"), *val);
00327             break;
00328         case ETypeUint:
00329             //Log::Print(_L("Uint: %d"), aValue.Uint());
00330 
00331             // if the protocol stack descriptor is of correct format, this is the
00332             // port number. add a peer entry
00333             if( iAttrNum == KCobainProtocolStackSize ) {
00334                 //TBTDevAddr btaddr = static_cast<TBTSockAddr>(iNameEntry().iAddr).BTAddr();
00335                 TNameRecord *record = iDeviceAddresses[iCurrentDeviceIndex];
00336                 TBTDevAddr btaddr = static_cast<TBTSockAddr>(record->iAddr).BTAddr();
00337                 TPeerData *data = new (ELeave) TPeerData();
00338                 data->iDeviceName = record->iName;
00339                 data->iDeviceAddress = btaddr.Des();
00340                 //##TODO##
00341                 //data->iServiceID = ?? // - what is this anyway?
00342                 // -> well it is a textual service description of course
00343                 data->iPort = aValue.Uint();
00344 
00345                 //Log::Print(_L("found port %d for device %S"), 
00346 //                    data->iPort, &(data->iDeviceName));
00347 
00348                 iPeerList->Append(data);
00349                 iNumPeers++;
00350             } else {
00351                 //Log::Print(_L("rejecting 2"));
00352             }
00353             break;
00354         case ETypeDES:
00355             //Log::Print(_L("DES"));
00356             break;
00357         case ETypeNil:
00358             //Log::Print(_L("Nil"));
00359             break;
00360         case ETypeInt:
00361            //Log::Print(_L("Int"));
00362             break;
00363         case ETypeString:
00364            //Log::Print(_L("String"));
00365             break;
00366         case ETypeBoolean:
00367            //Log::Print(_L("Boolean"));
00368             break;
00369         case ETypeDEA:
00370            //Log::Print(_L("DEA"));
00371             break;
00372         case ETypeURL:
00373            //Log::Print(_L("URL"));
00374             break;
00375         case ETypeEncoded:
00376            //Log::Print(_L("Encoded"));
00377             break;
00378         default:
00379             // dont really care..
00380             break;
00381     }
00382 }
00383 
00384 void CBTDiscoverer::StartListL(CSdpAttrValueList& /*aList*/)
00385 {
00386     // no implementation
00387 }
00388 
00389 void CBTDiscoverer::EndListL()
00390 {
00391     // no implementation
00392 }
00393 

Generated on Mon Dec 8 10:26:06 2003 for CobainAPIImplementation by doxygen 1.3.5