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 00031 // INCLUDE FILES 00032 #include "BluetoothServiceAdvertiser.h" 00033 #include "common.hrh" 00034 00035 _LIT(KRpsServiceName, "RPS"); 00036 _LIT(KRpsServiceDes, "RPS"); 00037 00038 const TInt KPortBufMaxSize = 2; 00039 const TInt KServAvailBufMaxSize = 1; 00040 00041 /* 00042 ============================================================================ 00043 CBluetoothServiceAdvertiser's constructor 00044 ============================================================================ 00045 */ 00046 CBluetoothServiceAdvertiser::CBluetoothServiceAdvertiser(MBluetoothServiceAdvertiserObserver& aSerAdvObs) 00047 :CActive(CActive::EPriorityStandard), iSerAdvObs(aSerAdvObs), iState(EIdle) 00048 { 00049 CActiveScheduler::Add(this); 00050 } 00051 00052 /* 00053 ============================================================================ 00054 CBluetoothServiceAdvertiser's destructor 00055 ============================================================================ 00056 */ 00057 CBluetoothServiceAdvertiser::~CBluetoothServiceAdvertiser() 00058 { 00059 Cancel(); 00060 UnregisterService(); 00061 } 00062 00063 /* 00064 ============================================================================ 00065 Entry point of the CBluetoothServiceAdvertiser's state machine. The initial state must be EIdle. 00066 A state other than EIdle will result in a KErrInUse. This is to prevent StartL() calling 00067 more than once if the state machine is alread active. 00068 ============================================================================ 00069 */ 00070 void CBluetoothServiceAdvertiser::StartL(const TInt aPort) 00071 { 00072 if (iState != EIdle) 00073 { 00074 User::Leave(KErrInUse); 00075 } 00076 00077 iPort = aPort; 00078 SelfComplete(); 00079 } 00080 00081 /* 00082 ============================================================================ 00083 Connect to the SDP server and open a SDP's RSdpDatabase subsession where 00084 service records and their attributes can be added, deleted, and updated. 00085 ============================================================================ 00086 */ 00087 void CBluetoothServiceAdvertiser::ConnectToSdpL() 00088 { 00089 iState = EConnecting; 00090 User::LeaveIfError(iSdpServ.Connect()); 00091 User::LeaveIfError(iSdpDatabase.Open(iSdpServ)); 00092 SelfComplete(); 00093 } 00094 00095 /* 00096 ============================================================================ 00097 Create and add the RPS's service record into the SDP's database 00098 ============================================================================ 00099 */ 00100 void CBluetoothServiceAdvertiser::BuildServiceRecordL() 00101 { 00102 iState = EBuildingServiceRecord; 00103 TUUID serviceUUID(KRPS_BTServiceID); 00104 //Creates a new service record, with a single service class (KRPS_BTServiceID) in the SDP database. 00105 //If succesful iRecordHandle will hold the RPS's record handle. 00106 iSdpDatabase.CreateServiceRecordL(serviceUUID, iRecordHandle); 00107 00108 //Now the RPS's record needs to be filled with RPS's service attributes 00109 00110 // Add the RFCOMM protocol attribute to the record. 00111 CSdpAttrValueDES* protocolDescriptorList = CSdpAttrValueDES::NewDESL(NULL); 00112 CleanupStack::PushL(protocolDescriptorList); 00113 00114 TBuf8<KPortBufMaxSize> port; 00115 port.Append((TChar)iPort); 00116 00117 //Builds a protocol list of attributes. In our example the list contains only the RFCOMM protocol element 00118 //and the RFCOMM's port. For more information about the structure of a SDP's record please refer to the SDK 00119 protocolDescriptorList 00120 ->StartListL() //Marks the start of the list 00121 ->BuildDESL() //Adds a Data Element Sequence (DES) 00122 ->StartListL() //Indicates that subsequent elements added belong to a DES (Data Element Sequence) or DEA (Data Element Alternative) 00123 ->BuildUUIDL(KRFCOMM) //Adds the RFCOMM's TUUID 00124 ->BuildUintL(port) //Adds the RFCOMM's port. Remote devices will connect to this port to use the RPS's service 00125 ->EndListL() //Marks the end of the subsequent element 00126 ->EndListL(); //Marks the end of the list 00127 00128 00129 //Sets the protocol list to the record 00130 iSdpDatabase.UpdateAttributeL(iRecordHandle, KSdpAttrIdProtocolDescriptorList, *protocolDescriptorList); 00131 CleanupStack::PopAndDestroy(protocolDescriptorList); 00132 00133 //Adds the record's name attribute 00134 iSdpDatabase.UpdateAttributeL(iRecordHandle, KSdpAttrIdBasePrimaryLanguage + KSdpAttrIdOffsetServiceName, KRpsServiceName); 00135 00136 //Adds the record's description attribute 00137 iSdpDatabase.UpdateAttributeL(iRecordHandle, KSdpAttrIdBasePrimaryLanguage + KSdpAttrIdOffsetServiceDescription, KRpsServiceDes); 00138 00139 //Adds the record's available service attribute 00140 CSdpAttrValue* attrVal = NULL; 00141 TBuf8<KServAvailBufMaxSize> avail; 00142 avail.FillZ(1); 00143 avail[0]=0xff;//Fully available value 00144 //Service availability is store as a TUint 00145 attrVal = CSdpAttrValueUint::NewUintL(avail); 00146 CleanupStack::PushL(attrVal); 00147 iSdpDatabase.UpdateAttributeL(iRecordHandle, KSdpAttrIdServiceAvailability, *attrVal); 00148 CleanupStack::PopAndDestroy(attrVal); 00149 SelfComplete(); 00150 } 00151 00152 /* 00153 ============================================================================ 00154 Removes the RPS's service record from the SDP's database 00155 ============================================================================ 00156 */ 00157 void CBluetoothServiceAdvertiser::UnregisterService() 00158 { 00159 // Deletes SDP Record 00160 if (iRecordHandle) 00161 { 00162 TRAPD(ret,iSdpDatabase.DeleteRecordL(iRecordHandle)); 00163 } 00164 // Closes SDP's database handle 00165 iSdpDatabase.Close(); 00166 // Close SDP's session 00167 iSdpServ.Close(); 00168 } 00169 00170 /* 00171 ============================================================================ 00172 Handles the active object's service advertising completion events. 00173 ============================================================================ 00174 */ 00175 void CBluetoothServiceAdvertiser::RunL() 00176 { 00177 switch (iState) 00178 { 00179 case EIdle: 00180 //State machine entry point 00181 ConnectToSdpL(); 00182 break; 00183 case EConnecting: 00184 //Connect to SDP server completed, start building the RPS's service record 00185 BuildServiceRecordL(); 00186 break; 00187 case EBuildingServiceRecord: 00188 //Build RPS's service record completed, notify the completion event to the observer. 00189 iSerAdvObs.AdvertiserComplete(); 00190 break; 00191 default: 00192 User::Leave(KErrCorrupt); 00193 break; 00194 }; 00195 } 00196 00197 /* 00198 ============================================================================ 00199 DoCancel is called as part of the active object's Cancel(). 00200 ============================================================================ 00201 */ 00202 void CBluetoothServiceAdvertiser::DoCancel() 00203 { 00204 //Not Used 00205 } 00206 00207 /* 00208 ============================================================================ 00209 Calls User::RequestComplete on this active object. Used to trigger the next step of the state machine. 00210 ============================================================================ 00211 */ 00212 void CBluetoothServiceAdvertiser::SelfComplete() 00213 { 00214 TRequestStatus* status = &iStatus; 00215 User::RequestComplete(status, KErrNone); 00216 SetActive(); 00217 } 00218 00219 /* 00220 ============================================================================ 00221 Handles a leave occurring in the request completion event handler RunL(). 00222 Close all resources, reset the state machine to the EIdle state, notify the 00223 observer of the error 00224 ============================================================================ 00225 */ 00226 TInt CBluetoothServiceAdvertiser::RunError(TInt aError) 00227 { 00228 switch (iState) 00229 { 00230 case EConnecting: 00231 break; 00232 case EBuildingServiceRecord: 00233 // Delete SDP Record 00234 if (iRecordHandle) 00235 { 00236 TRAPD(err,iSdpDatabase.DeleteRecordL(iRecordHandle)); 00237 } 00238 // Close SDP handles 00239 iSdpDatabase.Close(); 00240 iSdpServ.Close(); 00241 break; 00242 default: 00243 aError = KErrCorrupt; 00244 break; 00245 }; 00246 00247 iState = EIdle; 00248 iSerAdvObs.ReportAdvertiserErr(aError); 00249 return KErrNone; 00250 }