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 "BluetoothResponder.h" 00033 #include "BluetoothServiceAdvertiser.h" 00034 #include "BluetoothSocketWriterReader.h" 00035 #include "common.hrh" 00036 00037 const TInt KQueueSize = 1; 00038 00039 /* 00040 ============================================================================ 00041 CBluetoothResponder's two stage constructor 00042 ============================================================================ 00043 */ 00044 CBluetoothResponder* CBluetoothResponder::NewL(MBluetoothObserver& aRespObs, RSocketServ& aSocketServer) 00045 { 00046 CBluetoothResponder* self = new (ELeave) CBluetoothResponder(aRespObs, aSocketServer); 00047 CleanupStack::PushL(self); 00048 self->ConstructL(); 00049 CleanupStack::Pop(); 00050 return self; 00051 } 00052 00053 /* 00054 ============================================================================ 00055 CBluetoothResponder's second phase constructor 00056 ============================================================================ 00057 */ 00058 void CBluetoothResponder::ConstructL() 00059 { 00060 iServiceAdvertiser = new(ELeave) CBluetoothServiceAdvertiser(*this); 00061 iBtSocketReader = new(ELeave) CSocketReader(iAcceptingSocket, *this); 00062 iBtSocketWriter = new(ELeave) CSocketWriter(iAcceptingSocket, *this); 00063 } 00064 00065 /* 00066 ============================================================================ 00067 CBluetoothResponder's constructor 00068 ============================================================================ 00069 */ 00070 CBluetoothResponder::CBluetoothResponder(MBluetoothObserver& aRespObs, RSocketServ& aSocketServer): 00071 CBluetoothConnectionBase(EFalse), iRespObs(aRespObs), iSocketServer(aSocketServer), iState(EIdle) 00072 { 00073 TUid settingsUID; 00074 settingsUID.iUid = KRPS_BTServiceID; 00075 iBtSecurity.SetUid(settingsUID); 00076 iBtSecurity.SetAuthentication(EFalse); 00077 iBtSecurity.SetAuthorisation(EFalse); 00078 iBtSecurity.SetEncryption(EFalse); 00079 } 00080 00081 /* 00082 ============================================================================ 00083 CBluetoothResponder's destructor 00084 ============================================================================ 00085 */ 00086 CBluetoothResponder::~CBluetoothResponder() 00087 { 00088 Cancel(); 00089 delete iServiceAdvertiser; 00090 delete iBtSocketReader; 00091 delete iBtSocketWriter; 00092 iAcceptingSocket.Close(); 00093 iListeningSocket.Close(); 00094 } 00095 00096 /* 00097 ============================================================================ 00098 DoCancel is called as part of the active object's Cancel(). 00099 Cancels all outstanding BT socket operations 00100 ============================================================================ 00101 */ 00102 void CBluetoothResponder::DoCancel() 00103 { 00104 iListeningSocket.CancelAll(); 00105 iAcceptingSocket.CancelAll(); 00106 if(iBtSocketReader->IsActive()) 00107 { 00108 iBtSocketReader->Cancel(); 00109 } 00110 if(iBtSocketWriter->IsActive()) 00111 { 00112 iBtSocketWriter->Cancel(); 00113 } 00114 } 00115 00116 /* 00117 ============================================================================ 00118 Entry point of the CBluetoothResponder's state machine. The initial state must be EIdle. 00119 A state other than EIdle will result in a KErrInUse. This is to prevent StartL() calling 00120 more than once if the state machine is already active. 00121 ============================================================================ 00122 */ 00123 void CBluetoothResponder::StartL() 00124 { 00125 if (iState != EIdle) 00126 { 00127 User::Leave(KErrInUse); 00128 } 00129 00130 TRAPD(err,FindAvailablePortL()); 00131 if(err!=KErrNone) 00132 { 00133 iListeningSocket.Close(); 00134 User::Leave(err); 00135 } 00136 } 00137 00138 /* 00139 ============================================================================ 00140 Handles CBluetoothResponder's state machine completion events 00141 ============================================================================ 00142 */ 00143 void CBluetoothResponder::RunL() 00144 { 00145 User::LeaveIfError(iStatus.Int());//The error is handled in the RunError 00146 00147 switch (iState) 00148 { 00149 case EIdle: 00150 //State machine entry point 00151 break; 00152 case EFindingAvailablePort: 00153 //Founding available port completed, start binding the listening socket to the port 00154 BindToPortL(); 00155 break; 00156 case EBinding: 00157 //Binding completed, start advertising the service 00158 iServiceAdvertiser->StartL(iPort); 00159 iState = EAdvertising; 00160 break; 00161 case EAdvertising: 00162 //Advertising completed, start setting BT security 00163 RegisterService(); 00164 break; 00165 case ERegisteringService: 00166 //Setting BT security completed, start listening for incoming connection 00167 ListenL(); 00168 break; 00169 case EListening: 00170 //Remote device connected, start listening for incoming data 00171 iRespObs.ConnectionErr(iHandle, KErrNone); 00172 case EWaitingForData: 00173 //Incoming data received, start listening for incoming data 00174 case ESendingData: 00175 //Sending data completed, start listening for incoming data 00176 WaitForData(); 00177 break; 00178 default: 00179 User::Leave(KErrCorrupt); 00180 break; 00181 }; 00182 } 00183 00184 00185 /* 00186 ============================================================================ 00187 Opens a socket using the RFCOMM protocol and ask for an available RFCOMM port. 00188 ============================================================================ 00189 */ 00190 void CBluetoothResponder::FindAvailablePortL() 00191 { 00192 iState = EFindingAvailablePort; 00193 User::LeaveIfError(iListeningSocket.Open(iSocketServer, KBTRFCOMM)); 00194 /* 00195 ============================================================================ 00196 Get RFCOMM available port if any. Note that you can also try to get any available port manually. 00197 You can try to bind the listening socket to the current value of iPort (KPort). 00198 If this fails, increment the port until you exhaust all the ports (KMaxTUint8) or find an available one. 00199 ============================================================================ 00200 */ 00201 User::LeaveIfError(iListeningSocket.GetOpt(KRFCOMMGetAvailableServerChannel, KSolBtRFCOMM, iPort)); 00202 SelfComplete(); 00203 } 00204 00205 /* 00206 ============================================================================ 00207 Attempts to bind the listening socket to the BT device address and to an available RFCOMM port and start listening for 00208 incoming remote device connection (Master connection) 00209 ============================================================================ 00210 */ 00211 void CBluetoothResponder::BindToPortL() 00212 { 00213 iState = EBinding; 00214 iBtSocketAddr.SetPort(iPort); 00215 User::LeaveIfError(iListeningSocket.Bind(iBtSocketAddr)); 00216 User::LeaveIfError(iListeningSocket.Listen(KQueueSize)); 00217 SelfComplete(); 00218 } 00219 00220 /* 00221 ============================================================================ 00222 Attaches the BT security settings to the listening socket 00223 ============================================================================ 00224 */ 00225 void CBluetoothResponder::RegisterService() 00226 { 00227 iBtSocketAddr.SetSecurity(iBtSecurity); 00228 iState = ERegisteringService; 00229 SelfComplete(); 00230 } 00231 00232 /* 00233 ============================================================================ 00234 Sets up the BT socket to listen for incoming connection (Master connection) 00235 ============================================================================ 00236 */ 00237 void CBluetoothResponder::ListenL() 00238 { 00239 iState = EListening; 00240 /* 00241 ============================================================================ 00242 Closes old accepted socket if open 00243 ============================================================================ 00244 */ 00245 iAcceptingSocket.Close(); 00246 00247 /* 00248 ============================================================================ 00249 Opens a blank socket 00250 ============================================================================ 00251 */ 00252 User::LeaveIfError(iAcceptingSocket.Open(iSocketServer)); 00253 00254 /* 00255 ============================================================================ 00256 Waits for incoming connection. The RunL will handle it. 00257 ============================================================================ 00258 */ 00259 iListeningSocket.Accept(iAcceptingSocket, iStatus); 00260 SetActive(); 00261 } 00262 00263 /* 00264 ============================================================================ 00265 Sets the state machine in the listening mode for remote device's incoming data. 00266 Listening is done with CSocketReader (a separate active object). On completion CSocketReader calls the callback 00267 CBluetoothResponder::ReportData either with the data from the remote device or with an error. 00268 ============================================================================ 00269 */ 00270 void CBluetoothResponder::WaitForData() 00271 { 00272 if(!iBtSocketReader->IsActive()) 00273 { 00274 iBtSocketReader->ReadData(); 00275 iState=EWaitingForData; 00276 } 00277 } 00278 00279 /* 00280 ============================================================================ 00281 Sends the data to the remote device (Master). RunL will handle the sending data completion 00282 ============================================================================ 00283 */ 00284 void CBluetoothResponder::SendData(const TDesC8& aData) 00285 { 00286 //If CSocketWriter is already active we discard the data to send. RPS doesn't need to queue events. 00287 //You can change CSocketWriter's implementation to support queuing of events if your multiplayer game needs to. 00288 if(!iBtSocketWriter->IsActive()) 00289 { 00290 iBtSocketWriter->Write(aData); 00291 iState=ESendingData; 00292 } 00293 } 00294 00295 00296 /* 00297 ============================================================================ 00298 Callback from CBluetoothServiceAdvertiser if an error occurs during service advertising. 00299 ============================================================================ 00300 */ 00301 void CBluetoothResponder::ReportAdvertiserErr(TInt aError) 00302 { 00303 //Informs the observer of the error 00304 iRespObs.ConnectionErr(iHandle, aError); 00305 } 00306 00307 /* 00308 ============================================================================ 00309 Callback from CBluetoothServiceAdvertiser when the advertising of the service is succesfully completed 00310 ============================================================================ 00311 */ 00312 void CBluetoothResponder::AdvertiserComplete() 00313 { 00314 //Triggers the next step of the state machine (ERegisteringService) 00315 SelfComplete(); 00316 } 00317 00318 /* 00319 ============================================================================ 00320 Callback from CSocketWriter on sending data completion 00321 ============================================================================ 00322 */ 00323 void CBluetoothResponder::WriteComplete(TInt aError) 00324 { 00325 if(aError == KErrNone) 00326 { 00327 //Informs the observer of sending data completion and trigger the next step of the state machine (EWaitingForData) 00328 iRespObs.SendDataComplete(iHandle); 00329 SelfComplete(); 00330 } 00331 else 00332 { 00333 //informs the observer of the error and reset the state machine to the EIdle state 00334 Cancel(); 00335 iState = EIdle; 00336 iRespObs.ConnectionErr(iHandle, aError); 00337 } 00338 } 00339 00340 /* 00341 ============================================================================ 00342 Callback from CSocketReader on receiving data completion 00343 ============================================================================ 00344 */ 00345 void CBluetoothResponder::ReportData(const TDesC8& aData, TInt aError) 00346 { 00347 if(aError == KErrNone) 00348 { 00349 //Passes to the observer the data received from the remote device and trigger the next step 00350 //of the state machine (EWaitingForData) 00351 iRespObs.DataReceived(iHandle, aData); 00352 SelfComplete(); 00353 } 00354 else 00355 { 00356 //Informs the observer of the error and reset the state machine to the EIdle state 00357 Cancel(); 00358 iState = EIdle; 00359 iRespObs.ConnectionErr(iHandle, aError); 00360 } 00361 } 00362 00363 /* 00364 ============================================================================ 00365 Calls User::RequestComplete on this active object. Used to trigger the next step of the state machine. 00366 ============================================================================ 00367 */ 00368 void CBluetoothResponder::SelfComplete() 00369 { 00370 TRequestStatus* status = &iStatus; 00371 User::RequestComplete(status, KErrNone); 00372 SetActive(); 00373 } 00374 00375 /* 00376 ============================================================================ 00377 Handles a leave occurring in the request completion event handler RunL(). 00378 Close all active BT sockets, reset the state machine to the EIdle state and 00379 report the error to the observer 00380 ============================================================================ 00381 */ 00382 TInt CBluetoothResponder::RunError(TInt aError) 00383 { 00384 //Informs the observer of the error and reset the state machine. 00385 iAcceptingSocket.Close(); 00386 iListeningSocket.Close(); 00387 iRespObs.ConnectionErr(iHandle, aError); 00388 iState = EIdle; 00389 return KErrNone; 00390 }