examples/SFExamples/RockPaperScissorsGameSourceCode_S60/RPS/src/BluetoothConnector.cpp

00001 /*
00002 Copyright (c) 2002-2011 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
00003 
00004 Redistribution and use in source and binary forms, with or without
00005 modification, are permitted provided that the following conditions are met:
00006 
00007 * Redistributions of source code must retain the above copyright notice, this
00008   list of conditions and the following disclaimer.
00009 * Redistributions in binary form must reproduce the above copyright notice,
00010   this list of conditions and the following disclaimer in the documentation
00011   and/or other materials provided with the distribution.
00012 * Neither the name of Nokia Corporation nor the names of its contributors
00013   may be used to endorse or promote products derived from this software
00014   without specific prior written permission.
00015 
00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00017 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00020 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00021 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00022 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00023 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00024 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00025 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026 
00027 Description:  
00028 */ 
00029 
00030 // INCLUDE FILES
00031 
00032 #include "BluetoothConnector.h"
00033 #include "BluetoothServiceSearcher.h"
00034 #include "BluetoothSockConnector.h"
00035 #include "BluetoothSocketWriterReader.h"
00036 #include "common.hrh"
00037 
00038 const TInt KMaxIterConnection = 20;
00039 
00040 /*
00041 ============================================================================
00042 CBluetoothConnector's two stage constructor
00043 ============================================================================
00044 */
00045 CBluetoothConnector* CBluetoothConnector::NewL(MBluetoothObserver& aConnObs, RSocketServ& aSocketServer, const TBTDevAddr& aDevAddr)
00046         {
00047     CBluetoothConnector* self = new (ELeave) CBluetoothConnector(aConnObs, aSocketServer, aDevAddr);
00048     CleanupStack::PushL(self);
00049     self->ConstructL();
00050     CleanupStack::Pop();
00051     return self;
00052         }
00053 
00054 /*
00055 ============================================================================
00056 CBluetoothConnector's second phase constructor 
00057 ============================================================================
00058 */
00059 void CBluetoothConnector::ConstructL()
00060         {       
00061         iServiceSearcher = new(ELeave) CBluetoothServiceSearcher(*this);
00062         iSocketConnector = CBluetoothSockConnector::NewL(iBtSocket, *this, iSocketServer);
00063         iBtSocketReader  = new(ELeave) CSocketReader(iBtSocket, *this);
00064         iBtSocketWriter  = new(ELeave) CSocketWriter(iBtSocket, *this);
00065         }
00066 
00067 /*
00068 ============================================================================
00069 CBluetoothConnector's constructor 
00070 ============================================================================
00071 */
00072 CBluetoothConnector::CBluetoothConnector(MBluetoothObserver& aConnObs, RSocketServ& aSocketServer, const TBTDevAddr& aDevAddr):
00073  CBluetoothConnectionBase(ETrue), iConnObs(aConnObs), iSocketServer(aSocketServer), iBtDevAddr(aDevAddr),
00074  iState(EIdle), iPort(KPort), iMaxIterConnection(0)
00075         {
00076         }
00077 
00078 /*
00079 ============================================================================
00080 CBluetoothConnector's destructor
00081 ============================================================================
00082 */
00083 CBluetoothConnector::~CBluetoothConnector()
00084         {
00085         delete iServiceSearcher;
00086         CancelSocket();
00087         iBtSocket.Close();
00088         delete iSocketConnector;
00089         delete iBtSocketReader;
00090         delete iBtSocketWriter; 
00091         }
00092 
00093 /*
00094 ============================================================================
00095 DoCancel is called as part of the active object's Cancel().
00096 Cancels all outstanding BT socket operations
00097 ============================================================================
00098 */
00099 void CBluetoothConnector::DoCancel()
00100         {
00101         CancelSocket();
00102         }
00103 
00104 /*
00105 ============================================================================
00106 This is the entry point of the CBluetoothConnector's state machine. The initial state must be EIdle. Different states
00107 then EIdle will result in a KErrInUse. This is to prevent calling StartL() more than once if the state machine is already active.
00108 ============================================================================
00109 */
00110 void CBluetoothConnector::StartL()
00111         {
00112         iConnected = EFalse;
00113         if (iState != EIdle)
00114                 {
00115                 User::Leave(KErrInUse);
00116                 }
00117         else
00118                 {
00119                 SelfComplete();
00120                 }
00121         }
00122 
00123 /*
00124 ============================================================================
00125 Handles CBluetoothConnector's state machine completion events
00126 ============================================================================
00127 */
00128 void CBluetoothConnector::RunL()
00129         {
00130     switch (iState)
00131         {
00132         case EIdle:
00133                 //State machine entry point. Start searching for a service on the remote devices
00134                 SearchServiceL();
00135                 break;
00136         case ESearchingService:
00137                 //Searching for a service was successful. Start connecting to the remote device using the specific remote device
00138                 //service's port
00139                 ConnectDeviceL();
00140             break;   
00141         case EConnecting:
00142                 //The Master is succesfully connected to the Slave.
00143                 //The state machine can start listening for incoming data. Data transfer can begin
00144         case EWaitingForData:
00145                 //Data from the Slave arrived
00146                 //The state machine can start listening again for incoming data   
00147         case ESendingData:
00148                 //Master sent data to the Slave successfully
00149                 //The state machine can start listening again for incoming data   
00150                 WaitForData();
00151             break;
00152         default:
00153                         User::Leave(KErrCorrupt);
00154             break;
00155         };      
00156         }
00157 
00158 /*
00159 ============================================================================
00160 Sends a service search request to the remote device (Slave)
00161 In our example we have decided to filter our service discovering only by service UUID. If your application
00162 needs to make more complex filtering then you need to set the attribute's UUID you want to use in your search
00163 by calling CSdpSearchPattern::AddL in CBluetoothServiceSearcher::FindServiceByUUIDL.
00164 FindServiceByUUIDL is an asyncronus function. When the search is completed FindServiceByUUIDL calls
00165 the callback function CBluetoothConnector::OnServiceSearchComplete either with the BT service's port
00166 to connect to or with an error (i.e KErrNotFound)
00167 ============================================================================
00168 */
00169 void CBluetoothConnector::SearchServiceL()
00170         {
00171         iState = ESearchingService;
00172         TUUID serviceUUID(KRPS_BTServiceID);
00173         iServiceSearcher->FindServiceByUUIDL(iBtDevAddr, serviceUUID);
00174         }
00175 
00176 /*
00177 ============================================================================
00178 Connects to the remote device (Slave) using a BT device address and the RFCOMM's port
00179 After we have a valid BT device address and a valid BT service port we use CBluetoothSockConnector::ConnectToRemoteBtDeviceL
00180 to connect to the remote BT device. CBluetoothSockConnector uses the BT socket layer. ConnectToRemoteBtDeviceL
00181 is an Asynchronous function and  when the connection is completed it calls the callback
00182 CBluetoothConnector::OnSockConnectionComplete with the connection error (KErrNone for a succesful connection)
00183 ============================================================================
00184 */              
00185 void CBluetoothConnector::ConnectDeviceL()
00186         {
00187         iState = EConnecting;
00188         iSocketConnector->ConnectToRemoteBtDeviceL(iBtDevAddr, iPort);
00189         }
00190 
00191 /*
00192 ============================================================================
00193 Sets the state machine in the listening mode for remote device's incoming data.
00194 Listening is done with CSocketReader (a separate active object). CSocketReader calls the callback
00195 CBluetoothConnector::ReportData either with the data from the remote device or with a connection error.
00196 ============================================================================
00197 */              
00198 void CBluetoothConnector::WaitForData()
00199         {
00200         if(!iBtSocketReader->IsActive() && iConnected)
00201                 {                       
00202                 iState=EWaitingForData;
00203                 iBtSocketReader->ReadData();
00204                 }
00205         }
00206 
00207 /*
00208 ============================================================================
00209 Sends the data to the remote device (Slave). RunL will handle the sending data completion.
00210 ============================================================================
00211 */              
00212 void CBluetoothConnector::SendData(const TDesC8& aData)
00213         {
00214         /*
00215         ============================================================================
00216         If CSocketWriter is already active the data is discarded. RPS doesn't need to queue events.
00217         You can change CSocketWriter's implementation to support queuing of events if our multiplayer game needs to. 
00218         ============================================================================
00219         */              
00220         if(!iBtSocketWriter->IsActive() && iConnected)
00221                 {                       
00222                 iState=ESendingData;
00223                 iBtSocketWriter->Write(aData);
00224                 }
00225         }
00226 
00227 /*
00228 ============================================================================
00229 If an error occurs at any stage of the state machine, cancel all the CBluetoothConnector's
00230 active objects. Then the state machine is reset to the EIdle state
00231 ============================================================================
00232 */              
00233 void CBluetoothConnector::CancelSocket()
00234         {
00235         iConnected = EFalse;
00236         if(iSocketConnector->IsActive())
00237                 {               
00238                 iSocketConnector->Cancel();
00239                 }
00240         iBtSocketWriter->Cancel();
00241         iBtSocketReader->Cancel();
00242         iState = EIdle;
00243         }
00244 
00245 /*
00246 ============================================================================
00247 Callback from CBluetoothServiceSearcher.
00248 If succesful aPort will hold the RFCOMM's port to connect to.
00249 ============================================================================
00250 */              
00251 void CBluetoothConnector::OnServiceSearchComplete(TInt aPort, TInt aError)
00252         {
00253         if(aError == KErrNone)
00254                 {
00255                 //Remember the service's port and carry on with the state machine (connect to device)
00256                 iMaxIterConnection = 0;
00257                 iPort = aPort;
00258                 SelfComplete(); 
00259                 }
00260         else
00261                 {
00262                 if(iMaxIterConnection < KMaxIterConnection)
00263                         {                                       
00264                         iMaxIterConnection++;
00265                         User::After(TTimeIntervalMicroSeconds32(KOneSecondInMicroSeconds));
00266                         SearchServiceL();
00267                         }
00268                 else
00269                         {                               
00270                         //An error occured, cancel all active objects and report the error to the engine
00271                         iMaxIterConnection = 0;
00272                         CancelSocket();
00273                         iConnObs.ConnectionErr(Handle(), aError);
00274                         }
00275                 }
00276         }
00277 
00278 /*
00279 ============================================================================
00280 Callback from CBluetoothSockConnector on connection completion
00281 ============================================================================
00282 */              
00283 void CBluetoothConnector::OnSockConnectionComplete(TInt aError)
00284         {
00285         //report the error to the engine.
00286         if(aError == KErrNone)
00287                 {
00288                 iConnected = ETrue;
00289                 iConnObs.ConnectionErr(Handle(), aError);
00290                 iMaxIterConnection = 0;
00291                 //carry on with the state machine (listen for incoming/sending data)
00292                 SelfComplete();
00293                 }
00294         else
00295                 {
00296                 if(iMaxIterConnection < KMaxIterConnection)
00297                         {                               
00298                         iMaxIterConnection++;
00299                         User::After(TTimeIntervalMicroSeconds32(KOneSecondInMicroSeconds));
00300                         ConnectDeviceL();
00301                         }
00302                 else
00303                         {
00304                         iConnObs.ConnectionErr(Handle(), aError);
00305                         iMaxIterConnection = 0;
00306                         //cancel all active objects
00307                         CancelSocket();
00308                         }
00309                 }
00310         }
00311         
00312 /*
00313 ============================================================================
00314 Callback from CSocketWriter on sending data completion
00315 ============================================================================
00316 */
00317 void CBluetoothConnector::WriteComplete(TInt aError)
00318         {
00319         if(aError == KErrNone)
00320                 {
00321                 //carry on with the state machine (listen for incoming/sending data)
00322                 iConnObs.SendDataComplete(Handle());
00323                 SelfComplete();
00324                 }
00325         else
00326                 {                       
00327                 //An error occured, cancel all active objects and report the error to the engine
00328                 CancelSocket();
00329                 iConnObs.ConnectionErr(iHandle, aError);        
00330                 }
00331         }
00332 
00333 /*
00334 ============================================================================
00335 Callback from CSocketReader on receiving data completion
00336 ============================================================================
00337 */
00338 void CBluetoothConnector::ReportData(const TDesC8& aData, TInt aError)
00339         {               
00340         if(aError == KErrNone)
00341                 {
00342                 //Pass the data to the engine and carry on with the state machine (listen for incoming/sending data)
00343                 iConnObs.DataReceived(iHandle, aData);
00344                 SelfComplete();
00345                 }
00346         else
00347                 {                       
00348                 //An error occured, cancel all active objects and report the error to the engine
00349                 CancelSocket();
00350                 iConnObs.ConnectionErr(iHandle, aError);        
00351                 }
00352         }
00353 
00354 /*
00355 ============================================================================
00356 Call User::RequestComplete on this active object. Used to trigger the next step of
00357 the CBluetoothConnector's state machine.
00358 ============================================================================
00359 */
00360 void CBluetoothConnector::SelfComplete()
00361         {
00362         TRequestStatus* status = &iStatus;
00363         User::RequestComplete(status, KErrNone);
00364         SetActive();                    
00365         }
00366 
00367 /*
00368 ============================================================================
00369 Handles a leave occurring in the request completion event handler RunL().
00370 Close all active BT sockets, reset the state machine to the EIdle state and
00371 report the error to the observer 
00372 ============================================================================
00373 */
00374 TInt CBluetoothConnector::RunError(TInt aError)
00375         {
00376         CancelSocket();
00377         iConnObs.ConnectionErr(iHandle, aError);
00378         return KErrNone;
00379         }
00380 

Generated by  doxygen 1.6.2