1 /* |
1 /* |
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
2 * Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). |
3 * All rights reserved. |
3 * All rights reserved. |
4 * This component and the accompanying materials are made available |
4 * This component and the accompanying materials are made available |
5 * under the terms of "Eclipse Public License v1.0" |
5 * under the terms of "Eclipse Public License v1.0" |
6 * which accompanies this distribution, and is available |
6 * which accompanies this distribution, and is available |
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
31 EAuthenticationResult, |
31 EAuthenticationResult, |
32 ERegistryInitiatePairedDevicesView, |
32 ERegistryInitiatePairedDevicesView, |
33 ERegistryPairedDevicesNewView, |
33 ERegistryPairedDevicesNewView, |
34 ERegistryInitiatePairedDevicesList, |
34 ERegistryInitiatePairedDevicesList, |
35 ERegistryGetPairedDevices, |
35 ERegistryGetPairedDevices, |
|
36 ERegistryGetLocalAddress, |
36 }; |
37 }; |
37 |
38 |
38 /** The message argument which holds the Bluetooth address. */ |
39 /** The message argument which holds the Bluetooth address. */ |
39 const TInt KBTEngAddrSlot = 0; |
40 const TInt KBTEngAddrSlot = 0; |
40 |
41 |
79 { |
80 { |
80 User::LeaveIfError( iPairingResult.Open( *iPairingServ ) ); |
81 User::LeaveIfError( iPairingResult.Open( *iPairingServ ) ); |
81 User::LeaveIfError( iAuthenResult.Open( *iPairingServ ) ); |
82 User::LeaveIfError( iAuthenResult.Open( *iPairingServ ) ); |
82 iSSPResultActive = CBTEngActive::NewL( *this, ESimplePairingResult, CActive::EPriorityStandard ); |
83 iSSPResultActive = CBTEngActive::NewL( *this, ESimplePairingResult, CActive::EPriorityStandard ); |
83 iAuthenResultActive = CBTEngActive::NewL( *this, EAuthenticationResult, CActive::EPriorityStandard ); |
84 iAuthenResultActive = CBTEngActive::NewL( *this, EAuthenticationResult, CActive::EPriorityStandard ); |
84 SubscribeSspPairingResult(); |
85 } |
85 SubscribeAuthenticateResult(); |
86 |
86 } |
87 // RProperty for accessing the local device address |
|
88 User::LeaveIfError( iPropertyLocalAddr.Attach(KPropertyUidBluetoothCategory, KPropertyKeyBluetoothGetLocalDeviceAddress) ); |
87 |
89 |
88 // connect to registry |
90 // connect to registry |
89 User::LeaveIfError( iBTRegistry.Open( BTRegServ() ) ); |
91 User::LeaveIfError( iBTRegistry.Open( BTRegServ() ) ); |
90 iRegistryActive = CBTEngActive::NewL( *this, ERegistryInitiatePairedDevicesView, CActive::EPriorityStandard ); |
92 iRegistryActive = CBTEngActive::NewL( *this, ERegistryInitiatePairedDevicesView, CActive::EPriorityStandard ); |
91 // Start to get the list of all paired devices. |
93 iPairedDevices = new (ELeave) RArray<TBTNamelessDevice>; |
92 CreatePairedDevicesView( ERegistryInitiatePairedDevicesView ); |
94 |
93 iPairedDevices = new (ELeave) RArray<TBTNamelessDevice>; |
95 // Initialise paired devices list |
|
96 iLocalAddrActive = CBTEngActive::NewL( *this, ERegistryGetLocalAddress, CActive::EPriorityStandard ); |
|
97 InitPairedDevicesList(); |
|
98 |
94 TRACE_FUNC_EXIT |
99 TRACE_FUNC_EXIT |
95 } |
100 } |
96 |
101 |
97 // --------------------------------------------------------------------------- |
102 // --------------------------------------------------------------------------- |
98 // NewL |
103 // NewL |
136 } |
141 } |
137 if ( !iMessage.IsNull() ) |
142 if ( !iMessage.IsNull() ) |
138 { |
143 { |
139 iMessage.Complete( KErrCancel ); |
144 iMessage.Complete( KErrCancel ); |
140 } |
145 } |
|
146 iPropertyLocalAddr.Cancel(); |
|
147 iPropertyLocalAddr.Close(); |
|
148 delete iLocalAddrActive; |
|
149 TRACE_FUNC_EXIT |
|
150 } |
|
151 |
|
152 // --------------------------------------------------------------------------- |
|
153 // Initialises the paired devices list. |
|
154 // If the local address is not available from the P&S key |
|
155 // KPropertyKeyBluetoothGetLocalDeviceAddress, then the list may need to be |
|
156 // updated once the H/W is switched on. This is so that any registry update |
|
157 // from a restore operation can be included in the list, without mistaking the |
|
158 // new devices for new pairings. |
|
159 // --------------------------------------------------------------------------- |
|
160 // |
|
161 void CBTEngPairMan::InitPairedDevicesList() |
|
162 { |
|
163 TRACE_FUNC_ENTRY |
|
164 |
|
165 // Check that we have the Bluetooth local address. If we don't then initialise anyway, but subscribe for an update. |
|
166 // This allows us to refresh our paired devices list to include updates made to the remote devices table of the |
|
167 // Bluetooth registry from a restore operation. We need to include these devices without mistaking them for new |
|
168 // pairings. We look solely at the P&S key for the address to avoid the condition whereby the address has been |
|
169 // entered into the reigstry but the Bluetooth Manager server has not begun the restore process yet. The signalling |
|
170 // of the P&S key will cause Bluetooth Manager to update the registry with any restored devices before fulfilling |
|
171 // any further requests. |
|
172 |
|
173 // Subscribe to local address property in case we need an update. |
|
174 iPropertyLocalAddr.Subscribe( iLocalAddrActive->iStatus ); |
|
175 iLocalAddrActive->SetRequestId( ERegistryGetLocalAddress ); |
|
176 iLocalAddrActive->GoActive(); |
|
177 |
|
178 // Attempt to read address from P&S key. |
|
179 TBuf8<KBTDevAddrSize> btAddrDes; |
|
180 TInt err = iPropertyLocalAddr.Get( btAddrDes ); |
|
181 |
|
182 // Is the P&S key defined yet? (if not, stack not up yet) |
|
183 if ( err == KErrNone ) |
|
184 { |
|
185 // P&S key defined, is local address set? (if not, H/W not initialised yet) |
|
186 if ( btAddrDes.Length() == KBTDevAddrSize ) |
|
187 { |
|
188 TBTDevAddr btAddr = btAddrDes; |
|
189 |
|
190 if ( btAddr != TBTDevAddr() ) |
|
191 { |
|
192 // Non-zero local address is available. |
|
193 iPropertyLocalAddr.Cancel(); |
|
194 iLocalAddrActive->CancelRequest(); |
|
195 } |
|
196 } |
|
197 } |
|
198 |
|
199 // Perform initialisation of the paired devices list. |
|
200 DoInitPairedDevicesList(); |
|
201 |
|
202 TRACE_FUNC_EXIT |
|
203 } |
|
204 |
|
205 // --------------------------------------------------------------------------- |
|
206 // Initialises the paired devices list (second stage) |
|
207 // This method performs the actual initialisation, now that the local BT H/W |
|
208 // address had been made available. |
|
209 // --------------------------------------------------------------------------- |
|
210 // |
|
211 void CBTEngPairMan::DoInitPairedDevicesList() |
|
212 { |
|
213 TRACE_FUNC_ENTRY |
|
214 |
|
215 if ( !iRegistryActive->IsActive() ) |
|
216 { |
|
217 // Start to get the list of all paired devices. |
|
218 CreatePairedDevicesView( ERegistryInitiatePairedDevicesView ); |
|
219 } |
|
220 else |
|
221 { |
|
222 iNotHandledInitEventCounter++; |
|
223 } |
|
224 |
141 TRACE_FUNC_EXIT |
225 TRACE_FUNC_EXIT |
142 } |
226 } |
143 |
227 |
144 // --------------------------------------------------------------------------- |
228 // --------------------------------------------------------------------------- |
145 // Handles pairing related commands from BTEng clients. |
229 // Handles pairing related commands from BTEng clients. |
292 // only do unpairing if the we have a link key with it. |
376 // only do unpairing if the we have a link key with it. |
293 TInt index = iPairedDevices->Find( dev, addrComp ); |
377 TInt index = iPairedDevices->Find( dev, addrComp ); |
294 if ( index > KErrNotFound ) |
378 if ( index > KErrNotFound ) |
295 { |
379 { |
296 dev = (*iPairedDevices)[index]; |
380 dev = (*iPairedDevices)[index]; |
297 TBTDeviceSecurity security = dev.GlobalSecurity(); |
381 |
298 // Clear trust setting so that correct icon will be shown in ui applications. |
382 TRequestStatus status( KRequestPending ); |
299 security.SetNoAuthenticate(EFalse ); |
383 // Unpair the device in registry (synchronously) |
300 security.SetNoAuthorise(EFalse ); |
384 iBTRegistry.UnpairDevice( dev.Address(), status ); |
301 dev.SetGlobalSecurity(security); |
385 User::WaitForRequest( status ); |
302 dev.DeleteLinkKey(); |
386 TRACE_INFO( ( _L( "Delete link key, res %d"), status.Int() ) ) |
303 if ( dev.IsValidUiCookie() && |
387 |
304 ( dev.UiCookie() & EBTUiCookieJustWorksPaired ) ) |
388 if ( status == KErrNone ) |
305 { |
389 { |
306 // Remove the UI cookie bit for Just Works pairing. |
390 TBTDeviceSecurity security = dev.GlobalSecurity(); |
307 TInt32 cookie = dev.UiCookie() & ~EBTUiCookieJustWorksPaired; |
391 // Clear trust setting so that correct icon will be shown in ui applications. |
308 dev.SetUiCookie( cookie ); |
392 security.SetNoAuthenticate(EFalse ); |
309 TRACE_INFO( ( _L( "UI cookie %x cleared"), EBTUiCookieJustWorksPaired ) ); |
393 security.SetNoAuthorise(EFalse ); |
310 } |
394 dev.SetGlobalSecurity(security); |
311 // modify the device in registry synchronously |
395 dev.DeleteLinkKey(); |
312 // status.Int() could be -1 if the device is not in registry |
396 if ( dev.IsValidUiCookie() && |
313 // which is totally fine for us. |
397 ( dev.UiCookie() & EBTUiCookieJustWorksPaired ) ) |
314 (void) UpdateRegDevice( dev ); |
398 { |
|
399 // Remove the UI cookie bit for Just Works pairing. |
|
400 TInt32 cookie = dev.UiCookie() & ~EBTUiCookieJustWorksPaired; |
|
401 dev.SetUiCookie( cookie ); |
|
402 TRACE_INFO( ( _L( "UI cookie %x cleared"), EBTUiCookieJustWorksPaired ) ); |
|
403 } |
|
404 // modify the device in registry synchronously |
|
405 // status.Int() could be -1 if the device is not in registry |
|
406 // which is totally fine for us. |
|
407 (void) UpdateRegDevice( dev ); |
|
408 } |
315 } |
409 } |
316 TRACE_FUNC_EXIT |
410 TRACE_FUNC_EXIT |
317 } |
411 } |
318 |
412 |
319 TInt CBTEngPairMan::AddUiCookieJustWorksPaired( const TBTNamelessDevice& aDev ) |
413 TInt CBTEngPairMan::AddUiCookieJustWorksPaired( const TBTNamelessDevice& aDev ) |
394 { |
488 { |
395 HandleCreatePairedDevicesViewCompletedL( aStatus, aId ); |
489 HandleCreatePairedDevicesViewCompletedL( aStatus, aId ); |
396 break; |
490 break; |
397 } |
491 } |
398 case ERegistryInitiatePairedDevicesList: |
492 case ERegistryInitiatePairedDevicesList: |
|
493 { |
|
494 if (iSSPResultActive && iAuthenResultActive) |
|
495 { |
|
496 SubscribeSspPairingResult(); |
|
497 SubscribeAuthenticateResult(); |
|
498 } |
|
499 HandleGetPairedDevicesCompletedL( aStatus, aId ); |
|
500 break; |
|
501 } |
399 case ERegistryGetPairedDevices: |
502 case ERegistryGetPairedDevices: |
400 { |
503 { |
401 HandleGetPairedDevicesCompletedL( aStatus, aId ); |
504 HandleGetPairedDevicesCompletedL( aStatus, aId ); |
|
505 break; |
|
506 } |
|
507 case ERegistryGetLocalAddress: |
|
508 { |
|
509 // Refresh paired devices list to include any restored devices. |
|
510 DoInitPairedDevicesList(); |
402 break; |
511 break; |
403 } |
512 } |
404 default: |
513 default: |
405 // Should not be possible, but no need for handling. |
514 // Should not be possible, but no need for handling. |
406 TRACE_INFO( (_L("[BTEng]: CBTEngPairMan::RequestCompletedL unhandled event!!") ) ) |
515 TRACE_INFO( (_L("[BTEng]: CBTEngPairMan::RequestCompletedL unhandled event!!") ) ) |
464 // Delegates the request to current pair handler |
574 // Delegates the request to current pair handler |
465 // --------------------------------------------------------------------------- |
575 // --------------------------------------------------------------------------- |
466 // |
576 // |
467 void CBTEngPairMan::PairDeviceL( const TBTDevAddr& aAddr, TUint32 aCod ) |
577 void CBTEngPairMan::PairDeviceL( const TBTDevAddr& aAddr, TUint32 aCod ) |
468 { |
578 { |
|
579 iPairingOperationAttempted = ETrue; |
469 if ( !iPairer) |
580 if ( !iPairer) |
470 { |
581 { |
471 // no existing pair handling, create one: |
582 // no existing pair handling, create one: |
472 iPairer = CBTEngOtgPair::NewL( *this, aAddr ); |
583 iPairer = CBTEngOtgPair::NewL( *this, aAddr ); |
473 } |
584 } |
497 } |
608 } |
498 TRACE_FUNC_EXIT |
609 TRACE_FUNC_EXIT |
499 } |
610 } |
500 |
611 |
501 // --------------------------------------------------------------------------- |
612 // --------------------------------------------------------------------------- |
502 // Subscribes to simple pairing result from Pairing Server |
613 // Subscribes to simple pairing result from Pairing Server (if not already |
|
614 // subscribed). |
503 // --------------------------------------------------------------------------- |
615 // --------------------------------------------------------------------------- |
504 // |
616 // |
505 void CBTEngPairMan::SubscribeSspPairingResult() |
617 void CBTEngPairMan::SubscribeSspPairingResult() |
506 { |
618 { |
507 TRACE_FUNC_ENTRY |
619 TRACE_FUNC_ENTRY |
508 iPairingResult.SimplePairingResult( iSimplePairingRemote, iSSPResultActive->RequestStatus() ); |
620 if ( !iSSPResultActive->IsActive() ) |
509 iSSPResultActive->GoActive(); |
621 { |
510 TRACE_FUNC_EXIT |
622 iPairingResult.SimplePairingResult( iSimplePairingRemote, iSSPResultActive->RequestStatus() ); |
511 } |
623 iSSPResultActive->GoActive(); |
512 |
624 } |
513 // --------------------------------------------------------------------------- |
625 TRACE_FUNC_EXIT |
514 // Subscribes to authentication result from Pairing Server |
626 } |
|
627 |
|
628 // --------------------------------------------------------------------------- |
|
629 // Subscribes to authentication result from Pairing Server (if not already |
|
630 // subscribed). |
515 // --------------------------------------------------------------------------- |
631 // --------------------------------------------------------------------------- |
516 // |
632 // |
517 void CBTEngPairMan::SubscribeAuthenticateResult() |
633 void CBTEngPairMan::SubscribeAuthenticateResult() |
518 { |
634 { |
519 TRACE_FUNC_ENTRY |
635 TRACE_FUNC_ENTRY |
520 // Subscribe authentication result (which requires pairing for unpaired devices) |
636 if ( !iAuthenResultActive->IsActive() ) |
521 iAuthenResult.AuthenticationResult( iAuthenticateRemote, iAuthenResultActive->RequestStatus() ); |
637 { |
522 iAuthenResultActive->GoActive(); |
638 // Subscribe authentication result (which requires pairing for unpaired devices) |
|
639 iAuthenResult.AuthenticationResult( iAuthenticateRemote, iAuthenResultActive->RequestStatus() ); |
|
640 iAuthenResultActive->GoActive(); |
|
641 } |
523 TRACE_FUNC_EXIT |
642 TRACE_FUNC_EXIT |
524 } |
643 } |
525 |
644 |
526 // --------------------------------------------------------------------------- |
645 // --------------------------------------------------------------------------- |
527 // Handle a pairing result from the pairing server. |
646 // Handle a pairing result from the pairing server. |
568 // --------------------------------------------------------------------------- |
687 // --------------------------------------------------------------------------- |
569 // |
688 // |
570 void CBTEngPairMan::CreatePairedDevicesView( TInt aReqId ) |
689 void CBTEngPairMan::CreatePairedDevicesView( TInt aReqId ) |
571 { |
690 { |
572 TRACE_FUNC_ENTRY |
691 TRACE_FUNC_ENTRY |
573 iNotHandledRegEventCounter = 0; |
692 if ( aReqId == ERegistryInitiatePairedDevicesView ) |
|
693 { |
|
694 iNotHandledInitEventCounter = 0; |
|
695 } |
|
696 else |
|
697 { |
|
698 iNotHandledRegEventCounter = 0; |
|
699 } |
574 TBTRegistrySearch searchPattern; |
700 TBTRegistrySearch searchPattern; |
575 searchPattern.FindBonded(); |
701 searchPattern.FindBonded(); |
576 iRegistryActive->SetRequestId( aReqId ); |
702 iRegistryActive->SetRequestId( aReqId ); |
577 iBTRegistry.CreateView( searchPattern, iRegistryActive->iStatus ); |
703 iBTRegistry.CreateView( searchPattern, iRegistryActive->iStatus ); |
578 iRegistryActive->GoActive(); |
704 iRegistryActive->GoActive(); |
606 void CBTEngPairMan::HandleCreatePairedDevicesViewCompletedL( TInt aStatus, TInt aReqId ) |
732 void CBTEngPairMan::HandleCreatePairedDevicesViewCompletedL( TInt aStatus, TInt aReqId ) |
607 { |
733 { |
608 TRACE_FUNC_ENTRY |
734 TRACE_FUNC_ENTRY |
609 |
735 |
610 if ( aReqId == ERegistryInitiatePairedDevicesView ) |
736 if ( aReqId == ERegistryInitiatePairedDevicesView ) |
611 {// Initialization phase, list paired devices if there are. |
737 {// Initialization phase, list paired devices if there are any. |
612 if ( aStatus > KErrNone ) |
738 if ( iNotHandledInitEventCounter ) |
|
739 { |
|
740 // Reinitialisaton detected, create paired device view again: |
|
741 (void) iBTRegistry.CloseView(); |
|
742 CreatePairedDevicesView( ERegistryInitiatePairedDevicesView ); |
|
743 } |
|
744 else if ( aStatus > KErrNone ) |
613 { |
745 { |
614 GetPairedDevices( ERegistryInitiatePairedDevicesList ); |
746 GetPairedDevices( ERegistryInitiatePairedDevicesList ); |
615 } |
747 } |
616 else |
748 else |
617 {//no paired device, close the view. |
749 {//no paired device, close the view. |
618 (void) iBTRegistry.CloseView(); |
750 (void) iBTRegistry.CloseView(); |
619 } |
751 } |
620 } |
752 } |
621 else |
753 else |
622 { |
754 { |
623 if (iNotHandledRegEventCounter) |
755 if ( iNotHandledInitEventCounter ) |
|
756 { |
|
757 // We need to reinitialise but we may be pairing. |
|
758 // This situation is not expected to arise, as reinitialisation means |
|
759 // that the H/W was only just switched on. |
|
760 // If we have ever started to take part in a pairing, then prioritise that |
|
761 // pairing. |
|
762 (void) iBTRegistry.CloseView(); |
|
763 if ( iPairingOperationAttempted ) |
|
764 { |
|
765 iNotHandledInitEventCounter = 0; |
|
766 CreatePairedDevicesView( ERegistryPairedDevicesNewView ); |
|
767 } |
|
768 else |
|
769 { |
|
770 CreatePairedDevicesView( ERegistryInitiatePairedDevicesView ); |
|
771 } |
|
772 } |
|
773 else if (iNotHandledRegEventCounter) |
624 { // more registry change detected, create paired device view again: |
774 { // more registry change detected, create paired device view again: |
625 (void) iBTRegistry.CloseView(); |
775 (void) iBTRegistry.CloseView(); |
626 CreatePairedDevicesView( ERegistryPairedDevicesNewView ); |
776 CreatePairedDevicesView( ERegistryPairedDevicesNewView ); |
627 } |
777 } |
628 else if ( aStatus > KErrNone ) |
778 else if ( aStatus > KErrNone ) |
648 { |
798 { |
649 TRACE_FUNC_ENTRY |
799 TRACE_FUNC_ENTRY |
650 (void) iBTRegistry.CloseView(); |
800 (void) iBTRegistry.CloseView(); |
651 if ( aReqId == ERegistryInitiatePairedDevicesList ) |
801 if ( aReqId == ERegistryInitiatePairedDevicesList ) |
652 { |
802 { |
653 // We completed the initialization of paired device list, |
803 if ( iNotHandledInitEventCounter ) |
654 // move all paired devices to the array: |
804 { |
655 UpdatePairedDeviceListL(); |
805 // Reinitialisation required, create paired device view again: |
656 } |
806 CreatePairedDevicesView( ERegistryInitiatePairedDevicesView ); |
657 |
807 } |
658 if (iNotHandledRegEventCounter) |
808 else |
659 { // more registry change detected, create paired device view again: |
809 { |
660 CreatePairedDevicesView( ERegistryPairedDevicesNewView ); |
810 // We completed the initialisation of paired device list, |
661 } |
811 // move all paired devices to the array: |
662 else if ( aReqId == ERegistryGetPairedDevices) |
812 UpdatePairedDeviceListL(); |
663 { |
813 } |
664 // no more registry change detected, find new pairings: |
814 } |
665 CheckPairEventL(); |
815 else |
|
816 { |
|
817 if (iNotHandledInitEventCounter) |
|
818 { |
|
819 // We need to reinitialise but we may be pairing. |
|
820 // This situation is not expected to arise, as reinitialisation means |
|
821 // that the H/W was only just switched on. |
|
822 // If we have ever started to take part in a pairing, then prioritise that |
|
823 // pairing. |
|
824 if ( iPairingOperationAttempted ) |
|
825 { |
|
826 iNotHandledInitEventCounter = 0; |
|
827 CreatePairedDevicesView( ERegistryPairedDevicesNewView ); |
|
828 } |
|
829 else |
|
830 { |
|
831 CreatePairedDevicesView( ERegistryInitiatePairedDevicesView ); |
|
832 } |
|
833 } |
|
834 else if (iNotHandledRegEventCounter) |
|
835 { // more registry change detected, create paired device view again: |
|
836 CreatePairedDevicesView( ERegistryPairedDevicesNewView ); |
|
837 } |
|
838 else if ( aReqId == ERegistryGetPairedDevices) |
|
839 { |
|
840 // no more registry change detected, find new pairings: |
|
841 CheckPairEventL(); |
|
842 } |
666 } |
843 } |
667 |
844 |
668 TRACE_FUNC_EXIT |
845 TRACE_FUNC_EXIT |
669 } |
846 } |
670 |
847 |
719 ( index > KErrNotFound && |
896 ( index > KErrNotFound && |
720 dev.LinkKeyType() != (*pairedDevicesOld)[index].LinkKeyType() ) ); |
897 dev.LinkKeyType() != (*pairedDevicesOld)[index].LinkKeyType() ) ); |
721 TRACE_BDADDR( dev.Address() ); |
898 TRACE_BDADDR( dev.Address() ); |
722 if ( newPaired && !iPairer) |
899 if ( newPaired && !iPairer) |
723 { |
900 { |
|
901 iPairingOperationAttempted = ETrue; |
724 iPairer = CBTEngIncPair::NewL( *this, dev.Address() ); |
902 iPairer = CBTEngIncPair::NewL( *this, dev.Address() ); |
725 } |
903 } |
726 if ( iPairer ) |
904 if ( newPaired && iPairer ) |
727 { |
905 { |
728 // Ask pair handler to decide what to do: |
906 // Ask pair handler to decide what to do: |
729 iPairer->HandleRegistryNewPairedEvent( dev ); |
907 iPairer->HandleRegistryNewPairedEvent( dev ); |
730 } |
908 } |
731 } |
909 } |