datasourcemodules/bluetoothgpspositioningmodule/btgpsconfig/src/lbsbtgpsconfigimpl.cpp
changeset 0 9cfd9a3ee49c
child 52 29dbbeac905d
equal deleted inserted replaced
-1:000000000000 0:9cfd9a3ee49c
       
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // LBS Bluetooth GPS Configuration API implementation
       
    15 //
       
    16 
       
    17 #include "lbsbtgpsconfigimpl.h"
       
    18 #include <centralrepository.h>
       
    19 
       
    20 /** LBS Bluetooth GPS Configuration central repository UID
       
    21 @internalComponent
       
    22 */
       
    23 const TUint32 KLbsBtGpsConfigRepositoryUid = 0x102869C1;
       
    24 
       
    25 //-------------------------------------------------------
       
    26 // CENREP FORMAT
       
    27 //
       
    28 // key format: 0xAAAABBBB
       
    29 // where:
       
    30 //   AAAA = Device index
       
    31 //   BBBB = Setting index
       
    32 
       
    33 const TUint32 KDeviceIndexMask			= 0xFFFF0000;
       
    34 const TUint32 KDeviceIndexShift			= 16;
       
    35 
       
    36 // Maximum number of devices allowed in the list
       
    37 const TUint32 KMaxDevices 				= 20;
       
    38 
       
    39 // Index of first device in the list
       
    40 const TUint32 KFirstDeviceIndex 		= 0x0001;
       
    41 
       
    42 // GENERAL SETTINGS (stored under device index 0000)
       
    43 
       
    44 // Centrep data version
       
    45 //const TUint32 KSettingVersion 			= 0x00000000;
       
    46 
       
    47 // Stores the last allocated unique device key
       
    48 const TUint32 KSettingLastKey 			= 0x00000001;
       
    49 
       
    50 // Stores the number of devices in the list
       
    51 const TUint32 KSettingNumDevices 		= 0x00000002;
       
    52 
       
    53 // PER-DEVICE SETTINGS (BBBB)
       
    54 
       
    55 // Unique key identifying the device
       
    56 const TUint32 KDeviceSettingKey			= 0x0000;
       
    57 
       
    58 // Device type
       
    59 const TUint32 KDeviceSettingType		= 0x0001;
       
    60 
       
    61 // Device bluetooth socket address
       
    62 const TUint32 KDeviceSettingSockAddr	= 0x0002;
       
    63 //-------------------------------------------------------
       
    64 
       
    65 // Partial key and mask for centrep notifications - notify on all changes
       
    66 const TUint32 KNotifyPartialKey = 0x00000000;
       
    67 const TUint32 KNotifyMask = 0x00000000;
       
    68 
       
    69 
       
    70 // Number of times to retry if the repository is locked
       
    71 const TInt KLockedRetries = 10000;
       
    72 
       
    73 // Time to wait before retrying if the repository is locked
       
    74 const TInt KLockedRetryDelay = 100;
       
    75 
       
    76 
       
    77 /** Static constructor (with observer)
       
    78 Creates an instance of the LBS Bluetooth GPS Configuration API implementation, 
       
    79 specifying a callback to recieve update notifications.
       
    80 
       
    81 @param aObserver [IN] Observer which will recieve update notifications.
       
    82 
       
    83 @return A newly constructed CLbsBtGpsConfigImpl object.
       
    84 
       
    85 @capability LocalServices
       
    86 
       
    87 @internalComponent
       
    88 */
       
    89 CLbsBtGpsConfigImpl* CLbsBtGpsConfigImpl::NewL(MLbsBtGpsConfigObserver* aObserver)
       
    90 	{
       
    91 	// Check capabilities first
       
    92 	RProcess process;
       
    93 	if (!process.HasCapability(ECapabilityLocalServices))
       
    94 		{
       
    95 		User::Leave(KErrPermissionDenied);
       
    96 		}
       
    97 	
       
    98 	CLbsBtGpsConfigImpl* self = new (ELeave) CLbsBtGpsConfigImpl(aObserver);
       
    99     CleanupStack::PushL(self);
       
   100     self->ConstructL();
       
   101     CleanupStack::Pop(self);
       
   102     return self;
       
   103 	}
       
   104 
       
   105 
       
   106 /** Destructor 
       
   107 @internalComponent
       
   108 */
       
   109 CLbsBtGpsConfigImpl::~CLbsBtGpsConfigImpl()
       
   110 	{
       
   111 	Cancel();
       
   112 	delete iRepos;
       
   113 	}
       
   114 
       
   115 
       
   116 /** Returns the number of devices present in the list
       
   117 
       
   118 @return Number of devices.
       
   119 
       
   120 @leave KErrPermissionDenied if the client does not have the required capabilities.
       
   121 
       
   122 @capability LocalServices
       
   123 
       
   124 @internalComponent
       
   125 */
       
   126 TInt CLbsBtGpsConfigImpl::GetDeviceCount(TInt& aCount)
       
   127 	{
       
   128 	// Check capabilities first
       
   129 	RProcess process;
       
   130 	if (!process.HasCapability(ECapabilityLocalServices))
       
   131 		{
       
   132 		return KErrPermissionDenied;
       
   133 		}
       
   134 
       
   135 	TInt err = iRepos->Get(KSettingNumDevices, aCount); 
       
   136 	if (err == KErrNotFound)
       
   137 		{
       
   138 		// If the entry is not found, the number of devices is zero.
       
   139 		// Don't treat this as an error.
       
   140 		aCount = 0;
       
   141 		err = KErrNone;
       
   142 		}
       
   143 	
       
   144 	return err;
       
   145 	}
       
   146 
       
   147 
       
   148 /** Adds a new device at the specified position index within the list
       
   149 
       
   150 @param aAddress [In] Address of the new device.
       
   151 @param aPosition [In] Position in the list at which to add the device, note that any existing entries below this position will be shifted down.
       
   152 @param aKey [Out] Recieves the unique key assigned to identify the new device.
       
   153 
       
   154 Specifying aPosition >= DeviceCount() will result in the device being added to the end of the list.
       
   155 
       
   156 @return KErrNone if the operation succeeded.
       
   157 		KErrAlreadyExists if an entry with the same address is already present in the list.
       
   158 		KErrOverflow if there is no space left to add another entry.
       
   159 		KErrPermissionDenied if the client does not have the required capabilities.
       
   160 
       
   161 @capability LocalServices
       
   162 @capability WriteDeviceData
       
   163 
       
   164 @internalComponent
       
   165 */
       
   166 TInt CLbsBtGpsConfigImpl::AddDevice(const TBTDevAddr& aAddress, TInt aPosition, TLbsBtGpsEntryKey& aKey)
       
   167 	{
       
   168 	// Check capabilities first
       
   169 	RProcess process;
       
   170 	if (!process.HasCapability(ECapabilityLocalServices))
       
   171 		{
       
   172 		return KErrPermissionDenied;
       
   173 		}
       
   174 	if (!process.HasCapability(ECapabilityWriteDeviceData))
       
   175 		{
       
   176 		return KErrPermissionDenied;
       
   177 		}
       
   178 	 
       
   179 	TRAPD(err, AddDeviceL(aAddress, aPosition, aKey));
       
   180 	return err;
       
   181 	}
       
   182 
       
   183 
       
   184 /** Removes a device from the list
       
   185 
       
   186 @param aKey [In] The key identifying the device.
       
   187 
       
   188 @return KErrNone if the operation succeeded.
       
   189 		KErrNotFound if the specified device is not present in the list.
       
   190 		KErrPermissionDenied if the client does not have the required capabilities.
       
   191 
       
   192 @capability LocalServices
       
   193 @capability WriteDeviceData
       
   194 
       
   195 @internalComponent
       
   196 */
       
   197 TInt CLbsBtGpsConfigImpl::RemoveDevice(TLbsBtGpsEntryKey aKey)
       
   198 	{
       
   199 	// Check capabilities first
       
   200 	RProcess process;
       
   201 	if (!process.HasCapability(ECapabilityLocalServices))
       
   202 		{
       
   203 		return KErrPermissionDenied;
       
   204 		}
       
   205 	if (!process.HasCapability(ECapabilityWriteDeviceData))
       
   206 		{
       
   207 		return KErrPermissionDenied;
       
   208 		}
       
   209 
       
   210 	TRAPD(err, RemoveDeviceL(aKey));
       
   211 	return err;
       
   212 	}
       
   213 
       
   214 
       
   215 /** Empties the device list, removing all device entries
       
   216 
       
   217 @return KErrNone if the operation succeeded.
       
   218 		KErrPermissionDenied if the client does not have the required capabilities.
       
   219 
       
   220 @capability LocalServices
       
   221 @capability WriteDeviceData
       
   222 
       
   223 @internalComponent
       
   224 */
       
   225 TInt CLbsBtGpsConfigImpl::EmptyDeviceList()
       
   226 	{
       
   227 	// Check capabilities first
       
   228 	RProcess process;
       
   229 	if (!process.HasCapability(ECapabilityLocalServices))
       
   230 		{
       
   231 		return KErrPermissionDenied;
       
   232 		}
       
   233 	if (!process.HasCapability(ECapabilityWriteDeviceData))
       
   234 		{
       
   235 		return KErrPermissionDenied;
       
   236 		}
       
   237 
       
   238 	TRAPD(err, EmptyDeviceListL());
       
   239 	return err;
       
   240 	}
       
   241 
       
   242 
       
   243 /** Reorders a device in the list by specifying a new position index
       
   244 
       
   245 @param aKey [In] The key identifying the device.
       
   246 @param aNewPosition [In] New position index for the device in the list (where 0 indicates the start of the list).
       
   247 
       
   248 The device identified by the key will assume the specified position in the list, shifting exsiting devices as
       
   249 required in order to achieve this.
       
   250 
       
   251 Specifying aNewPosition = 0 will result in the device being moved to the start of the list.
       
   252 Specifying aNewPosition >= DeviceCount() will result in the device being moved to the end of the list.
       
   253 
       
   254 When a device is moved towards the start of the list, other devices located between the old and new positions 
       
   255 will be shifted towards the end of the list by one place. For example, starting with a list {A,B,C,D,E}, moving 
       
   256 device D to position 1 would result in {A,D,B,C,E}. 
       
   257 
       
   258 Similarly, when a device is moved towards the end of the list, other devices located between the old and new
       
   259 positions will be shifted towards the start of the list by one place. For example, starting with a list {A,B,C,D,E},
       
   260 moving device B to position 3 would result in {A,C,D,B,E}
       
   261 
       
   262 @return KErrNone if the operation succeeded.
       
   263 		ErrNotFound if the specified device is not present in the list.
       
   264 		KErrPermissionDenied if the client does not have the required capabilities.
       
   265 
       
   266 @capability LocalServices
       
   267 @capability WriteDeviceData
       
   268 
       
   269 @internalComponent
       
   270 */
       
   271 TInt CLbsBtGpsConfigImpl::ReorderDevice(TLbsBtGpsEntryKey aKey, TInt aNewPosition)
       
   272 	{
       
   273 	// Check capabilities first
       
   274 	RProcess process;
       
   275 	if (!process.HasCapability(ECapabilityLocalServices))
       
   276 		{
       
   277 		return KErrPermissionDenied;
       
   278 		}
       
   279 	if (!process.HasCapability(ECapabilityWriteDeviceData))
       
   280 		{
       
   281 		return KErrPermissionDenied;
       
   282 		}
       
   283 
       
   284 	TRAPD(err, ReorderDeviceL(aKey, aNewPosition));
       
   285 	return err;
       
   286 	}
       
   287 
       
   288 
       
   289 /** Retrieves the list of devices
       
   290 
       
   291 @param aList [Out] Reference to an empty RPointerArray to populate with device entries from the list.
       
   292 
       
   293 @leave KErrPermissionDenied if the client does not have the required capabilities.
       
   294 
       
   295 @capability LocalServices
       
   296 
       
   297 @internalComponent
       
   298 */
       
   299 void CLbsBtGpsConfigImpl::GetDeviceListL(RPointerArray<TLbsBtGpsDeviceInfo>& aList)
       
   300 	{
       
   301 	// Check capabilities first
       
   302 	RProcess process;
       
   303 	if (!process.HasCapability(ECapabilityLocalServices))
       
   304 		{
       
   305 		User::Leave(KErrPermissionDenied);
       
   306 		}
       
   307 
       
   308 	// Attempt to start a transaction
       
   309 	User::LeaveIfError(StartTransactionL(CRepository::EReadTransaction));
       
   310 
       
   311 	TInt deviceCount;
       
   312 	User::LeaveIfError(GetDeviceCount(deviceCount));
       
   313 
       
   314 	for (TInt index=0; index<deviceCount; ++index)
       
   315 		{
       
   316 		
       
   317 		TLbsBtGpsDeviceRecord devRecord;
       
   318 		
       
   319 		if (ReadDeviceRecord(index, devRecord) == KErrNone)
       
   320 			{
       
   321 			TLbsBtGpsDeviceInfo* devInfo = new (ELeave) TLbsBtGpsDeviceInfo();
       
   322 			CleanupStack::PushL(devInfo);
       
   323 			devInfo->SetKey(devRecord.Key());
       
   324 			devInfo->SetAddress(devRecord.SocketAddress().BTAddr());
       
   325 			devInfo->SetType(devRecord.Type());
       
   326 			aList.Append(devInfo);
       
   327 			CleanupStack::Pop(devInfo);
       
   328 			}
       
   329 		
       
   330 		}
       
   331 
       
   332 	// End central repository transaction
       
   333 	User::LeaveIfError(EndTransaction());
       
   334 	}
       
   335 	
       
   336 
       
   337 /**	This methods is reserved for future expansion and should not be used
       
   338 
       
   339 @param aFunctionNumber Reserved for future expansion
       
   340 @param aPtr1 Reserved for future expansion
       
   341 @param aPtr2 Reserved for future expansion
       
   342 
       
   343 @capability LocalServices
       
   344 
       
   345 @internalComponent
       
   346 */								
       
   347 TAny* CLbsBtGpsConfigImpl::ExtendedInterface(TInt /*aFunctionNumber*/, TAny* /*aPtr1*/, TAny* /*aPtr2*/)
       
   348 	{
       
   349 	return NULL;
       
   350 	}
       
   351 
       
   352 
       
   353 // ------------------ Internal API methods ------------------
       
   354 
       
   355 
       
   356 /** Updates the device information for a device in the list
       
   357 
       
   358 @param aDeviceInfo [In] The updated device info for the specified device. The key should identify an existing device in the list.
       
   359 
       
   360 @return KErrNone if the operation succeeded.
       
   361 		KErrNotFound if the specified device is not present in the list.
       
   362 		KErrPermissionDenied if the client does not have the required capabilities.
       
   363 
       
   364 @capability LocalServices
       
   365 @capability WriteDeviceData
       
   366 
       
   367 @internalComponent
       
   368 */
       
   369 TInt CLbsBtGpsConfigImpl::UpdateDevice(const TLbsBtGpsDeviceRecord& aDeviceRecord)
       
   370 	{
       
   371 	// Check capabilities first
       
   372 	RProcess process;
       
   373 	if (!process.HasCapability(ECapabilityLocalServices))
       
   374 		{
       
   375 		return KErrPermissionDenied;
       
   376 		}
       
   377 	if (!process.HasCapability(ECapabilityWriteDeviceData))
       
   378 		{
       
   379 		return KErrPermissionDenied;
       
   380 		}
       
   381 
       
   382 	TRAPD(err, UpdateDeviceL(aDeviceRecord));
       
   383 	return err;
       
   384 	}
       
   385 
       
   386 
       
   387 /** Retrieves the list of device records
       
   388 
       
   389 @param aList [Out] Reference to an empty RPointerArray to populate with device records from the list.
       
   390 
       
   391 @leave KErrPermissionDenied if the client does not have the required capabilities.
       
   392 
       
   393 @capability LocalServices
       
   394 
       
   395 @internalComponent
       
   396 */
       
   397 void CLbsBtGpsConfigImpl::GetDeviceRecordListL(RPointerArray<TLbsBtGpsDeviceRecord>& aRecordList)
       
   398 	{
       
   399 	// Check capabilities first
       
   400 	RProcess process;
       
   401 	if (!process.HasCapability(ECapabilityLocalServices))
       
   402 		{
       
   403 		User::Leave(KErrPermissionDenied);
       
   404 		}
       
   405 	
       
   406 	// Attempt to start a transaction
       
   407 	User::LeaveIfError(StartTransactionL(CRepository::EReadTransaction));
       
   408 
       
   409 	// Get the number of devices in the list
       
   410 	TInt deviceCount;
       
   411 	User::LeaveIfError(GetDeviceCount(deviceCount));
       
   412 
       
   413 	for (TInt index=0; index<deviceCount; ++index)
       
   414 		{
       
   415 		// Create a new record container
       
   416 		TLbsBtGpsDeviceRecord* devRecord = new (ELeave) TLbsBtGpsDeviceRecord();
       
   417 		CleanupStack::PushL(devRecord);
       
   418 
       
   419 		// Read the record into the container
       
   420 		User::LeaveIfError(ReadDeviceRecord(index, *devRecord));
       
   421 
       
   422 		// Add to the passes list
       
   423 		aRecordList.Append(devRecord);
       
   424 		
       
   425 		CleanupStack::Pop(devRecord);
       
   426 		}
       
   427 
       
   428 	// End central repository transaction
       
   429 	User::LeaveIfError(EndTransaction());
       
   430 	}
       
   431 
       
   432 
       
   433 // ------------------ Protected methods ------------------
       
   434 
       
   435 
       
   436 /**	Active object DoCancel method
       
   437 @internalComponent
       
   438 */								
       
   439 void CLbsBtGpsConfigImpl::DoCancel()
       
   440 	{
       
   441 	iRepos->NotifyCancel(KNotifyPartialKey, KNotifyMask);
       
   442 	}
       
   443 
       
   444 
       
   445 /**	Active object RunL method
       
   446 @internalComponent
       
   447 */								
       
   448 void CLbsBtGpsConfigImpl::RunL()
       
   449 	{
       
   450 	if (iObserver)
       
   451 		{
       
   452 		iObserver->OnDeviceListUpdate();
       
   453 		iRepos->NotifyRequest(KNotifyPartialKey, KNotifyMask, iStatus);
       
   454 		SetActive();
       
   455 		}
       
   456 	}
       
   457 
       
   458 
       
   459 /** Adds a new device at the specified position index within the list - leaving version
       
   460 
       
   461 @see AddDevice
       
   462 
       
   463 @internalComponent
       
   464 */
       
   465 void CLbsBtGpsConfigImpl::AddDeviceL(const TBTDevAddr& aAddress, TInt aPosition, TLbsBtGpsEntryKey& aKey)
       
   466 	{
       
   467 	TInt err;
       
   468 	TInt index;
       
   469 		
       
   470 	aKey = KLbsBtGpsEntryKeyNull;
       
   471 
       
   472 	// Attempt to start a transaction
       
   473 	User::LeaveIfError(StartTransactionL(CRepository::EReadWriteTransaction));
       
   474 
       
   475 	// Retrieve the current number of devices in the list
       
   476 	TInt deviceCount;
       
   477 	User::LeaveIfError(GetDeviceCount(deviceCount));
       
   478 
       
   479 	// Check that the desired position is in range, adjust if required
       
   480 	if (aPosition < 0 || aPosition > deviceCount)
       
   481 		{
       
   482 		aPosition = deviceCount;
       
   483 		}
       
   484 
       
   485 	// Leave if we've reached the maximum number of devices allowed in the list
       
   486 	if (deviceCount >= KMaxDevices)
       
   487 		{
       
   488 		User::Leave(KErrOverflow);
       
   489 		}
       
   490 
       
   491 	// Device record container
       
   492 	TLbsBtGpsDeviceRecord devRecord;
       
   493 	
       
   494 	// Leave if a device with this address is already present in the list
       
   495 	for (index=0; index<deviceCount; ++index)
       
   496 		{
       
   497 		User::LeaveIfError(ReadDeviceRecord(index, devRecord));
       
   498 
       
   499 		if (devRecord.SocketAddress().BTAddr() == aAddress)
       
   500 			{
       
   501 			// Return the key identifying the existing device
       
   502 			aKey = devRecord.Key();
       
   503 			User::Leave(KErrAlreadyExists);
       
   504 			}
       
   505 		}
       
   506 	
       
   507 	// Read the last allocated device key
       
   508 	TInt key;
       
   509 	err = iRepos->Get(KSettingLastKey, key);
       
   510 	if (err == KErrNotFound)
       
   511 		{
       
   512 		// Value not present in centrep, initialise sequence to NULL key
       
   513 		key = KLbsBtGpsEntryKeyNull;
       
   514 		}
       
   515 	else
       
   516 		{
       
   517 		User::LeaveIfError(err);
       
   518 		}
       
   519 
       
   520 	// Increment to get next available key to assign to the new device 
       
   521 	++key;
       
   522 	
       
   523 	// Write current key
       
   524 	User::LeaveIfError(iRepos->Set(KSettingLastKey, key));
       
   525 
       
   526 	// Move all entries following the desired position down one place, starting from the end
       
   527 	for (index=deviceCount-1; index>=aPosition; --index)
       
   528 		{
       
   529 		User::LeaveIfError(MoveDeviceRecord(index, index+1));
       
   530 		}
       
   531 		
       
   532 	// Build a device record to add to the list
       
   533 	devRecord.SetKey(key);
       
   534 
       
   535 	TBTSockAddr sockAddr;
       
   536 	sockAddr.SetBTAddr(aAddress);
       
   537 	devRecord.SetSocketAddress(sockAddr);
       
   538 
       
   539 	// Set unknown type for new devices
       
   540 	devRecord.SetType(TLbsBtGpsDeviceInfo::ELbsBtGpsDeviceUnknown);
       
   541 
       
   542 	// Write the new device record at the desired position
       
   543 	User::LeaveIfError(WriteDeviceRecord(aPosition, devRecord));
       
   544 
       
   545 	// Increment device counter and write to cenrep
       
   546 	++deviceCount;
       
   547 	User::LeaveIfError(iRepos->Set(KSettingNumDevices, deviceCount));
       
   548 	
       
   549 	// End central repository transaction
       
   550 	User::LeaveIfError(EndTransaction());
       
   551 
       
   552 	// Set key to return to client now the transaction has succeeded
       
   553 	aKey = key;
       
   554 	}
       
   555 
       
   556 
       
   557 /** Removes a device from the list - leaving version
       
   558 
       
   559 @see RemoveDevice
       
   560 
       
   561 @internalComponent
       
   562 */
       
   563 void CLbsBtGpsConfigImpl::RemoveDeviceL(TLbsBtGpsEntryKey aKey)
       
   564 	{
       
   565 	// Attempt to start a transaction
       
   566 	User::LeaveIfError(StartTransactionL(CRepository::EReadWriteTransaction));
       
   567 
       
   568 	// Get the number of devices in the list
       
   569 	TInt deviceCount;
       
   570 	User::LeaveIfError(GetDeviceCount(deviceCount));
       
   571 
       
   572 	// Flag to indicate if we have found the device record yet
       
   573 	TBool foundDevice = EFalse;
       
   574 
       
   575 	// Device record container
       
   576 	TLbsBtGpsDeviceRecord devRecord;
       
   577 
       
   578 	// Look for the device record
       
   579 	for (TInt index=0; index<deviceCount; ++index)
       
   580 		{
       
   581 		User::LeaveIfError(ReadDeviceRecord(index, devRecord));
       
   582 
       
   583 		if (foundDevice)
       
   584 			{
       
   585 			// Move following records up one place
       
   586 			User::LeaveIfError(MoveDeviceRecord(index, index-1));
       
   587 			}
       
   588 		else if (devRecord.Key() == aKey)
       
   589 			{
       
   590 			// Found the device record, delete it from cenrep
       
   591 			foundDevice = ETrue;
       
   592 			
       
   593 			TUint32 keyBase = (KFirstDeviceIndex + index) << KDeviceIndexShift;
       
   594 			TUint32 errKey;
       
   595 				
       
   596 			User::LeaveIfError(iRepos->Delete(keyBase, KDeviceIndexMask, errKey));
       
   597 			}
       
   598 		}
       
   599 
       
   600 	if (!foundDevice)
       
   601 		{
       
   602 		User::Leave(KErrNotFound);
       
   603 		}
       
   604 
       
   605 	// Decrement device counter and write to cenrep
       
   606 	--deviceCount;
       
   607 	User::LeaveIfError(iRepos->Set(KSettingNumDevices, deviceCount));
       
   608 	
       
   609 	// End central repository transaction
       
   610 	User::LeaveIfError(EndTransaction());
       
   611 	}
       
   612 
       
   613 
       
   614 /** Empties the device list, removing all device entries - leaving version
       
   615 
       
   616 @see EmptyDeviceList
       
   617 
       
   618 @internalComponent
       
   619 */
       
   620 void CLbsBtGpsConfigImpl::EmptyDeviceListL()
       
   621 	{
       
   622 	// Read last allocated device key as we want to save this
       
   623 	TInt key;
       
   624 	TInt err = iRepos->Get(KSettingLastKey, key);
       
   625 	if (err == KErrNotFound)
       
   626 		{
       
   627 		// Value not present in centrep, initialise sequence to NULL key
       
   628 		key = KLbsBtGpsEntryKeyNull;
       
   629 		}
       
   630 	else if (err != KErrNone)
       
   631 		{
       
   632 		User::Leave(err);
       
   633 		}
       
   634 
       
   635 	// Reset the repository
       
   636 	User::LeaveIfError(iRepos->Reset());
       
   637 
       
   638 	// Write back last key value
       
   639 	User::LeaveIfError(iRepos->Set(KSettingLastKey, key));
       
   640 	}
       
   641 
       
   642 
       
   643 /** Reorders a device in the list by specifying a new position index - leaving version
       
   644 
       
   645 @see ReorderDevice
       
   646 
       
   647 @internalComponent
       
   648 */
       
   649 void CLbsBtGpsConfigImpl::ReorderDeviceL(TLbsBtGpsEntryKey aKey, TInt aNewPosition)
       
   650 	{
       
   651 	// Attempt to start a transaction
       
   652 	User::LeaveIfError(StartTransactionL(CRepository::EReadWriteTransaction));
       
   653 
       
   654 	// Get the number of devices in the list
       
   655 	TInt deviceCount;
       
   656 	User::LeaveIfError(GetDeviceCount(deviceCount));
       
   657 
       
   658 	// Check that the desired position is in range, adjust if required
       
   659 	if (aNewPosition < 0 || aNewPosition >= deviceCount)
       
   660 		{
       
   661 		aNewPosition = deviceCount-1;
       
   662 		}
       
   663 	
       
   664 	// This will store the current position of the device, if found
       
   665 	TInt oldPosition = KErrNotFound;
       
   666 
       
   667 	// This will store the device record while we move it
       
   668 	TLbsBtGpsDeviceRecord devRecord;
       
   669 	
       
   670 	// Look for the device entry to move
       
   671 	TInt index;
       
   672 	for (index=0; index<deviceCount; ++index)
       
   673 		{
       
   674 		User::LeaveIfError(ReadDeviceRecord(index, devRecord));
       
   675 
       
   676 		if (devRecord.Key() == aKey)
       
   677 			{
       
   678 			// Found the device record
       
   679 			oldPosition = index;
       
   680 			break;
       
   681 			}
       
   682 		}
       
   683 
       
   684 	// Leave if the device entry to move cannot be found in the list
       
   685 	if (oldPosition == KErrNotFound)
       
   686 		{
       
   687 		User::Leave(KErrNotFound);
       
   688 		}
       
   689 
       
   690 	// Check if device record needs to be moved
       
   691 	if (oldPosition != aNewPosition)
       
   692 		{
       
   693 		// Delete the record from cenrep
       
   694 		TUint32 keyBase = (KFirstDeviceIndex + oldPosition) << KDeviceIndexShift;
       
   695 		TUint32 errKey;
       
   696 		User::LeaveIfError(iRepos->Delete(keyBase, KDeviceIndexMask, errKey));
       
   697 	
       
   698 		if (oldPosition < aNewPosition)
       
   699 			{
       
   700 			// Moving towards the end of the list - shift intermediate entries up one place
       
   701 			for (index = oldPosition + 1; index <= aNewPosition; ++index)
       
   702 				{
       
   703 				User::LeaveIfError(MoveDeviceRecord(index,index-1));
       
   704 				}
       
   705 			}
       
   706 		else if (oldPosition > aNewPosition)
       
   707 			{
       
   708 			// Moving towards the start of the list - shift intermediate entries down one place
       
   709 			for (index = oldPosition - 1; index >= aNewPosition; --index)
       
   710 				{
       
   711 				User::LeaveIfError(MoveDeviceRecord(index,index+1));
       
   712 				}
       
   713 			}
       
   714 	
       
   715 		// Write the record at the new position 
       
   716 		User::LeaveIfError(WriteDeviceRecord(aNewPosition, devRecord));
       
   717 		}
       
   718 	
       
   719 	// End central repository transaction
       
   720 	User::LeaveIfError(EndTransaction());
       
   721 	}
       
   722 
       
   723 
       
   724 /** Updates the device information for a device in the list - leaving version
       
   725 
       
   726 @see UpdateDevice
       
   727 
       
   728 @internalComponent
       
   729 */
       
   730 void CLbsBtGpsConfigImpl::UpdateDeviceL(const TLbsBtGpsDeviceRecord& aDeviceRecord)
       
   731 	{
       
   732 	// Attempt to start a transaction
       
   733 	User::LeaveIfError(StartTransactionL(CRepository::EReadWriteTransaction));
       
   734 
       
   735 	// Get the number of devices in the list
       
   736 	TInt deviceCount;
       
   737 	User::LeaveIfError(GetDeviceCount(deviceCount));
       
   738 
       
   739 	// Flag to indicate if we have found the device record yet
       
   740 	TBool foundDevice = EFalse;
       
   741 
       
   742 	// Device record container
       
   743 	TLbsBtGpsDeviceRecord devRecord;
       
   744 
       
   745 	// Look for the device record
       
   746 	for (TInt index=0; index<deviceCount; ++index)
       
   747 		{
       
   748 		User::LeaveIfError(ReadDeviceRecord(index, devRecord));
       
   749 
       
   750 		if (devRecord.Key() == aDeviceRecord.Key())
       
   751 			{
       
   752 			// Found the device record, update it with the new one passed in
       
   753 			foundDevice = ETrue;
       
   754 			User::LeaveIfError(WriteDeviceRecord(index, aDeviceRecord));
       
   755 			break;
       
   756 			}
       
   757 		}
       
   758 
       
   759 	if (!foundDevice)
       
   760 		{
       
   761 		User::Leave(KErrNotFound);
       
   762 		}
       
   763 	
       
   764 	// End central repository transaction
       
   765 	User::LeaveIfError(EndTransaction());
       
   766 	}
       
   767 
       
   768 
       
   769 /** Attempt to start a central repository transaction 
       
   770 
       
   771 @return KErrNone if the operation succeeded.
       
   772  
       
   773 @internalComponent
       
   774 */
       
   775 TInt CLbsBtGpsConfigImpl::StartTransactionL(CRepository::TTransactionMode aMode)
       
   776 	{
       
   777 	TInt retries = 0;
       
   778 
       
   779 	while (ETrue)
       
   780 		{
       
   781 		// Attempt to start the transaction
       
   782 		TInt err = iRepos->StartTransaction(aMode);
       
   783 		
       
   784 		if (err == KErrNone)
       
   785 			{
       
   786 			// Transaction started succesfully
       
   787 			break;
       
   788 			}
       
   789 		else if (err == KErrLocked && (retries++ < KLockedRetries)) 
       
   790 			{
       
   791 			// Repository is locked by another client, wait before retrying
       
   792 			User::After(TTimeIntervalMicroSeconds32(KLockedRetryDelay));
       
   793 			}
       
   794 		else
       
   795 			{
       
   796 			// Another error occurred, or maximum number of retries reached
       
   797 			return err;
       
   798 			}
       
   799 		}
       
   800 
       
   801 	// Make sure the transaction is cancelled if something goes wrong
       
   802 	iRepos->CleanupCancelTransactionPushL();
       
   803 	
       
   804 	return KErrNone;
       
   805 	}
       
   806 
       
   807 
       
   808 /** End (commit) a central repository transaction 
       
   809 
       
   810 @return KErrNone if the operation succeeded.
       
   811  
       
   812 @internalComponent
       
   813 */
       
   814 TInt CLbsBtGpsConfigImpl::EndTransaction()
       
   815 	{
       
   816 	CleanupStack::Pop(); // CleanupCancelTransaction
       
   817 
       
   818 	TUint32 errKey;
       
   819 	return iRepos->CommitTransaction(errKey);
       
   820 	}
       
   821 
       
   822 
       
   823 /** Read a device record from cenrep by index 
       
   824 
       
   825 @param aIndex [In] The index of the device entry to read
       
   826 @param aDeviceInfo [Out] Device info to fill from cenrep  
       
   827 
       
   828 StartTransaction should have been called.
       
   829 
       
   830 @internalComponent
       
   831 */
       
   832 TInt CLbsBtGpsConfigImpl::ReadDeviceRecord(TInt aIndex, TLbsBtGpsDeviceRecord& aDeviceRecord)
       
   833 	{
       
   834 	TInt err;
       
   835 	TUint32 keyBase = (KFirstDeviceIndex + aIndex) << KDeviceIndexShift;
       
   836 
       
   837 	TInt deviceKey;
       
   838 	err = iRepos->Get(keyBase | KDeviceSettingKey, deviceKey);
       
   839 	if (err != KErrNone)
       
   840 		{
       
   841 		return err;
       
   842 		}
       
   843 	aDeviceRecord.SetKey(deviceKey);
       
   844 
       
   845 	TInt deviceType;
       
   846 	err = iRepos->Get(keyBase | KDeviceSettingType, deviceType);
       
   847 	if (err != KErrNone)
       
   848 		{
       
   849 		return err;
       
   850 		}
       
   851 	aDeviceRecord.SetType(deviceType);
       
   852 
       
   853 	TBuf<KMaxSockAddrSize> addressBuffer;
       
   854 	err = iRepos->Get(keyBase | KDeviceSettingSockAddr, addressBuffer);
       
   855 	if (err != KErrNone)
       
   856 		{
       
   857 		return err;
       
   858 		}
       
   859 	TBTSockAddr address; 
       
   860 	address.Copy(addressBuffer);
       
   861 	aDeviceRecord.SetSocketAddress(address);
       
   862 	
       
   863 	return KErrNone;
       
   864 	}
       
   865 
       
   866 
       
   867 /** Write a device record to cenrep by index
       
   868 
       
   869 @param aIndex [In] The index of the device entry to write
       
   870 @param aDeviceInfo [Out] Device info to write to cenrep  
       
   871 
       
   872 StartTransaction should have been called.
       
   873 
       
   874 @internalComponent
       
   875 */
       
   876 TInt CLbsBtGpsConfigImpl::WriteDeviceRecord(TInt aIndex, const TLbsBtGpsDeviceRecord& aDeviceRecord)
       
   877 	{
       
   878 	TInt err;
       
   879 	TUint32 keyBase = (KFirstDeviceIndex + aIndex) << KDeviceIndexShift;
       
   880 	
       
   881 	TInt deviceKey = aDeviceRecord.Key();
       
   882 	err = iRepos->Set(keyBase | KDeviceSettingKey, deviceKey);
       
   883 	if (err != KErrNone)
       
   884 		{
       
   885 		return err;
       
   886 		}
       
   887 	
       
   888 	TInt deviceType = aDeviceRecord.Type();
       
   889 	err = iRepos->Set(keyBase | KDeviceSettingType, deviceType);
       
   890 	if (err != KErrNone)
       
   891 		{
       
   892 		return err;
       
   893 		}
       
   894 
       
   895 	TBuf<KMaxSockAddrSize> addressBuffer;
       
   896 	addressBuffer.Copy(aDeviceRecord.SocketAddress());
       
   897 	err = iRepos->Set(keyBase | KDeviceSettingSockAddr, addressBuffer);
       
   898 	if (err != KErrNone)
       
   899 		{
       
   900 		return err;
       
   901 		}
       
   902 	
       
   903 	return KErrNone;
       
   904 	}
       
   905 
       
   906 
       
   907 /** Move a device record from old to new position
       
   908 
       
   909 @param aOldIndex [In] The current index of the device record in the list
       
   910 @param aOldIndex [In] The new index of the device record in the list  
       
   911 
       
   912 StartTransaction should have been called.
       
   913 
       
   914 @internalComponent
       
   915 */
       
   916 TInt CLbsBtGpsConfigImpl::MoveDeviceRecord(TInt aOldIndex, TInt aNewIndex)
       
   917 	{
       
   918 	TUint32 oldKeyBase = (KFirstDeviceIndex + aOldIndex) << KDeviceIndexShift;
       
   919 	TUint32 newKeyBase = (KFirstDeviceIndex + aNewIndex) << KDeviceIndexShift;
       
   920 	TUint32 errKey;
       
   921 		
       
   922 	return iRepos->Move(oldKeyBase, newKeyBase, KDeviceIndexMask, errKey);
       
   923 	}
       
   924 
       
   925 
       
   926 /** Class constructor 
       
   927 
       
   928 @param aObserver [IN] Optional observer, which will recieve update notifications.
       
   929 
       
   930 @internalComponent
       
   931 */
       
   932 CLbsBtGpsConfigImpl::CLbsBtGpsConfigImpl(MLbsBtGpsConfigObserver* aObserver)
       
   933 : CActive(CActive::EPriorityStandard),
       
   934   iObserver(aObserver)
       
   935 	{
       
   936 	CActiveScheduler::Add(this);
       
   937 	}
       
   938 
       
   939 
       
   940 /** Second phase constructor 
       
   941 @internalComponent
       
   942 */
       
   943 void CLbsBtGpsConfigImpl::ConstructL()
       
   944 	{
       
   945 	iRepos = CRepository::NewL(TUid::Uid(KLbsBtGpsConfigRepositoryUid));
       
   946 	iRepos->NotifyRequest(KNotifyPartialKey, KNotifyMask, iStatus);
       
   947 	SetActive();
       
   948 	}