|
1 /* |
|
2 * Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Maintain a Bluetooth devices data model for paired devices view |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "btpairedmodel.h" |
|
20 #include <btengutil.h> |
|
21 #include "debug.h" |
|
22 #include "btui.h" |
|
23 |
|
24 const TInt KMaxCheckedConnections=20; |
|
25 |
|
26 |
|
27 // --------------------------------------------------------------------- |
|
28 // CBTPairedModel::CBTPairedModel |
|
29 // --------------------------------------------------------------------- |
|
30 // |
|
31 CBTPairedModel::CBTPairedModel(MBTDeviceObserver* aObserver, TBTDeviceSortOrder* aOrder) |
|
32 : CBTDevModelBase(aObserver, aOrder) |
|
33 { |
|
34 TRACE_FUNC_ENTRY |
|
35 TRACE_FUNC_EXIT |
|
36 } |
|
37 |
|
38 // --------------------------------------------------------------------- |
|
39 // CBTPairedModel::NewL |
|
40 // --------------------------------------------------------------------- |
|
41 // |
|
42 CBTPairedModel* CBTPairedModel::NewL(MBTDeviceObserver* aObserver, TBTDeviceSortOrder* aOrder ) |
|
43 { |
|
44 CBTPairedModel* self = new (ELeave) CBTPairedModel(aObserver, aOrder); |
|
45 CleanupStack::PushL(self); |
|
46 self->ConstructL(); |
|
47 CleanupStack::Pop(self); |
|
48 |
|
49 return self; |
|
50 } |
|
51 |
|
52 // -------------------------------------------------------------------------------------------- |
|
53 // Destructor |
|
54 // -------------------------------------------------------------------------------------------- |
|
55 // |
|
56 CBTPairedModel::~CBTPairedModel() |
|
57 { |
|
58 TRACE_FUNC_ENTRY |
|
59 |
|
60 delete iConnMan; |
|
61 delete iPairingDevice; |
|
62 delete iLinks; |
|
63 delete iBtEngSettings; |
|
64 iSocketServ.Close(); |
|
65 |
|
66 TRACE_FUNC_EXIT |
|
67 } |
|
68 |
|
69 // --------------------------------------------------------------------- |
|
70 // CBTPairedModel::ConstructL |
|
71 // ---------------------------------------------------------------------- |
|
72 // |
|
73 void CBTPairedModel::ConstructL() |
|
74 { |
|
75 TRACE_FUNC_ENTRY |
|
76 |
|
77 // get all devices from btregistry to cache - local copy of CBTDeviceArray |
|
78 iDevMan = CBTEngDevMan::NewL(this); |
|
79 iConnMan = CBTEngConnMan::NewL(this); |
|
80 iSearchPattern.FindAll(); |
|
81 iRegistryObserver = CBTRegistryObserver::NewL(this, iSearchPattern); |
|
82 iRegistryObserver->Refresh(); |
|
83 User::LeaveIfError( iSocketServ.Connect() ); |
|
84 iLinks=CBluetoothPhysicalLinks::NewL(*this,iSocketServ); |
|
85 |
|
86 iBtEngSettings = CBTEngSettings::NewL(this); |
|
87 |
|
88 TRACE_FUNC_EXIT |
|
89 } |
|
90 |
|
91 // --------------------------------------------------------------------- |
|
92 // CBTPairedModel::IsAnyDeviceConnected |
|
93 // ---------------------------------------------------------------------- |
|
94 // |
|
95 TBool CBTPairedModel::IsAnyDeviceConnected() |
|
96 { |
|
97 TRACE_FUNC_ENTRY |
|
98 |
|
99 FlagPhysicallyConnectedDevices(iDeviceArray); |
|
100 |
|
101 for(TInt i = 0; i < iDeviceArray.Count(); i++) |
|
102 { |
|
103 if(iDeviceArray[i]->iStatus & (EStatusPhysicallyConnected|EStatusBtuiConnected)) |
|
104 { |
|
105 TRACE_FUNC_EXIT |
|
106 return ETrue; |
|
107 } |
|
108 } |
|
109 |
|
110 TRACE_FUNC_EXIT |
|
111 |
|
112 return EFalse; |
|
113 } |
|
114 |
|
115 // --------------------------------------------------------------------- |
|
116 // CBTPairedModel::DoChangeDevice |
|
117 // --------------------------------------------------------------------- |
|
118 |
|
119 TInt CBTPairedModel::DoChangeDeviceL(const TBTDevice& aDevice) |
|
120 { |
|
121 TRACE_FUNC_ENTRY |
|
122 TRACE_BDADDR(aDevice.iAddr) |
|
123 // check that the device actually still exists |
|
124 if(aDevice.iOperation != EOpPair ) |
|
125 { |
|
126 User::LeaveIfError( GetIndexByAddress(aDevice.iAddr, aDevice.iIndex ) ); |
|
127 } |
|
128 |
|
129 // disconnect device to be unpaired, or blocked |
|
130 if((aDevice.iOperation == EOpBlock || aDevice.iOperation == EOpUnpair )) |
|
131 { |
|
132 if( iState != EDisconnectBeforeOperationState) |
|
133 { |
|
134 // disconnect by CBTEngConnMan if connected that way. |
|
135 if (aDevice.iStatus & static_cast<TInt>(EStatusBtuiConnected ) ) |
|
136 { |
|
137 TInt code=KErrNone; |
|
138 TRAPD(err, |
|
139 iState=EDisconnectBeforeOperationState; |
|
140 iDisconnectDevice=new(ELeave) TBTDevice(aDevice); |
|
141 code=iConnMan->Disconnect(aDevice.iAddr,EBTDiscImmediate); |
|
142 ); |
|
143 // if the return code is KErrNone then there will be |
|
144 // a callback. However if it fails, there will not be any. |
|
145 // So the execution will go on inside this method, if there was an error. |
|
146 if(err == KErrNone && code==KErrNone ) |
|
147 { |
|
148 return KErrNone; |
|
149 } |
|
150 |
|
151 } |
|
152 else // try disconnecting from the link layer |
|
153 { |
|
154 TInt code=KErrNone; |
|
155 TRAPD(err, |
|
156 iState=EDisconnectBeforeOperationState; |
|
157 iDisconnectDevice=new(ELeave) TBTDevice(aDevice); |
|
158 code=iLinks->Disconnect(aDevice.iAddr); |
|
159 ); |
|
160 // if the return code is KErrNone then there will be |
|
161 // a callback. However if it fails, there will not be any. |
|
162 // So the execution will go on inside this method, if there was an error. |
|
163 if(err == KErrNone && code==KErrNone ) |
|
164 { |
|
165 return KErrNone; |
|
166 } |
|
167 } |
|
168 } |
|
169 else |
|
170 iState=EIdleState; |
|
171 |
|
172 } |
|
173 |
|
174 if( aDevice.iOperation ==EOpPair) |
|
175 { |
|
176 DoPairDeviceL(); |
|
177 TRACE_FUNC_EXIT |
|
178 return KErrNone; |
|
179 } |
|
180 |
|
181 TInt err = CBTDevModelBase::DoChangeDeviceL(aDevice); |
|
182 if(iDisconnectDevice!= NULL) |
|
183 { |
|
184 delete iDisconnectDevice; |
|
185 iDisconnectDevice=NULL; |
|
186 } |
|
187 |
|
188 if (err != KErrNone) |
|
189 { |
|
190 TBTDevAddr addr; |
|
191 if(aDevice.iAddr == KNullAddress ) |
|
192 { |
|
193 if(aDevice.iIndex < 0 || aDevice.iIndex >= iDeviceArray.Count()) |
|
194 return KErrArgument; |
|
195 else |
|
196 addr=iDeviceArray[aDevice.iIndex]->iAddr; |
|
197 } |
|
198 else |
|
199 addr=aDevice.iAddr; |
|
200 |
|
201 switch (aDevice.iOperation) |
|
202 { |
|
203 case EOpConnect: |
|
204 { |
|
205 err = iConnMan->Connect(addr, aDevice.iDeviceClass); |
|
206 break; |
|
207 } |
|
208 case EOpDisconnect: |
|
209 { |
|
210 iDisconnectDevice=new(ELeave) TBTDevice(aDevice); |
|
211 if (aDevice.iStatus & static_cast<TInt>(EStatusBtuiConnected ) ) |
|
212 { |
|
213 err = iConnMan->Disconnect(addr, EBTDiscImmediate); |
|
214 } |
|
215 else |
|
216 { |
|
217 err=iLinks->Disconnect(aDevice.iAddr); |
|
218 } |
|
219 |
|
220 break; |
|
221 } |
|
222 default: |
|
223 User::Leave(err); |
|
224 break; |
|
225 } |
|
226 } |
|
227 |
|
228 TRACE_FUNC_EXIT |
|
229 |
|
230 return err; |
|
231 } |
|
232 |
|
233 // --------------------------------------------------------------------- |
|
234 // CBTPairedModel::DoCancelChange |
|
235 // --------------------------------------------------------------------- |
|
236 // |
|
237 void CBTPairedModel::DoCancelChangeL(const TBTDevice& aDevice) |
|
238 { |
|
239 TRACE_FUNC_ENTRY |
|
240 |
|
241 if(aDevice.iIndex >= iDeviceArray.Count()) |
|
242 { |
|
243 TRACE_INFO((_L("index is %d, max expected is %d"), aDevice.iIndex, iDeviceArray.Count())); |
|
244 TRACE_FUNC_EXIT |
|
245 return; |
|
246 } |
|
247 |
|
248 // in case it was stopped |
|
249 iRegistryObserver->StartIfNotRunning(); |
|
250 switch (aDevice.iOperation) |
|
251 { |
|
252 case EOpPair: |
|
253 if( iState==EDeleteDeviceState || iState==EAddDeviceState ) |
|
254 { |
|
255 iDevMan->Cancel(); |
|
256 } |
|
257 else |
|
258 { |
|
259 iConnMan->CancelPairDevice(); |
|
260 } |
|
261 delete iPairingDevice; |
|
262 iPairingDevice=NULL; |
|
263 iState=EIdleState; |
|
264 iRegistryObserver->Refresh(); |
|
265 break; |
|
266 |
|
267 case EOpConnect: |
|
268 { |
|
269 |
|
270 TBTDevAddr addr; |
|
271 if(aDevice.iIndex == KErrNotFound) |
|
272 { |
|
273 addr=aDevice.iAddr; |
|
274 } |
|
275 else |
|
276 { |
|
277 addr=iDeviceArray[aDevice.iIndex]->iAddr; |
|
278 } |
|
279 |
|
280 iConnMan->CancelConnect(addr); |
|
281 break; |
|
282 } |
|
283 default: |
|
284 CBTDevModelBase::CancelChange(aDevice); |
|
285 return; |
|
286 } |
|
287 iRegistryObserver->StartIfNotRunning(); |
|
288 |
|
289 if(iQueue.Count()>0) |
|
290 { |
|
291 delete iQueue[0]; |
|
292 iQueue.Remove(0); |
|
293 HandleQueue(); |
|
294 } |
|
295 |
|
296 TRACE_FUNC_EXIT |
|
297 } |
|
298 |
|
299 // --------------------------------------------------------------------- |
|
300 // CBTPairedModel::HandleNewDevice |
|
301 // |
|
302 // Adds the device if it is not banned |
|
303 // --------------------------------------------------------------------- |
|
304 // |
|
305 void CBTPairedModel::HandleNewDeviceL(const CBTDevice* aRegDevice, |
|
306 TNameEntry* aNameEntry) |
|
307 { |
|
308 TRACE_FUNC_ENTRY |
|
309 |
|
310 // It is needed to filter out blocked devices, |
|
311 // since otherwise blocked and paired devices would |
|
312 // be listed. |
|
313 if( ! aRegDevice->GlobalSecurity().Banned() |
|
314 && IsUserAwarePaired( aRegDevice->AsNamelessDevice() ) ) |
|
315 { |
|
316 AddDeviceL(aRegDevice, aNameEntry, EOpNone); |
|
317 } |
|
318 |
|
319 TRACE_FUNC_EXIT |
|
320 } |
|
321 |
|
322 // ----------------------------------------------------------------------- |
|
323 // CBTPairedModel::CreateDevice |
|
324 // |
|
325 // This implementaion will add the connectable status from the superclass. |
|
326 // ----------------------------------------------------------------------- |
|
327 // |
|
328 TBTDevice* CBTPairedModel::CreateDeviceL(const CBTDevice* aRegDevice, |
|
329 TNameEntry* aNameEntry) |
|
330 { |
|
331 TRACE_FUNC_ENTRY |
|
332 |
|
333 TBTDevice* device = CBTDevModelBase::CreateDeviceL(aRegDevice, aNameEntry); |
|
334 |
|
335 // add EStatusBtuiConnected status if the device has a profile connection |
|
336 TBTEngConnectionStatus connStatus; |
|
337 iConnMan->IsConnected(device->iAddr, connStatus); |
|
338 |
|
339 if(connStatus == EBTEngConnecting || connStatus == EBTEngConnected) |
|
340 { |
|
341 SetStatusFlags(device->iStatus,EStatusBtuiConnected); |
|
342 } |
|
343 |
|
344 // add connectable status |
|
345 TBool connectable=EFalse; |
|
346 iConnMan->IsConnectable(aRegDevice->BDAddr(), aRegDevice->DeviceClass(), connectable ); |
|
347 |
|
348 if( connectable) |
|
349 { |
|
350 SetStatusFlags(device->iStatus, EStatusConnectable ); |
|
351 } |
|
352 |
|
353 TRACE_FUNC_EXIT |
|
354 |
|
355 return device; |
|
356 } |
|
357 |
|
358 // --------------------------------------------------------------------- |
|
359 // CBTPairedModel::ConnectComplete |
|
360 // from MBTEngConnObserver |
|
361 // ---------------------------------------------------------------------- |
|
362 // |
|
363 void CBTPairedModel::ConnectComplete(TBTDevAddr& aAddr, TInt aErr, RBTDevAddrArray* aConflicts) |
|
364 { |
|
365 TRACE_FUNC_ENTRY |
|
366 |
|
367 TRACE_INFO((_L("aErr=%d"), aErr)) |
|
368 |
|
369 TInt index = GetIndexByAddress(aAddr); |
|
370 TBool requestIssuedFromPhone = EFalse; |
|
371 TBTDevice connectedDevice; |
|
372 |
|
373 // was the device connected from request by the ui |
|
374 if(iQueue.Count()>0 && iQueue[0]->iOperation==EOpConnect && |
|
375 iQueue[0]->iAddr == aAddr) |
|
376 { |
|
377 requestIssuedFromPhone = ETrue; |
|
378 if(index >=0) // is it from paired list |
|
379 { |
|
380 connectedDevice=*iDeviceArray[index]; |
|
381 connectedDevice.iOperation=EOpConnect; |
|
382 } |
|
383 else |
|
384 { |
|
385 connectedDevice=*iQueue[0]; |
|
386 } |
|
387 |
|
388 } |
|
389 else |
|
390 { |
|
391 requestIssuedFromPhone = EFalse; |
|
392 if(index >=0) // is it from paired list |
|
393 { |
|
394 connectedDevice=*iDeviceArray[index]; |
|
395 connectedDevice.iOperation=EOpConnect; |
|
396 } |
|
397 else |
|
398 { |
|
399 // it was not. Try to fill what can be filled. |
|
400 connectedDevice.iAddr=aAddr; |
|
401 connectedDevice.iIndex=KErrNotFound; |
|
402 connectedDevice.iOperation = EOpConnect; |
|
403 } |
|
404 } |
|
405 |
|
406 if (aErr == KErrAlreadyExists ) |
|
407 { |
|
408 // gather the names of the conflicting devices. |
|
409 RBTDevNameArray nameArray; |
|
410 for (TInt i = 0; aConflicts!= NULL && i < aConflicts->Count(); i++) |
|
411 { |
|
412 //remove duplicates |
|
413 if(i>0&& (*aConflicts)[i]==(*aConflicts)[i-1]) |
|
414 { |
|
415 continue; |
|
416 } |
|
417 TInt di = GetIndexByAddress((*aConflicts)[i]); |
|
418 |
|
419 if(di >=0 ) |
|
420 { |
|
421 nameArray.Append(&iDeviceArray[di]->iName); |
|
422 } |
|
423 } |
|
424 |
|
425 // we will unset the connect status of the device if connection failed & |
|
426 // it is found in paired devices. |
|
427 if( index >= 0 ) |
|
428 { |
|
429 // add EStatusBtuiConnected status if the device has a profile connection |
|
430 TBTEngConnectionStatus connStatus; |
|
431 iConnMan->IsConnected(connectedDevice.iAddr, connStatus); |
|
432 |
|
433 if (connStatus != EBTEngConnecting && connStatus != EBTEngConnected) |
|
434 { |
|
435 TRACE_INFO(_L("Unset EStatusBtuiConnected")) |
|
436 UnsetStatusFlags(iDeviceArray[index]->iStatus,EStatusBtuiConnected ); |
|
437 } |
|
438 } |
|
439 |
|
440 if(iObserver) |
|
441 { |
|
442 //Show only phone issued request complete notes |
|
443 //Do not show notes for device issued request when BTUI is active |
|
444 if ( requestIssuedFromPhone ) |
|
445 { |
|
446 iObserver->NotifyChangeDeviceComplete(aErr, connectedDevice, &nameArray); |
|
447 } |
|
448 |
|
449 SendRefreshIfNoError(aErr); |
|
450 } |
|
451 nameArray.Reset(); |
|
452 } |
|
453 else |
|
454 { |
|
455 if (aErr == KErrNone) |
|
456 { |
|
457 // we will set the connect status of the device |
|
458 // if it is found in paired devices. |
|
459 if( index >= 0 ) |
|
460 { |
|
461 SetStatusFlags(iDeviceArray[index]->iStatus,EStatusBtuiConnected ); |
|
462 } |
|
463 } |
|
464 else |
|
465 { |
|
466 // we will unset the connect status of the device if connection failed & |
|
467 // it is found in paired devices. |
|
468 if( index >= 0 ) |
|
469 { |
|
470 // add EStatusBtuiConnected status if the device has a profile connection |
|
471 TBTEngConnectionStatus connStatus; |
|
472 iConnMan->IsConnected(connectedDevice.iAddr, connStatus); |
|
473 |
|
474 if (connStatus != EBTEngConnecting && connStatus != EBTEngConnected) |
|
475 { |
|
476 TRACE_INFO(_L("Unset EStatusBtuiConnected")) |
|
477 UnsetStatusFlags(iDeviceArray[index]->iStatus,EStatusBtuiConnected ); |
|
478 } |
|
479 } |
|
480 } |
|
481 if(iObserver) |
|
482 { |
|
483 //Show only phone issued request complete notes |
|
484 //Do not show notes for device issued request when BTUI is active |
|
485 if ( requestIssuedFromPhone ) |
|
486 { |
|
487 iObserver->NotifyChangeDeviceComplete(aErr, connectedDevice); |
|
488 } |
|
489 |
|
490 SendRefreshIfNoError(aErr); |
|
491 } |
|
492 } |
|
493 |
|
494 // Process the next command if the connect was |
|
495 //initiated by this UI. |
|
496 if(iQueue.Count()>0 && iQueue[0]->iOperation==EOpConnect && |
|
497 iQueue[0]->iAddr == aAddr) |
|
498 { |
|
499 delete iQueue[0]; |
|
500 iQueue.Remove(0); |
|
501 HandleQueue(); |
|
502 } |
|
503 else |
|
504 { |
|
505 if( iQueue.Count()==0 ) |
|
506 { |
|
507 TRACE_INFO((_L("op Q is empty"))); |
|
508 } |
|
509 else |
|
510 { |
|
511 TRACE_INFO((_L("unexpected op Q contents, count is %d, op is %d"), iDeviceArray.Count(), iQueue[0]->iOperation)); |
|
512 } |
|
513 } |
|
514 TRACE_FUNC_EXIT |
|
515 } |
|
516 |
|
517 // --------------------------------------------------------------------- |
|
518 // CBTPairedModel::PowerStateChanged |
|
519 // from MBTEngSettingObserver |
|
520 // ---------------------------------------------------------------------- |
|
521 // |
|
522 void CBTPairedModel::PowerStateChanged( TBTPowerStateValue ) |
|
523 { |
|
524 TRACE_FUNC_ENTRY |
|
525 |
|
526 // This is implemented for case like when user choses offlne mode, Bluetooth is swithced off |
|
527 // very fast. Bt audio components don't have enough time to close audio connection. |
|
528 // BTUI needs to update UI display. |
|
529 |
|
530 TInt count = iDeviceArray.Count(); |
|
531 |
|
532 for (TInt i = 0; i < count; i++) |
|
533 { |
|
534 UnsetStatusFlags(iDeviceArray[i]->iStatus, EStatusBtuiConnected ); |
|
535 } |
|
536 |
|
537 SendRefreshIfNoError(KErrNone); |
|
538 |
|
539 TRACE_FUNC_EXIT |
|
540 } |
|
541 |
|
542 // ---------------------------------------------------- |
|
543 // CBTPairedModel::VisibilityModeChanged |
|
544 // from MBTEngSettingObserver |
|
545 // ---------------------------------------------------- |
|
546 // |
|
547 void CBTPairedModel::VisibilityModeChanged( TBTVisibilityMode ) |
|
548 { |
|
549 TRACE_FUNC_ENTRY |
|
550 |
|
551 |
|
552 TRACE_FUNC_EXIT |
|
553 } |
|
554 |
|
555 // --------------------------------------------------------------------- |
|
556 // CBTPairedModel::DisconnectComplete |
|
557 // from MBTEngConnObserver |
|
558 // ---------------------------------------------------------------------- |
|
559 // |
|
560 void CBTPairedModel::DisconnectComplete(TBTDevAddr& aAddr, TInt aErr) |
|
561 { |
|
562 TRACE_FUNC_ENTRY |
|
563 |
|
564 // the disconnect was part of a unpairing or blocking operation |
|
565 if(iState == EDisconnectBeforeOperationState && iDisconnectDevice && aAddr == iDisconnectDevice->iAddr ) |
|
566 { |
|
567 |
|
568 TRAPD(err, |
|
569 DoChangeDeviceL(*iDisconnectDevice); |
|
570 ); |
|
571 iState=EIdleState; |
|
572 if(err != KErrNone) |
|
573 { |
|
574 HandleLeave(err,iDisconnectDevice); |
|
575 } |
|
576 TRACE_FUNC_EXIT |
|
577 return; |
|
578 } |
|
579 |
|
580 TInt index = GetIndexByAddress(aAddr); |
|
581 |
|
582 // the disconnected device was not the devicein the list, |
|
583 // so we do not tell anyone about it. |
|
584 if ( iDisconnectDevice == NULL || iDisconnectDevice->iAddr != aAddr ) |
|
585 { |
|
586 if (index >=0 ) |
|
587 { |
|
588 UnsetStatusFlags(iDeviceArray[index]->iStatus, EStatusBtuiConnected ); |
|
589 } |
|
590 |
|
591 SendRefreshIfNoError(KErrNone); |
|
592 |
|
593 TBTDevice disconnectedDevice; |
|
594 disconnectedDevice.iAddr = aAddr; |
|
595 // Notify needed when there is active disconnect query dialog |
|
596 iObserver->NotifyChangeDeviceComplete(KErrDisconnected, disconnectedDevice); |
|
597 |
|
598 TRACE_FUNC_EXIT |
|
599 return; |
|
600 } |
|
601 |
|
602 if(index >=0 ) |
|
603 { |
|
604 // set it to "not connected" no matter disconnection works or not |
|
605 UnsetStatusFlags(iDeviceArray[index]->iStatus, EStatusBtuiConnected ); |
|
606 iDeviceArray[index]->iOperation = EOpDisconnect; |
|
607 iObserver->NotifyChangeDeviceComplete(aErr, *iDeviceArray[index]); |
|
608 } |
|
609 else |
|
610 { |
|
611 iDisconnectDevice->iIndex=index; |
|
612 iObserver->NotifyChangeDeviceComplete(aErr, *iDisconnectDevice); |
|
613 } |
|
614 |
|
615 delete iDisconnectDevice; |
|
616 iDisconnectDevice=NULL; |
|
617 |
|
618 SendRefreshIfNoError(aErr); |
|
619 // continue processing queue only if the disconnected device is |
|
620 // the device with we requested disconnect to. |
|
621 // this has to be checked so that we do not end on having multiple |
|
622 // queue processors at the same time |
|
623 if(iQueue.Count()>0 && iQueue[0]->iOperation==EOpDisconnect && |
|
624 iQueue[0]->iAddr == aAddr) |
|
625 { |
|
626 delete iQueue[0]; |
|
627 iQueue.Remove(0); |
|
628 HandleQueue(); |
|
629 } |
|
630 else |
|
631 { |
|
632 if( iQueue.Count()==0 ) |
|
633 { |
|
634 TRACE_INFO((_L("op Q is empty"))); |
|
635 } |
|
636 else |
|
637 { |
|
638 TRACE_INFO((_L("unexpected op Q contents, count is %d, op is %d"), iDeviceArray.Count(), iQueue[0]->iOperation)); |
|
639 } |
|
640 } |
|
641 TRACE_FUNC_EXIT |
|
642 } |
|
643 |
|
644 // --------------------------------------------------------------------- |
|
645 // CBTPairedModel::PairingComplete |
|
646 // from MBTEngConnObserver |
|
647 // ---------------------------------------------------------------------- |
|
648 // |
|
649 void CBTPairedModel::PairingComplete(TBTDevAddr& aAddr, TInt aErr) |
|
650 { |
|
651 TRACE_FUNC_ENTRY |
|
652 |
|
653 TRAPD(err, |
|
654 PairingCompleteL(aAddr,aErr); |
|
655 ); |
|
656 |
|
657 if(err!=KErrNone) |
|
658 { |
|
659 TBTDevice tmp; |
|
660 tmp.iAddr=aAddr; |
|
661 tmp.iIndex=GetIndexByAddress(aAddr); |
|
662 tmp.iOperation=EOpPair; |
|
663 HandleLeave(err,&tmp ); |
|
664 |
|
665 delete iPairingDevice; |
|
666 iPairingDevice=NULL; |
|
667 } |
|
668 |
|
669 TRACE_FUNC_EXIT |
|
670 } |
|
671 |
|
672 // --------------------------------------------------------------------- |
|
673 // CBTPairedModel::PairingCompleteL |
|
674 // Leaving version of PairingComplete |
|
675 // ---------------------------------------------------------------------- |
|
676 // |
|
677 void CBTPairedModel::PairingCompleteL(TBTDevAddr& aAddr, TInt aErr) |
|
678 { |
|
679 TRACE_FUNC_ENTRY |
|
680 |
|
681 // The device that was attempted to be paired is |
|
682 // different from the the device that the pairing is finnished. |
|
683 // This cannot happen, since CBTConnMan will report |
|
684 // only pairing started by the listener and the UI |
|
685 // does not allow making two pairings at the same time |
|
686 __ASSERT_DEBUG(aAddr==iPairingDevice->BDAddr(), |
|
687 PANIC(EBTPanicCommandComplettedToDiffrentDeviceThanStarted)); |
|
688 (void) aAddr; |
|
689 |
|
690 // bail out if the operation queue is not what we expect |
|
691 if( iQueue.Count() == 0 |
|
692 || iQueue[0]->iOperation != EOpPair |
|
693 || iQueue[0]->iAddr != aAddr ) |
|
694 { |
|
695 if( iQueue.Count()==0 ) |
|
696 { |
|
697 TRACE_INFO((_L("op Q is empty"))); |
|
698 } |
|
699 else |
|
700 { |
|
701 TRACE_INFO((_L("unexpected op Q contents, count is %d, op is %d"), iDeviceArray.Count(), iQueue[0]->iOperation)); |
|
702 } |
|
703 TRACE_FUNC_EXIT |
|
704 return; |
|
705 } |
|
706 |
|
707 iState=EIdleState; |
|
708 TBTDevice* tmpDevice=NULL; |
|
709 tmpDevice=CreateDeviceL(iPairingDevice, &( iQueue[0]->iNameEntry ) ); |
|
710 tmpDevice->iOperation=EOpPair; |
|
711 |
|
712 // new paired device must be inserted to the array, since |
|
713 // user may be doing trust/ connect operations before |
|
714 // it is refreshed from registry |
|
715 TBool deleleteTmpDevice=ETrue; |
|
716 |
|
717 if( aErr == KErrNone ) |
|
718 { |
|
719 SetStatusFlags(tmpDevice->iStatus,EStatusPaired); |
|
720 TInt index; |
|
721 index=GetIndexByAddress(iPairingDevice->BDAddr()); |
|
722 |
|
723 if(index == KErrNotFound) |
|
724 { |
|
725 iDeviceArray.InsertInOrderL(tmpDevice,*iSortOrder ); |
|
726 |
|
727 RenumberDeviceArray(); |
|
728 |
|
729 // iPairingDevice is now owned by iDeviceArray. |
|
730 // So it must not be deleted by his function |
|
731 deleleteTmpDevice=EFalse; |
|
732 |
|
733 SendRefreshIfNoError(aErr,GetIndexByAddress(iPairingDevice->BDAddr())); |
|
734 } |
|
735 } |
|
736 |
|
737 |
|
738 iObserver->NotifyChangeDeviceComplete(aErr, *tmpDevice); |
|
739 |
|
740 /* |
|
741 * We issue an background refresh in case |
|
742 * registry is updated from btnotif |
|
743 */ |
|
744 iRegistryObserver->StartIfNotRunning(); |
|
745 iRegistryObserver->Refresh(); |
|
746 // delete if the ownership has not changed |
|
747 if(deleleteTmpDevice ) |
|
748 { |
|
749 delete tmpDevice; |
|
750 tmpDevice=NULL; |
|
751 } |
|
752 |
|
753 delete iPairingDevice; |
|
754 iPairingDevice=NULL; |
|
755 delete iQueue[0]; |
|
756 iQueue.Remove(0); |
|
757 |
|
758 HandleQueue(); |
|
759 |
|
760 TRACE_FUNC_EXIT |
|
761 } |
|
762 |
|
763 // --------------------------------------------------------------------- |
|
764 // BTPairedModel::HandleDevManComplete |
|
765 // from MBTEngDevModelBase |
|
766 // ---------------------------------------------------------------------- |
|
767 // |
|
768 void CBTPairedModel::HandleDevManComplete(TInt aErr) |
|
769 { |
|
770 TRACE_FUNC_ENTRY |
|
771 |
|
772 // if this is handled we can remove this |
|
773 if(iDisconnectDevice) |
|
774 { |
|
775 delete iDisconnectDevice; |
|
776 iDisconnectDevice=NULL; |
|
777 } |
|
778 |
|
779 if(iPairingDevice) |
|
780 { |
|
781 // add the device just deleted |
|
782 if(iState==EDeleteDeviceState && (aErr==KErrNone || aErr == KErrNotFound)) |
|
783 { |
|
784 iPairingDevice->DeleteLinkKey(); |
|
785 TBTDeviceSecurity sec=iPairingDevice->GlobalSecurity(); |
|
786 sec.SetBanned(EFalse); |
|
787 sec.SetNoAuthorise(EFalse); |
|
788 iDevMan->AddDevice(*iPairingDevice); |
|
789 iState=EAddDeviceState; |
|
790 TRACE_FUNC_EXIT |
|
791 return; |
|
792 } |
|
793 // if the device is added allready, or if deletion failed |
|
794 // we will go on with pairing the device |
|
795 if(iState==EAddDeviceState||(iState==EDeleteDeviceState&& aErr != KErrNone)) |
|
796 { |
|
797 aErr = iConnMan->PairDevice(iPairingDevice->BDAddr(), iPairingDevice->DeviceClass()); |
|
798 iState=EPairDeviceState; |
|
799 // NOTE: now PairingComplete will be called and not this method. |
|
800 TRACE_FUNC_EXIT |
|
801 return; |
|
802 } |
|
803 } |
|
804 // these are not handled by superclass |
|
805 if(iQueue.Count()>0 && |
|
806 ( iQueue[0]->iOperation==EOpConnect || |
|
807 iQueue[0]->iOperation==EOpDisconnect ) ) |
|
808 { |
|
809 iObserver->NotifyChangeDeviceComplete(aErr, *iQueue[0]); |
|
810 } |
|
811 |
|
812 CBTDevModelBase::HandleDevManComplete(aErr); |
|
813 |
|
814 TRACE_FUNC_EXIT |
|
815 } |
|
816 |
|
817 // --------------------------------------------------------------------- |
|
818 // CBTPairedModel::DoPairDevice |
|
819 // --------------------------------------------------------------------- |
|
820 // |
|
821 void CBTPairedModel::DoPairDeviceL() |
|
822 { |
|
823 TRACE_FUNC_ENTRY |
|
824 |
|
825 // we are starting a new command. Checks that no earlier commands |
|
826 // have been executed, but not finished properly. |
|
827 __ASSERT_DEBUG(iState==EIdleState,PANIC(EBTPanicDevManQueueIsInIllegalState)); |
|
828 // check that there is no other pairing going on. |
|
829 __ASSERT_DEBUG(iPairingDevice!=NULL,PANIC(EBTPanicTwoPairingAttemptsAtTheSameTime)); |
|
830 |
|
831 iRegistryObserver->Cancel(); |
|
832 |
|
833 // devices to be paired are first deleted |
|
834 // then added back. Only after that the paring itself is |
|
835 // started |
|
836 TBTRegistrySearch dele; |
|
837 dele.FindAddress(iPairingDevice->BDAddr()); |
|
838 TInt err = iDevMan->DeleteDevices(dele); |
|
839 |
|
840 iState=EDeleteDeviceState; |
|
841 if (err) |
|
842 { |
|
843 HandleDevManComplete(err); |
|
844 } |
|
845 |
|
846 TRACE_FUNC_EXIT |
|
847 } |
|
848 |
|
849 // --------------------------------------------------------------------- |
|
850 // CBTPairedModel::PairDevice |
|
851 // |
|
852 // Puts the given aPairingDevice to iPairingDevice and |
|
853 // adds and empty device with iOperation=EOpPair as placeholder to iQueue. |
|
854 // the pairing itself will be handled by DoChangeDevice that |
|
855 // cals then |
|
856 // --------------------------------------------------------------------- |
|
857 // |
|
858 TInt CBTPairedModel::PairDeviceL(const CBTDevice* aPairingDevice, |
|
859 TNameEntry* aNameEntry) |
|
860 { |
|
861 TRACE_FUNC_ENTRY |
|
862 |
|
863 // cannot put two pairings to queue. |
|
864 // this is not possible since ui does not allow it. |
|
865 if(iPairingDevice) |
|
866 return KErrInUse; |
|
867 |
|
868 TBTDevice* device=new(ELeave) TBTDevice(); |
|
869 device->iOperation=EOpPair; |
|
870 device->iAddr=aPairingDevice->BDAddr(); |
|
871 if ( aNameEntry ) |
|
872 { |
|
873 device->iNameEntry = *aNameEntry; |
|
874 } |
|
875 CleanupStack::PushL(device); |
|
876 iPairingDevice=aPairingDevice->CopyL(); |
|
877 // put the device to queue directly |
|
878 iQueue.AppendL(device); |
|
879 TInt err = KErrNone; |
|
880 if(iQueue.Count() ==1 ) |
|
881 { |
|
882 err = DoChangeDeviceL(*iQueue[0]); |
|
883 } |
|
884 CleanupStack::Pop(device); |
|
885 TRACE_FUNC_EXIT |
|
886 return err; |
|
887 |
|
888 } |
|
889 |
|
890 // --------------------------------------------------------------------- |
|
891 // CBTPairedModel::HandleDisconnectCompleteL |
|
892 // Disconnection by CBluetoothPhysicalLinks, for those |
|
893 // connections not opened by btui. |
|
894 // --------------------------------------------------------------------- |
|
895 // |
|
896 void CBTPairedModel::HandleDisconnectCompleteL(TInt aErr) |
|
897 { |
|
898 TRACE_FUNC_ENTRY |
|
899 |
|
900 if(iDisconnectDevice) |
|
901 { |
|
902 DisconnectComplete(iDisconnectDevice->iAddr,aErr); |
|
903 } |
|
904 |
|
905 TRACE_FUNC_EXIT |
|
906 } |
|
907 |
|
908 // --------------------------------------------------------------------- |
|
909 // CBTPairedModel::FlagPhysicallyConnectedDevices |
|
910 // |
|
911 // Marks the EStatusPhysicallyConnected attribute to the devices |
|
912 // that have active connection. |
|
913 // --------------------------------------------------------------------- |
|
914 // |
|
915 void CBTPairedModel::FlagPhysicallyConnectedDevices(RDeviceArray &aDeviceArray) |
|
916 { |
|
917 TRACE_FUNC_ENTRY |
|
918 |
|
919 RBTDevAddrArray a; |
|
920 iLinks->Enumerate(a,KMaxCheckedConnections); |
|
921 |
|
922 TInt i=0; |
|
923 |
|
924 for(i=0;i<aDeviceArray.Count();i++) |
|
925 { |
|
926 FlagPhysicallyConnectedDevices( *aDeviceArray[i], a ); |
|
927 } |
|
928 a.Close(); |
|
929 |
|
930 TRACE_FUNC_EXIT |
|
931 } |
|
932 |
|
933 void CBTPairedModel::FlagPhysicallyConnectedDevices(TBTDevice& aDevice, RBTDevAddrArray& aBTDeviceArray) |
|
934 { |
|
935 TRACE_FUNC_ENTRY |
|
936 |
|
937 TInt i2=0; |
|
938 |
|
939 UnsetStatusFlags( aDevice.iStatus, EStatusPhysicallyConnected ); |
|
940 for( i2=0; i2<aBTDeviceArray.Count(); i2++ ) |
|
941 { |
|
942 if(aDevice.iAddr == aBTDeviceArray[i2]) |
|
943 { |
|
944 SetStatusFlags( aDevice.iStatus,EStatusPhysicallyConnected ); |
|
945 break; |
|
946 } |
|
947 } |
|
948 |
|
949 TRACE_FUNC_EXIT |
|
950 } |
|
951 |
|
952 // --------------------------------------------------------------------- |
|
953 // CBTPairedModel::GetDevice |
|
954 // |
|
955 // Adds the EPhysicallyConnected attribute devices that have any active |
|
956 // bluetooth connection. |
|
957 // --------------------------------------------------------------------- |
|
958 // |
|
959 TInt CBTPairedModel::GetDevice(TBTDevice& aDevice) |
|
960 { |
|
961 TRACE_FUNC_ENTRY |
|
962 |
|
963 TInt rvalue=CBTDevModelBase::GetDevice(aDevice); |
|
964 RBTDevAddrArray a; |
|
965 iLinks->Enumerate(a,KMaxCheckedConnections); |
|
966 FlagPhysicallyConnectedDevices(aDevice, a); |
|
967 a.Close(); |
|
968 |
|
969 TRACE_FUNC_EXIT |
|
970 |
|
971 return rvalue; |
|
972 } |
|
973 |
|
974 // --------------------------------------------------------------------- |
|
975 // CBTPairedModel::HandleLeave |
|
976 // from CBTDevModelBase |
|
977 // --------------------------------------------------------------------- |
|
978 // |
|
979 void CBTPairedModel::HandleLeave(TInt aErr,const TBTDevice* aDevice ) |
|
980 { |
|
981 TRACE_FUNC_ENTRY |
|
982 |
|
983 iConnMan->CancelPairDevice(); |
|
984 |
|
985 delete iPairingDevice; |
|
986 iPairingDevice=NULL; |
|
987 |
|
988 delete iDisconnectDevice; |
|
989 iDisconnectDevice=NULL; |
|
990 |
|
991 iRegistryObserver->StartIfNotRunning(); |
|
992 iRegistryObserver->Refresh(); |
|
993 |
|
994 iState=EIdleState; |
|
995 |
|
996 CBTDevModelBase::HandleLeave(aErr,aDevice ); |
|
997 |
|
998 TRACE_FUNC_EXIT |
|
999 } |