|
1 // Copyright (c) 1999-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 // This does the main work on behalf of the subsessions of liasing with DBMS |
|
15 // |
|
16 // |
|
17 |
|
18 #include "BTRegistryDB.h" |
|
19 #include "btmanserverutil.h" |
|
20 #include <utf.h> |
|
21 #include <bluetooth/logger.h> |
|
22 #include <bafl/sysutil.h> |
|
23 |
|
24 #ifdef __FLOG_ACTIVE |
|
25 _LIT8(KLogComponent, LOG_COMPONENT_BT_REGISTRY); |
|
26 #endif |
|
27 |
|
28 #ifdef _DEBUG |
|
29 PANICCATEGORY("btregdb"); |
|
30 #endif |
|
31 |
|
32 |
|
33 void Panic(TBTRegistryDBPanic aPanic) |
|
34 { |
|
35 LOG_STATIC_FUNC |
|
36 _LIT(KRegistryDBPanicName, "BT RegistryDB Panic"); |
|
37 User::Panic(KRegistryDBPanicName, aPanic); |
|
38 } |
|
39 // |
|
40 |
|
41 CBTRegistry::CBTRegistry() |
|
42 { |
|
43 LOG_FUNC |
|
44 } |
|
45 |
|
46 CBTRegistry::~CBTRegistry() |
|
47 { |
|
48 LOG_FUNC |
|
49 iDB.Close(); |
|
50 iDBMSServer.Close(); |
|
51 } |
|
52 |
|
53 CBTRegistry* CBTRegistry::NewL() |
|
54 { |
|
55 LOG_STATIC_FUNC |
|
56 CBTRegistry* self = new (ELeave) CBTRegistry; |
|
57 CleanupStack::PushL(self); |
|
58 self->ConstructL(); |
|
59 #ifdef _DEBUG |
|
60 CleanupStack::Check(self); |
|
61 #endif |
|
62 CleanupStack::Pop(); |
|
63 return self; |
|
64 } |
|
65 |
|
66 void CBTRegistry::ConstructL() |
|
67 { |
|
68 LOG_FUNC |
|
69 // we use a DBMS Server session as multiple clients may |
|
70 // be updating their views concurrently. Without this |
|
71 // DBMS would (rightly) panic a rowset already in update |
|
72 User::LeaveIfError(iDBMSServer.Connect()); |
|
73 OpenRegistryL(); |
|
74 } |
|
75 |
|
76 void CBTRegistry::OpenRegistryL() |
|
77 /** |
|
78 Open the Registry DB. |
|
79 If it doesn't exist, attempt to create the necessary path,file and DB |
|
80 **/ |
|
81 { |
|
82 LOG_FUNC |
|
83 const static TInt KMaxTries=4; |
|
84 TInt err; |
|
85 TInt loopCount=0; |
|
86 |
|
87 |
|
88 // In secure EKA2 DBMS land, registry DB is created in DBMS data cage |
|
89 do |
|
90 { |
|
91 err=iDB.Open(iDBMSServer, TBTRegistryDatabaseSecure()(), KBTRegistryDatabaseSecurePolicy()); |
|
92 |
|
93 if(err == KErrNotFound) |
|
94 { |
|
95 CreateRegistryL(); |
|
96 } |
|
97 else if (err != KErrNone) |
|
98 { |
|
99 // If we get here the BT registry file must be corrupt. |
|
100 // Delete the file and go round the while loop once more. |
|
101 DeleteCorruptRegistryL(); |
|
102 } |
|
103 else |
|
104 { |
|
105 TRAP(err,ValidateMetaTableL()); // make sure it's ok version etc. |
|
106 if(err==KErrNone) |
|
107 { |
|
108 TRAP(err,ValidatePersistTableL()); // make sure it's been properly written to |
|
109 } |
|
110 if (err!=KErrNone) |
|
111 { |
|
112 // Either the Meta Table validate failed or the Persist Table validate failed. |
|
113 // Delete the file and go round the while loop once more. |
|
114 DeleteCorruptRegistryL(); |
|
115 } |
|
116 } |
|
117 loopCount++; |
|
118 } while (err!=KErrNone && loopCount<KMaxTries); |
|
119 |
|
120 if(err != KErrNone) |
|
121 { |
|
122 User::Leave(KErrAbort); // give up gracefully |
|
123 } |
|
124 |
|
125 // Purge any SSP debug link keys left over from a previous SSP debug session |
|
126 PurgeDebugLinkKeysL(); |
|
127 |
|
128 (void)iDB.Compact(); // compact now |
|
129 // ready! |
|
130 } |
|
131 |
|
132 |
|
133 |
|
134 RDbTable* CBTRegistry::OpenTableL(const TDesC& aTable) |
|
135 /** |
|
136 Find tables of a given name |
|
137 @param aTable Name of table to open |
|
138 @return table and ownership |
|
139 **/ |
|
140 { |
|
141 LOG_FUNC |
|
142 RDbTable* table = new (ELeave) RDbTable; |
|
143 CleanupCloseDeletePushL(table); |
|
144 |
|
145 TInt err; |
|
146 |
|
147 err = table->Open(iDB, aTable); |
|
148 User::LeaveIfError(err); |
|
149 |
|
150 CleanupStack::Pop(); // table |
|
151 |
|
152 return table; |
|
153 } |
|
154 |
|
155 RDbTable* CBTRegistry::OpenPersistTableL() |
|
156 /** |
|
157 Find the persist table (local device settings) |
|
158 and return it and ownership |
|
159 |
|
160 @return ownership of table |
|
161 **/ |
|
162 { |
|
163 LOG_FUNC |
|
164 return OpenTableL(KPersistTable); |
|
165 } |
|
166 |
|
167 RDbTable* CBTRegistry::OpenDeviceTableL() |
|
168 /** |
|
169 Find the remote device table |
|
170 @return table and ownership |
|
171 **/ |
|
172 { |
|
173 LOG_FUNC |
|
174 return OpenTableL(KDeviceTable); |
|
175 } |
|
176 |
|
177 RDbTable* CBTRegistry::OpenCSYTableL() |
|
178 /** |
|
179 Find the CSY table |
|
180 @return table and ownership |
|
181 **/ |
|
182 { |
|
183 LOG_FUNC |
|
184 return OpenTableL(KCSYTable); |
|
185 } |
|
186 |
|
187 void CBTRegistry::ValidateMetaTableL() |
|
188 /** |
|
189 Go to Meta table and check version numbers etc |
|
190 **/ |
|
191 { |
|
192 LOG_FUNC |
|
193 RDbTable* table = OpenTableL(KMetaTable); |
|
194 CleanupCloseDeletePushL(table); |
|
195 |
|
196 // get the processSID |
|
197 TBool success = table->FirstL(); |
|
198 if (!success) |
|
199 { |
|
200 LOG(_L("BT Registry DB Meta Table CORRUPT!")); |
|
201 User::Leave(KErrEof); |
|
202 } |
|
203 |
|
204 table->GetL(); |
|
205 |
|
206 |
|
207 //put version checking in when we think about backup server |
|
208 TUint major = table->ColUint32(ColumnNoL(KMetaColName_VersionMajor, *table)); |
|
209 TUint minor = table->ColUint32(ColumnNoL(KMetaColName_VersionMinor, *table)); |
|
210 LOG(_L("CBTRegistry opened registry DB Meta Table")); |
|
211 LOG1(_L("\tMajorVersion: %d"), major); |
|
212 LOG1(_L("\tMinorVersion: %d"), minor); |
|
213 |
|
214 if(KRegistryDBVersionMajor != major || |
|
215 KRegistryDBVersionMinor != minor) |
|
216 { |
|
217 User::Leave(KErrCorrupt); |
|
218 } |
|
219 |
|
220 CleanupStack::PopAndDestroy(table); |
|
221 } |
|
222 |
|
223 void CBTRegistry::ValidatePersistTableL() |
|
224 /** |
|
225 Go to Persist table and check local device values |
|
226 **/ |
|
227 { |
|
228 LOG_FUNC |
|
229 RDbTable* table = OpenTableL(KPersistTable); |
|
230 CleanupCloseDeletePushL(table); |
|
231 |
|
232 // get the processSID |
|
233 TBool success = table->FirstL(); |
|
234 if (!success) |
|
235 { |
|
236 LOG(_L("BT Registry DB Local Device Table (Persist Table) CORRUPT!")); |
|
237 User::Leave(KErrEof); |
|
238 } |
|
239 |
|
240 table->GetL(); |
|
241 |
|
242 #ifdef _DEBUG |
|
243 // check the Local device configuration (aka Stack Persistance data) |
|
244 TPtrC8 addrBuf(table->ColDes8(ColumnNoL(KColName_DeviceAddress, *table))); |
|
245 TUint32 CoD = table->ColUint32(ColumnNoL(KPersistColName_CoD, *table)); |
|
246 TUint8 scanEnable = table->ColUint8(ColumnNoL(KPersistColName_ScanEnable, *table)); |
|
247 TPtrC8 name = table->ColDes8(ColumnNoL(KPersistColName_LocalName, *table)); |
|
248 TUint8 powerSettings = table->ColUint8(ColumnNoL(KPersistColName_PowerSettings, *table)); |
|
249 TUint8 limDisc = table->ColUint8(ColumnNoL(KPersistColName_LimitedDiscoverable, *table)); |
|
250 TBool afhChannelAssessmentMode = table->ColUint8(ColumnNoL(KPersistColName_AFHChannelAssessmentMode, *table)); |
|
251 TBool acceptPairedOnlyMode = table->ColUint8(ColumnNoL(KPersistColName_AcceptPairedOnlyMode, *table)); |
|
252 LOG(_L("CBTRegistry opened registry DB Persist Table")); |
|
253 LOG6(_L("\tDevice Address (zero is acceptable): %02x%02x %02x%02x%02x%02x"), |
|
254 addrBuf[0], |
|
255 addrBuf[1], |
|
256 addrBuf[2], |
|
257 addrBuf[3], |
|
258 addrBuf[4], |
|
259 addrBuf[5] |
|
260 ); |
|
261 LOG1(_L("\tCoD: 0x%02x"),CoD); |
|
262 LOG1(_L("\tScan Enable: 0x%02x"),scanEnable); |
|
263 LOG1(_L8("\tLocal Name: \"%S\""),&name); //name is an 8 bit string |
|
264 LOG1(_L("\tPower Settings: 0x%02x"),powerSettings); |
|
265 LOG1(_L("\tLimited Discoverable: 0x%02x"),limDisc); |
|
266 LOG1(_L("\tAFHChannelAssessmentMode: %d"),afhChannelAssessmentMode); |
|
267 LOG1(_L("\tAcceptPairedOnlyMode: %d"),acceptPairedOnlyMode); |
|
268 #endif |
|
269 |
|
270 CleanupStack::PopAndDestroy(table); |
|
271 } |
|
272 |
|
273 void CBTRegistry::CreateRegistryL() |
|
274 /** |
|
275 Creates the Database and Tables we need |
|
276 **/ |
|
277 { |
|
278 LOG_FUNC |
|
279 // In secure DBMS land, the BT Manager DB is created in DBMS's data cage. |
|
280 TInt err = iDB.Create(iDBMSServer, TBTRegistryDatabaseSecure()(), KBTRegistryDatabaseSecurePolicy()); // This leaves iDB in an open state. |
|
281 |
|
282 |
|
283 User::LeaveIfError(err); |
|
284 |
|
285 SetupDefaultRegistryL(); |
|
286 |
|
287 // close the database |
|
288 iDB.Close(); |
|
289 LOG(_L("BT Registry DB Created successfully")); |
|
290 } |
|
291 |
|
292 void CBTRegistry::PurgeDebugLinkKeysL() |
|
293 /** |
|
294 Remove (if present) any SSP debug link keys that may have been created by a previous SSP debug session. |
|
295 **/ |
|
296 { |
|
297 LOG_FUNC |
|
298 RBTDbQuery query; |
|
299 CleanupClosePushL(query); |
|
300 query.MatchLinkKeyTypeL(ELinkKeyDebug); |
|
301 |
|
302 //We dont use the bookmark here, so employ a dummy bookmark. |
|
303 TDbBookmark dummy; |
|
304 RDbView* view = OpenViewL(query, dummy); |
|
305 CleanupCloseDeletePushL(view); |
|
306 |
|
307 if (!view->IsEmptyL()) |
|
308 { |
|
309 // Debug link keys found in registry, unpair these. |
|
310 UnpairViewL(*view); |
|
311 } |
|
312 |
|
313 CleanupStack::PopAndDestroy(2, &query); // view and query |
|
314 } |
|
315 |
|
316 |
|
317 void CBTRegistry::CreatePersistTableL() |
|
318 /** |
|
319 Create the table with all that is necessary for storing local device details |
|
320 **/ |
|
321 { |
|
322 LOG_FUNC |
|
323 CDbColSet* theColumns = CDbColSet::NewLC(); |
|
324 |
|
325 // add in the columns for the Local device configuration (aka Stack Persistance data) |
|
326 theColumns->AddL(TDbCol(KColName_DeviceAddress, EDbColText8)); // Binary not allowed in SQL |
|
327 theColumns->AddL(TDbCol(KPersistColName_CoD, EDbColUint32)); |
|
328 theColumns->AddL(TDbCol(KPersistColName_ScanEnable, EDbColUint8)); |
|
329 // specify the maximum local name length to be KMaxBluetoothNameLen |
|
330 theColumns->AddL(TDbCol(KPersistColName_LocalName, EDbColText8, KMaxBluetoothNameLen)); |
|
331 theColumns->AddL(TDbCol(KPersistColName_PowerSettings, EDbColUint8)); |
|
332 theColumns->AddL(TDbCol(KPersistColName_LimitedDiscoverable, EDbColBit)); |
|
333 theColumns->AddL(TDbCol(KPersistColName_AFHChannelAssessmentMode, EDbColBit)); |
|
334 theColumns->AddL(TDbCol(KPersistColName_AcceptPairedOnlyMode, EDbColBit)); |
|
335 User::LeaveIfError(iDB.CreateTable(KPersistTable, *theColumns)); |
|
336 |
|
337 CleanupStack::PopAndDestroy(theColumns); |
|
338 } |
|
339 |
|
340 void CBTRegistry::CreateDeviceTableL() |
|
341 /** |
|
342 Create the table with all that is necessary to store details about remote devices |
|
343 |
|
344 To provide better CoD searching than the underlying SQL supports |
|
345 this table uses >1 column for device class of remote device |
|
346 |
|
347 This also allows for future versions of the CoD field in the BT Spec |
|
348 **/ |
|
349 { |
|
350 LOG_FUNC |
|
351 CDbColSet* theColumns = CDbColSet::NewLC(); |
|
352 |
|
353 theColumns->AddL(TDbCol(KColName_ProcessSID, EDbColUint32)); //SID of process adding record |
|
354 theColumns->AddL(TDbCol(KColName_DeviceAddress, EDbColText8)); // Binary not allowed in SQL |
|
355 theColumns->AddL(TDbCol(KDeviceColName_CoD_MajorDev, EDbColUint32)); |
|
356 theColumns->AddL(TDbCol(KDeviceColName_CoD_MinorDev, EDbColUint32)); |
|
357 theColumns->AddL(TDbCol(KDeviceColName_CoD_Service, EDbColUint32)); |
|
358 theColumns->AddL(TDbCol(KDeviceColName_BluetoothName, EDbColText8, KMaxBluetoothNameLen)); // keep UTF8 |
|
359 theColumns->AddL(TDbCol(KDeviceColName_FriendlyName, EDbColText16, KMaxBluetoothNameLen)); // possible UNICODE? |
|
360 theColumns->AddL(TDbCol(KDeviceColName_LinkKey, EDbColText8)); // Binary not allowed in SQL |
|
361 theColumns->AddL(TDbCol(KDeviceColName_PassKey, EDbColText8)); // Binary not allowed in SQL |
|
362 theColumns->AddL(TDbCol(KDeviceColName_PageScanMode, EDbColUint8)); |
|
363 theColumns->AddL(TDbCol(KDeviceColName_PageScanRepMode, EDbColUint8)); |
|
364 theColumns->AddL(TDbCol(KDeviceColName_PageScanPeriodMode, EDbColUint8)); |
|
365 theColumns->AddL(TDbCol(KDeviceColName_LastSeen, EDbColInt64)); |
|
366 theColumns->AddL(TDbCol(KDeviceColName_LastUsed, EDbColInt64)); |
|
367 theColumns->AddL(TDbCol(KDeviceColName_GlobalSecSecurity, EDbColUint8)); |
|
368 theColumns->AddL(TDbCol(KDeviceColName_GlobalSecPasskeyLen, EDbColUint32)); |
|
369 theColumns->AddL(TDbCol(KDeviceColName_LinkKeyType, EDbColUint8)); |
|
370 theColumns->AddL(TDbCol(KDeviceColName_UiCookie, EDbColText8)); // Can only simulate "bit-masked" searching in SQL if stored as text |
|
371 |
|
372 User::LeaveIfError(iDB.CreateTable(KDeviceTable, *theColumns)); |
|
373 |
|
374 CleanupStack::PopAndDestroy(theColumns); |
|
375 } |
|
376 |
|
377 void CBTRegistry::CreateMetaTableL() |
|
378 /** |
|
379 Stores useful information about the database |
|
380 Version - useful for attempting to see if we can restore an old db |
|
381 Originating process |
|
382 **/ |
|
383 { |
|
384 LOG_FUNC |
|
385 CDbColSet* theColumns = CDbColSet::NewLC(); |
|
386 |
|
387 theColumns->AddL(TDbCol(KMetaColName_VersionMajor, EDbColUint32)); |
|
388 theColumns->AddL(TDbCol(KMetaColName_VersionMinor, EDbColUint32)); |
|
389 theColumns->AddL(TDbCol(KColName_ProcessSID, EDbColUint32)); //SID of process adding record |
|
390 |
|
391 User::LeaveIfError(iDB.CreateTable(KMetaTable, *theColumns)); |
|
392 |
|
393 CleanupStack::PopAndDestroy(theColumns); |
|
394 |
|
395 SetMetaDataL(); |
|
396 } |
|
397 |
|
398 void CBTRegistry::CreateCSYTableL() |
|
399 /** |
|
400 Create the table with all that is necessary to store details about virtual serial ports |
|
401 **/ |
|
402 { |
|
403 LOG_FUNC |
|
404 CDbColSet* theColumns = CDbColSet::NewLC(); |
|
405 |
|
406 theColumns->AddL(TDbCol(KColName_ProcessSID, EDbColUint32)); //SID of process adding record |
|
407 theColumns->AddL(TDbCol(KBTCOMMColName_Port, EDbColUint32)); |
|
408 theColumns->AddL(TDbCol(KColName_DeviceAddress, EDbColText8)); //Device address |
|
409 theColumns->AddL(TDbCol(KBTCOMMColName_ServiceUUID, EDbColText8)); //SDP UUID - 16bytes |
|
410 theColumns->AddL(TDbCol(KBTCOMMColName_Security, EDbColUint8)); //Security |
|
411 theColumns->AddL(TDbCol(KBTCOMMColName_ServiceName, EDbColText)); //ServiceName |
|
412 |
|
413 User::LeaveIfError(iDB.CreateTable(KCSYTable, *theColumns)); |
|
414 |
|
415 CleanupStack::PopAndDestroy(theColumns); |
|
416 } |
|
417 |
|
418 |
|
419 TDbColNo CBTRegistry::ColumnNoL(const TDesC& aColName, const RDbRowSet& aRowSet) |
|
420 /** |
|
421 Looks up column names and returns the column number |
|
422 |
|
423 @param aColName the name of the column |
|
424 @param aRowSet the rowset in which to find the column |
|
425 @return the column number with aColName |
|
426 **/ |
|
427 { |
|
428 LOG_FUNC |
|
429 // get the schema from the table - we own this |
|
430 #ifdef _DEBUG |
|
431 CDbColSet* schema = NULL; |
|
432 TRAPD(err, schema = aRowSet.ColSetL()); |
|
433 if(err == KErrNoMemory) |
|
434 { |
|
435 User::Leave(err); |
|
436 } |
|
437 //This __ASSERT_DEBUG is here to catch any 'Leaves' |
|
438 //in RDbRowSet::ColSetL other than that\those using |
|
439 //KErrNoMemory. |
|
440 __ASSERT_DEBUG(err == KErrNone, Panic(EBTManColSetError)); |
|
441 #else |
|
442 CDbColSet* schema = aRowSet.ColSetL(); // no need to push onto cleanup |
|
443 #endif |
|
444 // get the column number, based on name |
|
445 TDbColNo column = schema->ColNo(aColName); |
|
446 delete schema; |
|
447 return column; |
|
448 } |
|
449 |
|
450 |
|
451 |
|
452 TBool CBTRegistry::DevicePresentL(const TBTDevAddr& aAddress) |
|
453 /** |
|
454 Checks to see if a device is present in the Registry |
|
455 @param aAddress The key to finding a device |
|
456 @return True if Device is present, false if not |
|
457 **/ |
|
458 { |
|
459 LOG_FUNC |
|
460 // form an SQL query for the device with address aAddress |
|
461 RBTDbQuery query; |
|
462 CleanupClosePushL(query); |
|
463 query.FindDeviceL(aAddress); |
|
464 |
|
465 TDbBookmark dummy; |
|
466 RDbView* view = NULL; |
|
467 |
|
468 // open the view with that SQL query |
|
469 view = OpenViewL(query, dummy); // uses a private view... |
|
470 CleanupCloseDeletePushL(view); |
|
471 |
|
472 TInt count = view->CountL(); |
|
473 |
|
474 __ASSERT_ALWAYS(count <= 1, Panic(ETooManyRemoteDeviceEntries)); |
|
475 |
|
476 CleanupStack::PopAndDestroy(2, &query); // view and query |
|
477 return (count!=0); |
|
478 } |
|
479 |
|
480 void CBTRegistry::CreateDeviceL(const CBTDevice& aDetails, TBool aStoreUiCookie, const TSecureId& aClientSID) |
|
481 /** |
|
482 Add a new record into the DB |
|
483 |
|
484 @param aDetails The new device details to add |
|
485 @param aClientUid The ID of the process adding the new record |
|
486 @leave KErrCorrupt if device to add is not valid |
|
487 @leave KErrAlreadyExists if device to add is already present |
|
488 **/ |
|
489 { |
|
490 LOG_FUNC |
|
491 if (!aDetails.IsValidBDAddr()) |
|
492 { |
|
493 User::Leave(KErrCorrupt); |
|
494 } |
|
495 |
|
496 if (DevicePresentL(aDetails.BDAddr())) |
|
497 { |
|
498 User::Leave(KErrAlreadyExists); |
|
499 } |
|
500 |
|
501 RDbTable* table = OpenDeviceTableL(); |
|
502 CleanupCloseDeletePushL(table); |
|
503 |
|
504 table->InsertL(); |
|
505 table->SetColL(ColumnNoL(KColName_DeviceAddress, *table), aDetails.BDAddr().Des()); |
|
506 |
|
507 table->SetColL(ColumnNoL(KColName_ProcessSID, *table), aClientSID); |
|
508 |
|
509 // got some initial details; stick them in now... |
|
510 SetDeviceL(*table, aDetails, !aStoreUiCookie); // does the remaining columns |
|
511 CleanupStack::PopAndDestroy(table); |
|
512 } |
|
513 |
|
514 void CBTRegistry::UnpairL(RDbRowSet& aRowSet) |
|
515 /** |
|
516 Unpairs a set of devices |
|
517 |
|
518 @pre A rowset constraining the view to a single device |
|
519 @param aRowSet The set of records to unpair |
|
520 @see DBMS for leave codes |
|
521 **/ |
|
522 { |
|
523 LOG_FUNC |
|
524 aRowSet.UpdateL(); |
|
525 aRowSet.SetColNullL(ColumnNoL(KDeviceColName_LinkKey, aRowSet)); |
|
526 aRowSet.SetColNullL(ColumnNoL(KDeviceColName_PassKey, aRowSet)); |
|
527 aRowSet.SetColNullL(ColumnNoL(KDeviceColName_LinkKeyType, aRowSet)); |
|
528 |
|
529 CleanPutL(aRowSet); |
|
530 } |
|
531 |
|
532 void CBTRegistry::UnpairViewL(RDbRowSet& aRowSet) |
|
533 /** |
|
534 Unpairs all sets of devices in the supplied rowset |
|
535 |
|
536 @pre A rowset constraining the view |
|
537 @param aRowSet The set of records to unpair |
|
538 @see DBMS for leave codes |
|
539 **/ |
|
540 { |
|
541 LOG_FUNC |
|
542 aRowSet.FirstL(); |
|
543 TInt c = aRowSet.CountL(); |
|
544 for (TInt i=0; i<c; i++) |
|
545 { |
|
546 UnpairL(aRowSet); |
|
547 aRowSet.NextL(); |
|
548 } |
|
549 } |
|
550 |
|
551 void CBTRegistry::UpdateDeviceL(RDbRowSet& aRowSet, const CBTDevice& aDetails) |
|
552 /** |
|
553 Given a rowset (from a previous find) and |
|
554 mark the rowset for update, and make the changes |
|
555 |
|
556 @param aRowSet The set of rows to update - typically one row... |
|
557 **/ |
|
558 { |
|
559 LOG_FUNC |
|
560 aRowSet.UpdateL(); |
|
561 SetDeviceL(aRowSet, aDetails); |
|
562 } |
|
563 |
|
564 void CBTRegistry::UpdateNameL(const TBTDevAddr& aAddress, |
|
565 const TDesC8& aName, |
|
566 TBTManServerRequest aRequest) |
|
567 /** |
|
568 Update the name of a device - either friendly or Bluetooth name |
|
569 |
|
570 @param aAddress The device to update |
|
571 @param aName The new name |
|
572 @param aRequest Determines the type of name to change |
|
573 |
|
574 Could change this so subsession opens the rowset and just gives that to this |
|
575 **/ |
|
576 { |
|
577 LOG_FUNC |
|
578 // Find the row |
|
579 RBTDbQuery deviceQuery; |
|
580 CleanupClosePushL(deviceQuery); |
|
581 deviceQuery.FindDeviceL(aAddress); |
|
582 |
|
583 TDbBookmark dummy; |
|
584 |
|
585 RDbView* view = OpenViewL(deviceQuery, dummy); |
|
586 CleanupCloseDeletePushL(view); |
|
587 |
|
588 view->UpdateL(); |
|
589 |
|
590 switch (aRequest) |
|
591 { |
|
592 case EBTRegistryModifyFriendlyName: |
|
593 { |
|
594 TBuf<KMaxFriendlyNameLen> temp; |
|
595 User::LeaveIfError(CnvUtfConverter::ConvertToUnicodeFromUtf8(temp,aName)); |
|
596 view->SetColL(ColumnNoL(KDeviceColName_FriendlyName, *view), temp); |
|
597 break; |
|
598 } |
|
599 |
|
600 case EBTRegistryModifyBluetoothName: |
|
601 { |
|
602 view->SetColL(ColumnNoL(KDeviceColName_BluetoothName, *view), aName); |
|
603 break; |
|
604 } |
|
605 default: |
|
606 Panic(EBadNameToUpdate); |
|
607 } |
|
608 CleanPutL(*view); |
|
609 CleanupStack::PopAndDestroy(2, &deviceQuery); // view and deviceQuery |
|
610 } |
|
611 |
|
612 void CBTRegistry::UpdateLocalDeviceL(const TBTLocalDevice& aLocalDevice) |
|
613 /** |
|
614 @param aLocalDevice The new settings |
|
615 **/ |
|
616 { |
|
617 LOG_FUNC |
|
618 // obliterate what's there |
|
619 RDbTable* table = OpenPersistTableL(); |
|
620 CleanupCloseDeletePushL(table); |
|
621 |
|
622 TInt count = table->CountL(); |
|
623 __ASSERT_DEBUG(count <=1, Panic(ETooManyLocalDeviceEntries)); |
|
624 if (!count) |
|
625 { |
|
626 // we need to insert the one and only row as this is a fresh table |
|
627 table->InsertL(); |
|
628 } |
|
629 else |
|
630 { |
|
631 // go to the only row |
|
632 TBool success = table->FirstL(); |
|
633 if (!success) |
|
634 { |
|
635 LOG(_L("BT Registry DB Local Device Table (Persist Table) CORRUPT!")); |
|
636 User::Leave(KErrEof); |
|
637 } |
|
638 |
|
639 table->UpdateL(); |
|
640 } |
|
641 |
|
642 if (aLocalDevice.IsValidAddress()) |
|
643 table->SetColL(ColumnNoL(KColName_DeviceAddress, *table), |
|
644 aLocalDevice.Address().Des()); |
|
645 |
|
646 if (aLocalDevice.IsValidDeviceClass()) |
|
647 table->SetColL(ColumnNoL(KPersistColName_CoD, *table), |
|
648 static_cast<TUint>(aLocalDevice.DeviceClass())); |
|
649 |
|
650 if (aLocalDevice.IsValidDeviceName()) |
|
651 table->SetColL(ColumnNoL(KPersistColName_LocalName, *table), |
|
652 aLocalDevice.DeviceName()); |
|
653 |
|
654 if (aLocalDevice.IsValidScanEnable()) |
|
655 table->SetColL(ColumnNoL(KPersistColName_ScanEnable, *table), |
|
656 static_cast<TUint>(aLocalDevice.ScanEnable())); |
|
657 |
|
658 if (aLocalDevice.IsValidPowerSetting()) |
|
659 table->SetColL(ColumnNoL(KPersistColName_PowerSettings, *table), |
|
660 static_cast<TUint>(aLocalDevice.PowerSetting())); |
|
661 |
|
662 if (aLocalDevice.IsValidAFHChannelAssessmentMode()) |
|
663 table->SetColL(ColumnNoL(KPersistColName_AFHChannelAssessmentMode, *table), |
|
664 static_cast<TBool>(aLocalDevice.AFHChannelAssessmentMode())); |
|
665 |
|
666 if (aLocalDevice.IsValidLimitedDiscoverable()) |
|
667 table->SetColL(ColumnNoL(KPersistColName_LimitedDiscoverable, *table), |
|
668 static_cast<TBool>(aLocalDevice.LimitedDiscoverable())); |
|
669 |
|
670 if (aLocalDevice.IsValidAcceptPairedOnlyMode()) |
|
671 table->SetColL(ColumnNoL(KPersistColName_AcceptPairedOnlyMode, *table), |
|
672 static_cast<TBool>(aLocalDevice.AcceptPairedOnlyMode())); |
|
673 |
|
674 CleanPutL(*table); |
|
675 CleanupStack::PopAndDestroy(table); |
|
676 } |
|
677 |
|
678 void CBTRegistry::SetMetaDataL() |
|
679 /** |
|
680 Set the values for the MetaData Table |
|
681 **/ |
|
682 { |
|
683 LOG_FUNC |
|
684 // put defaults in |
|
685 RDbTable* table = OpenTableL(KMetaTable); |
|
686 CleanupCloseDeletePushL(table); |
|
687 |
|
688 #ifdef _DEBUG |
|
689 TInt c=0; |
|
690 TRAP_IGNORE(c=table->CountL()); |
|
691 __ASSERT_DEBUG(c==0, Panic(EMetaTableBroken)); |
|
692 #endif |
|
693 |
|
694 table->InsertL(); |
|
695 |
|
696 table->SetColL(ColumnNoL(KColName_ProcessSID, *table), RProcess().SecureId()); |
|
697 |
|
698 table->SetColL(ColumnNoL(KMetaColName_VersionMajor, *table), KRegistryDBVersionMajor); |
|
699 table->SetColL(ColumnNoL(KMetaColName_VersionMinor, *table), KRegistryDBVersionMinor); |
|
700 |
|
701 CleanPutL(*table); |
|
702 CleanupStack::PopAndDestroy(table); |
|
703 } |
|
704 |
|
705 void CBTRegistry::SetDeviceL(RDbRowSet& aRowSet, const CBTDevice& aDetails, TBool aIgnoreUiCookie) |
|
706 /** |
|
707 Set the values for the device record if the Details are valid |
|
708 |
|
709 @param aRowSet The rowset to adjust...typically one row |
|
710 @param aDetails The new details |
|
711 **/ |
|
712 { |
|
713 LOG_FUNC |
|
714 if (aDetails.AsNamelessDevice().IsValidPageScanMode()) |
|
715 { |
|
716 aRowSet.SetColL(ColumnNoL(KDeviceColName_PageScanMode, aRowSet), static_cast<TUint>(aDetails.AsNamelessDevice().PageScanMode())); |
|
717 } |
|
718 if (aDetails.AsNamelessDevice().IsValidPageScanRepMode()) |
|
719 { |
|
720 aRowSet.SetColL(ColumnNoL(KDeviceColName_PageScanRepMode, aRowSet), static_cast<TUint>(aDetails.AsNamelessDevice().PageScanRepMode())); |
|
721 } |
|
722 if (aDetails.AsNamelessDevice().IsValidPageScanPeriodMode()) |
|
723 { |
|
724 aRowSet.SetColL(ColumnNoL(KDeviceColName_PageScanPeriodMode, aRowSet), static_cast<TUint>(aDetails.AsNamelessDevice().PageScanPeriodMode())); |
|
725 } |
|
726 if (aDetails.IsValidDeviceClass()) |
|
727 { |
|
728 const TBTDeviceClass& cod = aDetails.DeviceClass(); |
|
729 |
|
730 aRowSet.SetColL(ColumnNoL(KDeviceColName_CoD_MajorDev, aRowSet), static_cast<TUint>(cod.MajorDeviceClass())); |
|
731 aRowSet.SetColL(ColumnNoL(KDeviceColName_CoD_MinorDev, aRowSet), static_cast<TUint>(cod.MinorDeviceClass())); |
|
732 aRowSet.SetColL(ColumnNoL(KDeviceColName_CoD_Service, aRowSet), static_cast<TUint>(cod.MajorServiceClass())); |
|
733 } |
|
734 if (aDetails.IsValidDeviceName()) |
|
735 { |
|
736 aRowSet.SetColL(ColumnNoL(KDeviceColName_BluetoothName, aRowSet), aDetails.DeviceName()); |
|
737 } |
|
738 if (aDetails.IsValidFriendlyName()) |
|
739 { |
|
740 aRowSet.SetColL(ColumnNoL(KDeviceColName_FriendlyName, aRowSet), aDetails.FriendlyName()); |
|
741 } |
|
742 if (aDetails.IsValidUsed()) |
|
743 { |
|
744 aRowSet.SetColL(ColumnNoL(KDeviceColName_LastUsed, aRowSet), aDetails.Used().Int64()); |
|
745 } |
|
746 if (aDetails.IsValidSeen()) |
|
747 { |
|
748 aRowSet.SetColL(ColumnNoL(KDeviceColName_LastSeen, aRowSet), aDetails.Seen().Int64()); |
|
749 } |
|
750 if (aDetails.IsValidGlobalSecurity()) |
|
751 { |
|
752 aRowSet.SetColL(ColumnNoL(KDeviceColName_GlobalSecSecurity, aRowSet), static_cast<TUint>(aDetails.GlobalSecurity().SecurityValue())); |
|
753 aRowSet.SetColL(ColumnNoL(KDeviceColName_GlobalSecPasskeyLen, aRowSet), static_cast<TUint>(aDetails.GlobalSecurity().PasskeyMinLength())); |
|
754 } |
|
755 if (aDetails.IsValidLinkKey()) |
|
756 { |
|
757 aRowSet.SetColL(ColumnNoL(KDeviceColName_LinkKey, aRowSet), aDetails.LinkKey()); |
|
758 aRowSet.SetColL(ColumnNoL(KDeviceColName_LinkKeyType, aRowSet), aDetails.LinkKeyType()); |
|
759 } |
|
760 else |
|
761 { |
|
762 LOG(_L("Sec\tNot setting link key")) |
|
763 } |
|
764 if (aDetails.IsValidPassKey()) |
|
765 { |
|
766 aRowSet.SetColL(ColumnNoL(KDeviceColName_PassKey, aRowSet), aDetails.PassKey()); |
|
767 } |
|
768 if (aDetails.IsValidUiCookie() && !aIgnoreUiCookie) |
|
769 { |
|
770 static const TUint8 KCookieBinaryRepresentationWidth = 32; // 32bits encoded as binary string. |
|
771 TBuf8<KCookieBinaryRepresentationWidth> textCookieValue; |
|
772 textCookieValue.NumFixedWidth(aDetails.UiCookie(), EBinary, KCookieBinaryRepresentationWidth); |
|
773 aRowSet.SetColL(ColumnNoL(KDeviceColName_UiCookie, aRowSet), textCookieValue); |
|
774 } |
|
775 |
|
776 CleanPutL(aRowSet); |
|
777 } |
|
778 |
|
779 void CBTRegistry::CleanPutL(RDbRowSet& aRowSet) |
|
780 /** |
|
781 Try to put the changes into a RowSet |
|
782 If this fails cancel the update and reset |
|
783 Then re-leave |
|
784 **/ |
|
785 { |
|
786 LOG_FUNC |
|
787 TRAPD(dbResult, aRowSet.PutL()); |
|
788 |
|
789 if (dbResult!=KErrNone) |
|
790 { |
|
791 aRowSet.Cancel(); |
|
792 aRowSet.Reset(); |
|
793 User::Leave(KErrCorrupt); // this will complete the client message |
|
794 } |
|
795 } |
|
796 |
|
797 RDbView* CBTRegistry::OpenDeviceL(const TBTDevAddr& aAddr, TDbBookmark& aBookmark) |
|
798 /** |
|
799 Open a view onto a given record in the Registry |
|
800 @return a bookmark to the entry should the caller want it |
|
801 **/ |
|
802 { |
|
803 LOG_FUNC |
|
804 RBTDbQuery query; |
|
805 CleanupClosePushL(query); |
|
806 query.FindDeviceL(aAddr); |
|
807 |
|
808 // open the device |
|
809 RDbView* view = NULL; |
|
810 view = OpenViewL(query, aBookmark); |
|
811 |
|
812 CleanupCloseDeletePushL(view); |
|
813 |
|
814 #ifdef _DEBUG |
|
815 TInt c=0; |
|
816 TRAP_IGNORE(c=view->CountL()); |
|
817 __ASSERT_DEBUG(c<=1, Panic(ETooManyRemoteDeviceEntries)); |
|
818 #endif |
|
819 |
|
820 CleanupStack::Pop(view); // view (pass ownership) |
|
821 CleanupStack::PopAndDestroy(&query); // query |
|
822 return view; |
|
823 } |
|
824 |
|
825 RDbView* CBTRegistry::OpenViewL(const TDesC& aSQLQuery, TDbBookmark& aBookmark) |
|
826 /** |
|
827 Returns a view resulting from the execution of the aSQLQuery |
|
828 Update aBookmark to be the beginning of the view |
|
829 **/ |
|
830 { |
|
831 LOG_FUNC |
|
832 RDbView* view = new (ELeave) RDbView; |
|
833 CleanupCloseDeletePushL(view); |
|
834 |
|
835 // open the view based on the SQL query |
|
836 User::LeaveIfError(view->Prepare(iDB, aSQLQuery)); |
|
837 // could separate this into separate Evaluates, but expected to be smallish DB |
|
838 User::LeaveIfError(view->EvaluateAll()); |
|
839 |
|
840 // move to first row, and bookmark it |
|
841 view->FirstL(); |
|
842 aBookmark = view->Bookmark(); // set bookmark in case user would like it |
|
843 |
|
844 CleanupStack::Pop(view); |
|
845 return view; // returns ownership |
|
846 } |
|
847 |
|
848 RDbView* CBTRegistry::OpenViewL(const RBTDbQuery& aQuery, TDbBookmark& aBookmark) |
|
849 /** |
|
850 Overload allowing just a RBTDbQuery to be executed - hides the SQL query |
|
851 **/ |
|
852 { |
|
853 LOG_FUNC |
|
854 return OpenViewL(aQuery.QueryBuf(), aBookmark); |
|
855 } |
|
856 |
|
857 void CBTRegistry::IncrementRowL(RDbRowSet& aRowSet, TDbBookmark& aBookmark) |
|
858 /** |
|
859 Move to the next row in a RowSet and return a bookmark should the caller be interested |
|
860 **/ |
|
861 { |
|
862 LOG_FUNC |
|
863 aRowSet.NextL(); // move onto next row for next get |
|
864 aBookmark = aRowSet.Bookmark(); |
|
865 } |
|
866 |
|
867 void CBTRegistry::GetRowL(RDbRowSet& aRowSet, const TDbBookmark& aBookmark) |
|
868 /** |
|
869 Mark the rowset for reading |
|
870 **/ |
|
871 { |
|
872 LOG_FUNC |
|
873 if (!aRowSet.AtEnd()) |
|
874 { |
|
875 aRowSet.GotoL(aBookmark); |
|
876 aRowSet.GetL(); // get the row (which is a remote device on this table) |
|
877 } |
|
878 else |
|
879 { |
|
880 User::Leave(KErrEof); |
|
881 } |
|
882 } |
|
883 |
|
884 |
|
885 void CBTRegistry::GetNamelessDetailsL(TBTNamelessDevice& aDevice, |
|
886 RDbRowSet& aRowSet, |
|
887 TBool includeKeys) |
|
888 /** |
|
889 Gets the next device (row) out of a rowset and puts them in a CBTDevice |
|
890 The CBTDevice and its ownership is returned to the caller |
|
891 **/ |
|
892 { |
|
893 LOG_FUNC |
|
894 __ASSERT_DEBUG(!aRowSet.IsColNull(ColumnNoL(KColName_DeviceAddress, aRowSet)), Panic(ECorruptDeviceEntry)); |
|
895 |
|
896 TPtrC8 addrBuf(aRowSet.ColDes8(ColumnNoL(KColName_DeviceAddress, aRowSet))); |
|
897 aDevice.SetAddress(static_cast<TBTDevAddr>(addrBuf)); |
|
898 |
|
899 TDbColNo column; |
|
900 |
|
901 column = ColumnNoL(KDeviceColName_PageScanMode, aRowSet); |
|
902 if (!aRowSet.IsColNull(column)) |
|
903 { |
|
904 aDevice.SetPageScanMode(aRowSet.ColUint8(column)); |
|
905 } |
|
906 |
|
907 column = ColumnNoL(KDeviceColName_PageScanPeriodMode, aRowSet); |
|
908 if (!aRowSet.IsColNull(column)) |
|
909 { |
|
910 aDevice.SetPageScanPeriodMode(aRowSet.ColUint8(column)); |
|
911 } |
|
912 |
|
913 column = ColumnNoL(KDeviceColName_PageScanRepMode, aRowSet); |
|
914 if (!aRowSet.IsColNull(column)) |
|
915 { |
|
916 aDevice.SetPageScanRepMode(aRowSet.ColUint8(column)); |
|
917 } |
|
918 |
|
919 /* column = ColumnNoL(KDeviceColName_CoD, aRowSet); |
|
920 if (!aRowSet.IsColNull(column)) |
|
921 { |
|
922 aDevice.SetDeviceClass(aRowSet.ColUint32(column)); |
|
923 } |
|
924 */ |
|
925 // all CoD columns must be set - just test one |
|
926 column = ColumnNoL(KDeviceColName_CoD_MajorDev, aRowSet); |
|
927 if (!aRowSet.IsColNull(column)) |
|
928 { |
|
929 TUint majorDeviceClass = aRowSet.ColUint(column); |
|
930 |
|
931 column = ColumnNoL(KDeviceColName_CoD_MinorDev, aRowSet); |
|
932 TUint minorDeviceClass = aRowSet.ColUint(column); |
|
933 |
|
934 column = ColumnNoL(KDeviceColName_CoD_Service, aRowSet); |
|
935 TUint serviceClass = aRowSet.ColUint(column); |
|
936 |
|
937 aDevice.SetDeviceClass(TBTDeviceClass(static_cast<TUint16>(serviceClass), |
|
938 static_cast<TUint8>(majorDeviceClass), |
|
939 static_cast<TUint8>(minorDeviceClass))); |
|
940 |
|
941 } |
|
942 |
|
943 column = ColumnNoL(KDeviceColName_GlobalSecSecurity, aRowSet); |
|
944 if (!aRowSet.IsColNull(column)) |
|
945 { |
|
946 TBTDeviceSecurity devSec; |
|
947 devSec.SetSecurityValue(aRowSet.ColUint8(column)); |
|
948 column = ColumnNoL(KDeviceColName_GlobalSecPasskeyLen, aRowSet); |
|
949 devSec.SetPasskeyMinLength(aRowSet.ColUint32(column)); |
|
950 |
|
951 aDevice.SetGlobalSecurity(devSec); |
|
952 } |
|
953 |
|
954 column = ColumnNoL(KDeviceColName_LinkKey, aRowSet); |
|
955 TDbColNo typeColumn = ColumnNoL(KDeviceColName_LinkKeyType, aRowSet); |
|
956 |
|
957 if (!aRowSet.IsColNull(column)) |
|
958 { |
|
959 if(includeKeys) |
|
960 { |
|
961 TBTLinkKey linkKey; |
|
962 linkKey.Copy(aRowSet.ColDes8(column)); |
|
963 aDevice.SetLinkKey(linkKey, static_cast<TBTLinkKeyType>(aRowSet.ColUint8(typeColumn))); |
|
964 } |
|
965 else |
|
966 { |
|
967 LOG(_L("Device paired but lack of capability to retrieve link key")); |
|
968 aDevice.SetPaired(static_cast<TBTLinkKeyType>(aRowSet.ColUint8(typeColumn))); |
|
969 } |
|
970 } |
|
971 else |
|
972 { |
|
973 LOG(_L("Sec\tDevice has NULL LinkKey column => Unpaired")) |
|
974 } |
|
975 |
|
976 column = ColumnNoL(KDeviceColName_PassKey, aRowSet); |
|
977 |
|
978 if (!aRowSet.IsColNull(column)) |
|
979 { |
|
980 if(includeKeys) |
|
981 { |
|
982 TBTPinCode passKey; |
|
983 passKey.Copy(aRowSet.ColDes8(column)); |
|
984 aDevice.SetPassKey(passKey); |
|
985 } |
|
986 else |
|
987 { |
|
988 LOG(_L("Device has PIN code but lack of capability to retrieve PIN code")); |
|
989 } |
|
990 } |
|
991 else |
|
992 { |
|
993 LOG(_L("Sec\tDevice has NULL PinCode column")) |
|
994 } |
|
995 |
|
996 column = ColumnNoL(KDeviceColName_LastSeen, aRowSet); |
|
997 if (!aRowSet.IsColNull(column)) |
|
998 { |
|
999 aDevice.SetSeen(TTime(aRowSet.ColInt64(column))); |
|
1000 } |
|
1001 |
|
1002 column = ColumnNoL(KDeviceColName_LastUsed, aRowSet); |
|
1003 if (!aRowSet.IsColNull(column)) |
|
1004 { |
|
1005 aDevice.SetUsed(TTime(aRowSet.ColInt64(column))); |
|
1006 } |
|
1007 |
|
1008 column = ColumnNoL(KDeviceColName_UiCookie, aRowSet); |
|
1009 if (!aRowSet.IsColNull(column)) |
|
1010 { |
|
1011 TPtrC8 cookieBuf(aRowSet.ColDes8(column)); |
|
1012 TLex8 lexer(cookieBuf); |
|
1013 TUint32 cookieValue = 0; |
|
1014 TInt err = lexer.Val(cookieValue, EBinary); |
|
1015 if(err != KErrNone) |
|
1016 { |
|
1017 // discard the specific lexer errors, the fundemental issue |
|
1018 // is that the device entry is corrupted in someway. |
|
1019 User::Leave(KErrCorrupt); |
|
1020 } |
|
1021 aDevice.SetUiCookie(cookieValue); |
|
1022 } |
|
1023 } |
|
1024 |
|
1025 const TBTNamelessDevice* CBTRegistry::GetNextNamelessDeviceLC(RDbRowSet& aRowSet, |
|
1026 TDbBookmark& aBookmark, |
|
1027 TBool includeKeys) |
|
1028 /** |
|
1029 Get the next row from the rowset; building and return TBTNamelessDevice via heap |
|
1030 **/ |
|
1031 { |
|
1032 LOG_FUNC |
|
1033 GetRowL(aRowSet, aBookmark); |
|
1034 // there is a row to get, instantiate an object to receive details |
|
1035 TBTNamelessDevice* device = new(ELeave) TBTNamelessDevice; // for passing ownership |
|
1036 CleanupStack::PushL(device); |
|
1037 GetNamelessDetailsL(*device, aRowSet, includeKeys); |
|
1038 IncrementRowL(aRowSet, aBookmark); |
|
1039 return device; |
|
1040 } |
|
1041 |
|
1042 CBTDevice* CBTRegistry::GetNextDeviceL(RDbRowSet& aRowSet, |
|
1043 TDbBookmark& aBookmark, |
|
1044 TBool includeLinkKey) |
|
1045 /** |
|
1046 Get the next row from the rowset; building and return CBTDevice via heap |
|
1047 **/ |
|
1048 { |
|
1049 LOG_FUNC |
|
1050 GetRowL(aRowSet, aBookmark); |
|
1051 // there is a row to get, so instantiate an object to receive details |
|
1052 CBTDevice* device = CBTDevice::NewLC(); |
|
1053 GetNamelessDetailsL(device->AsNamelessDevice(), aRowSet, includeLinkKey); |
|
1054 |
|
1055 TDbColNo column = ColumnNoL(KDeviceColName_BluetoothName, aRowSet); |
|
1056 if (!aRowSet.IsColNull(column)) |
|
1057 { |
|
1058 device->SetDeviceNameL(aRowSet.ColDes8(column)); |
|
1059 } |
|
1060 |
|
1061 column = ColumnNoL(KDeviceColName_FriendlyName, aRowSet); |
|
1062 if (!aRowSet.IsColNull(column)) |
|
1063 { |
|
1064 TBuf<KMaxFriendlyNameLen> unicodeBuf; |
|
1065 unicodeBuf.Copy(aRowSet.ColDes(column)); |
|
1066 device->SetFriendlyNameL(unicodeBuf); |
|
1067 } |
|
1068 IncrementRowL(aRowSet, aBookmark); |
|
1069 CleanupStack::Pop(device); |
|
1070 return device; |
|
1071 } |
|
1072 |
|
1073 const TUid CBTRegistry::CreatingProcessUidL(RDbRowSet& aRowSet) |
|
1074 /** |
|
1075 @return Value read from DB of the process that created a rowset |
|
1076 **/ |
|
1077 { |
|
1078 LOG_FUNC |
|
1079 #ifdef _DEBUG |
|
1080 TInt c=0; |
|
1081 TRAP_IGNORE(c=aRowSet.CountL()); |
|
1082 __ASSERT_DEBUG(c==1, Panic(ETooManyRemoteDeviceEntries)); |
|
1083 #endif |
|
1084 |
|
1085 aRowSet.GetL(); // this makes the semantics of this function a bit odd...it leaves the rowset open for read |
|
1086 TInt val = aRowSet.ColUint32(ColumnNoL(KColName_ProcessSID, aRowSet)); |
|
1087 return TUid::Uid(val); |
|
1088 } |
|
1089 |
|
1090 |
|
1091 void CBTRegistry::DeleteViewL(RDbRowSet& aRowSet, TBool aDeleteAll, const TSecureId& aSecureId) |
|
1092 /** |
|
1093 Delete all the rows in the set whose originating Id is the same as |
|
1094 aSecureId |
|
1095 |
|
1096 @param aRowSet The rowset whose records are to be deleted |
|
1097 @param aDeleteAll If set to ETrue, all rows are deleted. If EFalse, only those |
|
1098 rows whose SID value is same as aSecureId will be deleted. |
|
1099 @param aSecureId The SID of the calling process. |
|
1100 **/ |
|
1101 { |
|
1102 LOG_FUNC |
|
1103 aRowSet.FirstL(); |
|
1104 TInt c = aRowSet.CountL(); |
|
1105 |
|
1106 if( c == 0 ) |
|
1107 { |
|
1108 // No rows, nothing to do |
|
1109 return; |
|
1110 } |
|
1111 |
|
1112 TDbColNo secureIdColNo=ColumnNoL(KColName_ProcessSID, aRowSet); |
|
1113 // There should always be a ProcessSID column present in the view |
|
1114 __ASSERT_ALWAYS(secureIdColNo != KDbNullColNo, Panic(EColumnNotFound)); |
|
1115 |
|
1116 for (TInt i=0; i<c; i++) |
|
1117 { |
|
1118 // Retrieve the current row ready to be accessed |
|
1119 aRowSet.GetL(); |
|
1120 if( aDeleteAll || (aRowSet.ColUint32(secureIdColNo) == aSecureId) ) |
|
1121 { |
|
1122 aRowSet.DeleteL(); |
|
1123 } |
|
1124 // Regardless of the DeleteL or no DeleteL, the cursor remains |
|
1125 // in the same location, so we always need to call NextL. |
|
1126 aRowSet.NextL(); |
|
1127 } |
|
1128 // better try to compact now to avoid ballooning |
|
1129 (void)iDB.Compact(); |
|
1130 } |
|
1131 |
|
1132 |
|
1133 TBTLocalDevice* CBTRegistry::GetLocalDeviceLC() |
|
1134 /** |
|
1135 Get the single row pertaining to the local device |
|
1136 Build and return a TBTLocalDevice |
|
1137 **/ |
|
1138 { |
|
1139 LOG_FUNC |
|
1140 TBTLocalDevice* device = new(ELeave) TBTLocalDevice; // for passing ownership |
|
1141 CleanupStack::PushL(device); |
|
1142 |
|
1143 RDbTable* table = OpenPersistTableL(); |
|
1144 CleanupCloseDeletePushL(table); |
|
1145 |
|
1146 #ifdef _DEBUG |
|
1147 TInt c=0; |
|
1148 TRAP_IGNORE(c=table->CountL()); |
|
1149 __ASSERT_DEBUG(c==1, Panic(ENotOneLocalDeviceEntry)); |
|
1150 #endif |
|
1151 |
|
1152 |
|
1153 TBool success = table->FirstL(); // go to only row in table |
|
1154 if (!success) |
|
1155 { |
|
1156 LOG(_L("BT Registry DB Local Device Table (Persist Table) CORRUPT!")); |
|
1157 User::Leave(KErrEof); |
|
1158 } |
|
1159 |
|
1160 table->GetL(); // mark for retrieval |
|
1161 |
|
1162 TPtrC8 addrBuf(table->ColDes8(ColumnNoL(KColName_DeviceAddress, *table))); |
|
1163 device->SetAddress(static_cast<TBTDevAddr>(addrBuf)); |
|
1164 |
|
1165 device->SetDeviceClass(table->ColUint32(ColumnNoL(KPersistColName_CoD, *table))); |
|
1166 device->SetDeviceName(table->ColDes8(ColumnNoL(KPersistColName_LocalName, *table))); |
|
1167 device->SetScanEnable(static_cast<THCIScanEnable>(table->ColUint8(ColumnNoL(KPersistColName_ScanEnable, *table)))); |
|
1168 device->SetPowerSetting(table->ColUint8(ColumnNoL(KPersistColName_PowerSettings, *table))); |
|
1169 device->SetAFHChannelAssessmentMode(table->ColUint8(ColumnNoL(KPersistColName_AFHChannelAssessmentMode, *table))); |
|
1170 device->SetLimitedDiscoverable(table->ColUint8(ColumnNoL(KPersistColName_LimitedDiscoverable, *table))); |
|
1171 device->SetAcceptPairedOnlyMode(table->ColUint8(ColumnNoL(KPersistColName_AcceptPairedOnlyMode, *table))); |
|
1172 CleanupStack::PopAndDestroy(table); //table |
|
1173 return device; |
|
1174 } |
|
1175 |
|
1176 const TBTCommPortSettings* CBTRegistry::GetCommPortSettingsLC(const TBTCommPortSettings& aSettings) |
|
1177 /** |
|
1178 Get the virtual serial port settings for the port referred to in aSettings |
|
1179 **/ |
|
1180 { |
|
1181 LOG_FUNC |
|
1182 TBTCommPortSettings* settings = new(ELeave) TBTCommPortSettings; // for passing ownership |
|
1183 CleanupStack::PushL(settings); |
|
1184 |
|
1185 RDbView* view = OpenCommPortLC(aSettings); |
|
1186 |
|
1187 // mark for retrieval |
|
1188 view->GetL(); |
|
1189 // get the unit number |
|
1190 settings->SetPort(aSettings.Port()); |
|
1191 // get the device address |
|
1192 TPtrC8 addrBuf(view->ColDes8(ColumnNoL(KColName_DeviceAddress, *view))); |
|
1193 settings->SetBTAddr(static_cast<TBTDevAddr>(addrBuf)); |
|
1194 |
|
1195 // get the uuid |
|
1196 TUUID uuid; |
|
1197 uuid.SetL(view->ColDes8(ColumnNoL(KBTCOMMColName_ServiceUUID, *view))); |
|
1198 settings->SetUUID(uuid); |
|
1199 |
|
1200 // get the service uuid and name |
|
1201 settings->SetSecurityLevel(view->ColUint8(ColumnNoL(KBTCOMMColName_Security, *view))); |
|
1202 settings->SetName(view->ColDes(ColumnNoL(KBTCOMMColName_ServiceName, *view))); |
|
1203 |
|
1204 CleanupStack::PopAndDestroy(view); //closes view |
|
1205 // don't pop settings - C function |
|
1206 return settings; |
|
1207 } |
|
1208 |
|
1209 void CBTRegistry::PutCommPortSettingsInTableL(RDbRowSet& aRowSet, |
|
1210 const TBTCommPortSettings& aSettings) |
|
1211 /** |
|
1212 Update the port settings |
|
1213 **/ |
|
1214 { |
|
1215 LOG_FUNC |
|
1216 aRowSet.SetColL(ColumnNoL(KBTCOMMColName_Port, aRowSet), aSettings.Port()); |
|
1217 aRowSet.SetColL(ColumnNoL(KColName_DeviceAddress, aRowSet), aSettings.BDAddr().Des()); |
|
1218 aRowSet.SetColL(ColumnNoL(KBTCOMMColName_ServiceUUID, aRowSet), aSettings.UUID().Des()); |
|
1219 aRowSet.SetColL(ColumnNoL(KBTCOMMColName_Security, aRowSet), static_cast<TUint>(aSettings.SecurityLevel())); |
|
1220 aRowSet.SetColL(ColumnNoL(KBTCOMMColName_ServiceName, aRowSet), aSettings.Name()); |
|
1221 |
|
1222 TRAPD(err,aRowSet.PutL()); |
|
1223 if (err!=KErrNone) |
|
1224 { |
|
1225 aRowSet.Cancel(); |
|
1226 aRowSet.Reset(); |
|
1227 User::Leave(err); |
|
1228 } |
|
1229 } |
|
1230 |
|
1231 RDbView* CBTRegistry::OpenCommPortL(const TBTCommPortSettings& aSettings) |
|
1232 /** |
|
1233 Return view of the com port specified |
|
1234 **/ |
|
1235 { |
|
1236 LOG_FUNC |
|
1237 // Form the SQL query based on the search criteria |
|
1238 RBTDbQuery query; |
|
1239 CleanupClosePushL(query); |
|
1240 query.FindCommPortL(aSettings.Port()); // just search on port for now |
|
1241 |
|
1242 // execute the SQL with dummy bookmark for now |
|
1243 TDbBookmark dummy; |
|
1244 RDbView* view = OpenViewL(query, dummy); |
|
1245 CleanupCloseDeletePushL(view); |
|
1246 |
|
1247 TInt count = view->CountL(); |
|
1248 |
|
1249 if (!count) |
|
1250 { |
|
1251 User::Leave(KErrNotFound); // nothing in there: which may be OK! |
|
1252 } |
|
1253 |
|
1254 CleanupStack::Pop(view); // returns ownership - don't destroy |
|
1255 CleanupStack::PopAndDestroy(&query); // query |
|
1256 return view; |
|
1257 } |
|
1258 |
|
1259 RDbView* CBTRegistry::OpenCommPortLC(const TBTCommPortSettings& aSettings) |
|
1260 { |
|
1261 LOG_FUNC |
|
1262 RDbView* view = OpenCommPortL(aSettings); |
|
1263 CleanupCloseDeletePushL(view); |
|
1264 return view; |
|
1265 } |
|
1266 |
|
1267 void CBTRegistry::DeleteCommPortSettingsL(RDbView& aCommPortSettingsView) |
|
1268 { |
|
1269 LOG_FUNC |
|
1270 aCommPortSettingsView.DeleteL(); |
|
1271 } |
|
1272 |
|
1273 void CBTRegistry::AddCommPortSettingsL(const TBTCommPortSettings& aSettings, |
|
1274 const TSecureId& aClientSID) |
|
1275 /** |
|
1276 Add port settings row |
|
1277 Create row and enter values in aSettings. |
|
1278 THIS must only be called if the table has been checked for existing settings |
|
1279 **/ |
|
1280 { |
|
1281 LOG_FUNC |
|
1282 #ifdef _DEBUG |
|
1283 // check it's not already there |
|
1284 TRAPD(err, OpenCommPortL(aSettings)); |
|
1285 ASSERT_DEBUG(err==KErrNotFound); |
|
1286 #endif |
|
1287 |
|
1288 RDbTable* table = OpenTableL(KCSYTable); |
|
1289 |
|
1290 //create a record for this port, it wasn't there |
|
1291 CleanupCloseDeletePushL(table); |
|
1292 table->InsertL(); |
|
1293 |
|
1294 table->SetColL(ColumnNoL(KColName_ProcessSID, *table), aClientSID); // store originating client ID |
|
1295 |
|
1296 //put the port values in |
|
1297 PutCommPortSettingsInTableL(*table, aSettings); |
|
1298 CleanupStack::PopAndDestroy(table); //table |
|
1299 } |
|
1300 |
|
1301 void CBTRegistry::UpdateCommPortSettingsL(RDbView& aView, |
|
1302 const TBTCommPortSettings& aSettings) |
|
1303 /** |
|
1304 Update the port settings |
|
1305 **/ |
|
1306 { |
|
1307 LOG_FUNC |
|
1308 aView.UpdateL(); // mark for update |
|
1309 PutCommPortSettingsInTableL(aView, aSettings); |
|
1310 } |
|
1311 |
|
1312 void CBTRegistry::DeleteCorruptRegistryL() |
|
1313 { |
|
1314 LOG_FUNC |
|
1315 // The registry is corrupt so we need to create a new one and notify |
|
1316 // interested parties that all of the user's pairings may have been lost. |
|
1317 |
|
1318 |
|
1319 // close the database (if open) |
|
1320 iDB.Close(); |
|
1321 TInt err = KErrNone; |
|
1322 |
|
1323 // The RDbs method must be used to access the private data cage. |
|
1324 err = iDBMSServer.DeleteDatabase(TBTRegistryDatabaseSecure()(), KBTManServerUid); |
|
1325 if(err) |
|
1326 { |
|
1327 LOG1(_L("UNSUCCESSFUL attempt to delete Corrupt BT Registry DB, error %d"), err); |
|
1328 } |
|
1329 else |
|
1330 { |
|
1331 LOG(_L("Corrupt BT Registry DB Deleted successfully")); |
|
1332 // Use P&S to let UIs know that the registry may have lost some |
|
1333 // of the user's pairings. |
|
1334 RProperty::Set(KPropertyUidBluetoothCategory, |
|
1335 KPropertyKeyBluetoothCorruptRegistryReset, |
|
1336 User::TickCount()); |
|
1337 } |
|
1338 } |
|
1339 |
|
1340 void CBTRegistry::SetupDefaultRegistryL() |
|
1341 { |
|
1342 LOG_FUNC |
|
1343 CreateMetaTableL(); |
|
1344 CreatePersistTableL(); |
|
1345 CreateCSYTableL(); |
|
1346 CreateDeviceTableL(); |
|
1347 |
|
1348 // now add default values for the tables: set all the states to 'unset' |
|
1349 TBTLocalDevice defaultDevice; |
|
1350 |
|
1351 |
|
1352 // Set up the defaults - these will get overwritten if there are appropriate values in the ini file |
|
1353 defaultDevice.SetAddress(TBTDevAddr(0)); |
|
1354 defaultDevice.SetDeviceName(KDefaultLocalName); |
|
1355 defaultDevice.SetScanEnable(EPageScanOnly); |
|
1356 defaultDevice.SetLimitedDiscoverable(EFalse); |
|
1357 defaultDevice.SetDeviceClass(0); |
|
1358 // The registry is being kicked off with a default channel assessment |
|
1359 // mode setting of 'enabled'. This is the default if h/w supports |
|
1360 // channel assessment. If h/w does not support channel assessment, |
|
1361 // this value becomes meaningless. |
|
1362 // Any use of it to update h/w will be rejected. |
|
1363 defaultDevice.SetAFHChannelAssessmentMode(ETrue); |
|
1364 defaultDevice.SetAcceptPairedOnlyMode(EFalse); |
|
1365 |
|
1366 // Try and get any relevant parameters from the ini file |
|
1367 TRAP_IGNORE(GetDefaultDeviceFromIniL(defaultDevice)); // Ignore any leaves as they cannot result in corruption of defaultDevice |
|
1368 |
|
1369 UpdateLocalDeviceL(defaultDevice); |
|
1370 //#pragma message("defaults for persist table ini file/licensee?") |
|
1371 } |
|
1372 |
|
1373 // |
|
1374 |
|
1375 TInt CBTRegistry::SetDeviceName(const TDesC& aDeviceName, TBTLocalDevice& aDevice) |
|
1376 { |
|
1377 // GetDefaultDeviceName() returns 16bit unicode, it need to be converted to 8bit UTF |
|
1378 TBTDeviceName8 tempBuf; |
|
1379 TInt error = CnvUtfConverter::ConvertFromUnicodeToUtf8(tempBuf, aDeviceName); |
|
1380 if(error == KErrNone) |
|
1381 { |
|
1382 aDevice.SetDeviceName(tempBuf); |
|
1383 } |
|
1384 return error; |
|
1385 } |
|
1386 |
|
1387 TBool CBTRegistry::SetDeviceNameFromIniFile(TBTLocalDevice& aDevice, RBuf8& bufPtr) |
|
1388 { |
|
1389 // Default so try the old mechanism. |
|
1390 _LIT8(KVarDeviceName, "DeviceName"); |
|
1391 TPtrC8 devName(NULL, 0); |
|
1392 if (FindVar(bufPtr, KVarDeviceName, devName) && devName.Length() <= KMaxBCBluetoothNameLen) |
|
1393 { |
|
1394 aDevice.SetDeviceName(devName); |
|
1395 return ETrue; |
|
1396 } |
|
1397 return EFalse; |
|
1398 } |
|
1399 |
|
1400 void CBTRegistry::GetDefaultDeviceFromIniL(TBTLocalDevice& aDevice) |
|
1401 { |
|
1402 LOG_FUNC |
|
1403 // Try and open the .ini file and get any relavent parameters |
|
1404 RFs fileSession; |
|
1405 User::LeaveIfError(fileSession.Connect()); |
|
1406 CleanupClosePushL(fileSession); |
|
1407 |
|
1408 _LIT(KIniDrive, "Z:"); |
|
1409 _LIT(KIniName, "DefaultBtReg.ini"); |
|
1410 TFileName iniFileName; |
|
1411 fileSession.PrivatePath(iniFileName); |
|
1412 iniFileName.Insert(0, KIniDrive); |
|
1413 iniFileName.Append(KIniName); |
|
1414 |
|
1415 RFile file; |
|
1416 User::LeaveIfError(file.Open(fileSession, iniFileName, EFileStreamText|EFileRead)); |
|
1417 CleanupClosePushL(file); |
|
1418 TInt data_size = 0; |
|
1419 User::LeaveIfError(file.Size(data_size)); |
|
1420 |
|
1421 // All text encoding is narrow 8-bit ASCII as ini files generated on a PC will be encoded that way |
|
1422 // and the bluetooth specification only allows 8-bit ASCII strings so there is no need to convert |
|
1423 // between ASCII and Unicode and back again. |
|
1424 RBuf8 bufPtr; |
|
1425 bufPtr.CreateL(data_size); |
|
1426 CleanupClosePushL(bufPtr); |
|
1427 User::LeaveIfError(file.Read(bufPtr)); |
|
1428 |
|
1429 // Any or all of the following variables may be specified in this ini file: |
|
1430 // |
|
1431 // Variable: Variable Name: Values Taken: |
|
1432 // Default device name DeviceName String |
|
1433 // Inquiry scan enabled by default InquiryScan 0 or 1 |
|
1434 // Page scanning enabled by default PageScan 0 or 1 |
|
1435 // Limited discovery enabled by default LimitedDiscovery 0 or 1 |
|
1436 // Default device class DeviceClass Integer (decimal format) |
|
1437 // Allow paired only eanabled by default AcceptPairedOnlyMode 0 or 1 |
|
1438 // |
|
1439 // Notes on file syntax: |
|
1440 // - Variable Names are followed by an ‘=’ character and then the value taken. |
|
1441 // - There are no whitespaces in variable names. |
|
1442 // - Variable names may be followed by any number of whitespaces, until the first character of the value taken. Thereafter any whitespaces are considered part of the value until the end of line. |
|
1443 // - All characters should be narrow (standard 8bit ASCII). |
|
1444 // - Integers should contain only the standard characters 0 to 9. |
|
1445 // - Boolean values should be indicated by a 0 or 1. |
|
1446 // - Strings may contain whitespaces, but any at the beginning will be stripped. |
|
1447 // - There is no need to terminate the file with a new line. |
|
1448 // - Anything after "//" on a line is ignored as comments |
|
1449 |
|
1450 |
|
1451 // Remove any comments from the buffer |
|
1452 TInt slashPos; |
|
1453 TInt commentLength; |
|
1454 TPtr8 comment(NULL, 0); |
|
1455 _LIT8(KDoubleSlash, "//"); |
|
1456 while ((slashPos = bufPtr.Find(KDoubleSlash)) != KErrNotFound) |
|
1457 { |
|
1458 _LIT8(KEol, "\n"); |
|
1459 comment.Set(bufPtr.MidTPtr(slashPos)); |
|
1460 if ((commentLength = comment.Find(KEol)) == KErrNotFound) |
|
1461 { |
|
1462 commentLength = comment.Length(); // just to end of file |
|
1463 } |
|
1464 bufPtr.Replace(slashPos, commentLength, KNullDesC8); |
|
1465 } |
|
1466 |
|
1467 // Get the default device name |
|
1468 // we try to get the device name from deviceattributes.ini as a first resort, |
|
1469 // deviceattributes.ini is global device configuration for setting global data like the device name |
|
1470 |
|
1471 CDeviceTypeInformation* deviceInfo = NULL; |
|
1472 TRAPD(ret, deviceInfo = SysUtil::GetDeviceTypeInfoL()); |
|
1473 CleanupStack::PushL(deviceInfo); |
|
1474 TPtrC16 deviceName; |
|
1475 |
|
1476 if (ret == KErrNone) |
|
1477 { |
|
1478 ret = deviceInfo->GetDefaultDeviceName(deviceName); |
|
1479 if (ret == KErrNone) |
|
1480 { |
|
1481 LEAVEIFERRORL(SetDeviceName(deviceName, aDevice)); |
|
1482 } |
|
1483 else if (ret == CDeviceTypeInformation::KDefaultValue) |
|
1484 { |
|
1485 if(!SetDeviceNameFromIniFile(aDevice, bufPtr)) |
|
1486 { |
|
1487 ret = SetDeviceName(deviceName, aDevice); |
|
1488 __ASSERT_DEBUG(ret == KErrNone,Panic(ECorruptDeviceEntry)); |
|
1489 if(ret != KErrNone) |
|
1490 { |
|
1491 SetDeviceNameFromIniFile(aDevice, bufPtr); |
|
1492 } |
|
1493 } |
|
1494 } |
|
1495 else |
|
1496 { |
|
1497 SetDeviceNameFromIniFile(aDevice, bufPtr); |
|
1498 } |
|
1499 } |
|
1500 else |
|
1501 { // if the above did not work, then use the old mechanism |
|
1502 SetDeviceNameFromIniFile(aDevice, bufPtr); |
|
1503 } |
|
1504 |
|
1505 // Get default scan enabled status |
|
1506 TInt scanStatus = aDevice.ScanEnable(); |
|
1507 TInt result = 0; |
|
1508 _LIT8(KVarInquiryScan, "InquiryScan"); |
|
1509 if (FindVar(bufPtr, KVarInquiryScan, result)) |
|
1510 { |
|
1511 if (result) |
|
1512 scanStatus |= EInquiryScanOnly; |
|
1513 else |
|
1514 scanStatus &= ~EInquiryScanOnly; |
|
1515 } |
|
1516 |
|
1517 _LIT8(KVarPageScan, "PageScan"); |
|
1518 if (FindVar(bufPtr, KVarPageScan, result)) |
|
1519 { |
|
1520 if (result) |
|
1521 scanStatus |= EPageScanOnly; |
|
1522 else |
|
1523 scanStatus &= ~EPageScanOnly; |
|
1524 } |
|
1525 aDevice.SetScanEnable(static_cast<THCIScanEnable>(scanStatus)); |
|
1526 |
|
1527 |
|
1528 // Get default limited discovery status |
|
1529 _LIT8(KVarLimitedDiscovery, "LimitedDiscovery"); |
|
1530 if (FindVar(bufPtr, KVarLimitedDiscovery, result)) |
|
1531 { |
|
1532 aDevice.SetLimitedDiscoverable(result); |
|
1533 } |
|
1534 |
|
1535 |
|
1536 // Get default device class |
|
1537 _LIT8(KVarDeviceClass, "DeviceClass"); |
|
1538 if (FindVar(bufPtr, KVarDeviceClass, result)) |
|
1539 { |
|
1540 aDevice.SetDeviceClass(result); |
|
1541 } |
|
1542 |
|
1543 |
|
1544 // Get default AFH channel assessment only mode |
|
1545 _LIT8(KAFHChannelAssessmentMode, "AFHChannelAssessmentMode"); |
|
1546 if (FindVar(bufPtr, KAFHChannelAssessmentMode, result)) |
|
1547 { |
|
1548 aDevice.SetAFHChannelAssessmentMode(result); |
|
1549 } |
|
1550 |
|
1551 |
|
1552 // Get default accept paired only mode |
|
1553 _LIT8(KAcceptPairedOnlyMode, "AcceptPairedOnlyMode"); |
|
1554 if (FindVar(bufPtr, KAcceptPairedOnlyMode, result)) |
|
1555 { |
|
1556 aDevice.SetAcceptPairedOnlyMode(result); |
|
1557 } |
|
1558 |
|
1559 |
|
1560 CleanupStack::PopAndDestroy(4, &fileSession); // deviceinfo, bufPtr, file, fileSession |
|
1561 } |
|
1562 |
|
1563 TBool CBTRegistry::FindVar(const TDesC8& aPtr, const TDesC8 &aVarName, TPtrC8 &aResult) const |
|
1564 { |
|
1565 LOG_FUNC |
|
1566 // Find the variable name |
|
1567 TInt start=aPtr.Find(aVarName); |
|
1568 if (start == KErrNotFound) |
|
1569 { |
|
1570 return EFalse; |
|
1571 } |
|
1572 |
|
1573 // Now find the end of the value string (end of line or end of file) |
|
1574 TPtrC8 value(aPtr.Mid(start)); |
|
1575 _LIT8(KEol, "\n"); |
|
1576 TInt length = value.Find(KEol); |
|
1577 if (length != KErrNotFound) |
|
1578 { |
|
1579 if (value[length-1] == '\r') |
|
1580 { |
|
1581 length--; |
|
1582 } |
|
1583 } |
|
1584 else |
|
1585 { |
|
1586 length = value.Length(); |
|
1587 } |
|
1588 |
|
1589 // Now find the start of the value to be parsed |
|
1590 TLex8 lex(aPtr.Mid(start, length)); |
|
1591 TChar next = lex.Get(); |
|
1592 while (next != '=' && next != NULL) |
|
1593 { |
|
1594 next = lex.Get(); // Step through until we find a '=' character or EOS |
|
1595 } |
|
1596 |
|
1597 if (next == NULL) |
|
1598 { |
|
1599 return EFalse; // End of string was found before '=' so there's no valid value. |
|
1600 } |
|
1601 |
|
1602 lex.SkipSpace(); // Will now be at the start of the value |
|
1603 |
|
1604 // Now copy the variable value into the result |
|
1605 aResult.Set(lex.Remainder()); |
|
1606 |
|
1607 return ETrue; |
|
1608 } |
|
1609 |
|
1610 |
|
1611 TBool CBTRegistry::FindVar(const TDesC8& aPtr, const TDesC8 &aVarName, TInt &aResult) const |
|
1612 { |
|
1613 LOG_FUNC |
|
1614 TPtrC8 ptr(NULL,0); |
|
1615 |
|
1616 if (FindVar(aPtr, aVarName,ptr)) |
|
1617 { |
|
1618 TLex8 lex(ptr); |
|
1619 if (lex.Val(aResult) == KErrNone) |
|
1620 { |
|
1621 return(ETrue); |
|
1622 } |
|
1623 } |
|
1624 |
|
1625 return(EFalse); |
|
1626 } |
|
1627 |
|
1628 |
|
1629 TBTRegistryDatabaseSecure::TBTRegistryDatabaseSecure() |
|
1630 { |
|
1631 LOG_FUNC |
|
1632 iBuf.Append(RFs::GetSystemDrive() + 'a'); //Gets the system drive and convert it from enum to a char |
|
1633 iBuf.Append(':'); |
|
1634 iBuf.Append(KBTRegistryDatabaseSecure); |
|
1635 } |
|
1636 |
|
1637 const TDesC& TBTRegistryDatabaseSecure::operator()() const |
|
1638 { |
|
1639 LOG_FUNC |
|
1640 return iBuf; |
|
1641 } |
|
1642 |