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