bluetoothcommsprofiles/btpan/bnep/CBnepBridge.cpp
changeset 0 29b1cd4cb562
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2004-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 //
       
    15 
       
    16 /**
       
    17  @file
       
    18  @internalComponent
       
    19 */
       
    20 
       
    21 #include <e32std.h>
       
    22 #include <bluetooth/logger.h>
       
    23 #include <bttypes.h>
       
    24 #include <comms-infras/eintsock.h>
       
    25 #include <elements/nm_interfaces.h>
       
    26 #include "CBnepBridge.h"
       
    27 #include "CBnepChannelController.h"
       
    28 #include "RBnepFrame.h"
       
    29 #include "bneputils.h"
       
    30 #include "CBnepLocalDevice.h"
       
    31 #include "CBnepLink.h"
       
    32 #include <networking/pktdrv.h>
       
    33 #include "pancommon.h"
       
    34 
       
    35 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
    36 #include <elements/nm_node.h>
       
    37 #include <comms-infras/ss_common.h>
       
    38 #include "panmessages.h"
       
    39 #include <bt_sock.h>
       
    40 #include <bttypes.h>
       
    41 
       
    42 using namespace ESock;
       
    43 using namespace Messages;
       
    44 
       
    45 #ifdef ESOCK_EXTLOG_ACTIVE
       
    46 _LIT8(KBnepSubTag, "bnep");
       
    47 #endif
       
    48 
       
    49 #endif
       
    50 // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
    51 
       
    52 #ifdef __FLOG_ACTIVE
       
    53 _LIT8(KLogComponent, LOG_COMPONENT_PAN_BNEP);
       
    54 #endif
       
    55 
       
    56 #ifdef _DEBUG
       
    57 PANICCATEGORY("panbnep");
       
    58 #endif
       
    59 
       
    60 // Class CBnepBridge 
       
    61 /**
       
    62    Create the bridge and attach the local device to it.
       
    63 */
       
    64 CBnepBridge::CBnepBridge (MPanDevice& aLocalDevice) : iDataTransferred(KMaxPanConnections)
       
    65     {
       
    66 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
    67     NM_LOG_NODE_CREATE(KBnepSubTag, CBnepBridge);
       
    68 #endif
       
    69 
       
    70     CONNECT_LOGGER
       
    71     LOG_FUNC
       
    72     iLinks[KBnepLocalDeviceArrayId] = &aLocalDevice; 
       
    73     iLinkCount = 1;
       
    74     LOG2(_L8("CBnepBridge::iLinks[%d] = 0x%08x"),KBnepLocalDeviceArrayId,iLinks[KBnepLocalDeviceArrayId]);
       
    75     }
       
    76 
       
    77 /**
       
    78    Destroy the bridge.  Does not delete the devices as they are not owned by
       
    79    the bridge. The links will be deleted when the CBnepChannelControllers are deleted.
       
    80 */
       
    81 CBnepBridge::~CBnepBridge()
       
    82     {
       
    83     LOG_STATIC_FUNC
       
    84     /**
       
    85        Destroy the bridge.  Does not delete the devices as they are not owned by
       
    86        the bridge. The links will be deleted when the CBnepChannelControllers are deleted.
       
    87        @internalComponent
       
    88     */
       
    89 
       
    90     delete iDataCounterTimer;
       
    91 
       
    92     if (iBnepPacketNotifier)
       
    93     	{
       
    94     	iBnepPacketNotifier->MbpnbRelease();
       
    95     	iBnepPacketNotifier = NULL;
       
    96     	}
       
    97    
       
    98 
       
    99     iLib.Close();
       
   100     iDataTransferred.Close();
       
   101 
       
   102     LOG1(_L8("CBnepBridge holds %d links on destruction - Invalidating links..."),iLinkCount);
       
   103     for (TUint index = 0; index < KMaxPanConnections; ++index)
       
   104         {
       
   105         if((index != KBnepLocalDeviceArrayId) && (iLinks[index]))
       
   106             {
       
   107 			// Invalidate the link as it is no longer bound to a bridge.
       
   108             static_cast<CBnepLink*>(iLinks[index])->Invalidate();
       
   109             }
       
   110         }
       
   111         
       
   112 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
   113     // Deregister custom messages with the comms transport
       
   114     TPanMessage::DeRegister();
       
   115 
       
   116     NM_LOG_NODE_DESTROY(KBnepSubTag, CBnepBridge);
       
   117 
       
   118 	delete iPanLinkControl;
       
   119 #endif
       
   120 
       
   121 	CLOSE_LOGGER
       
   122     }
       
   123 
       
   124 /**
       
   125    Add a new device to the bridge
       
   126    @return KErrOverflow The maximum number of supported devices are already
       
   127    in the network.
       
   128 */
       
   129 TInt CBnepBridge::AttachDevice (MPanDevice& aDevice)
       
   130     {
       
   131     LOG_FUNC
       
   132     TUint spareSlot;
       
   133     TInt err = GetVacantSlot(spareSlot);
       
   134     if(KErrNone == err)
       
   135         {
       
   136         iLinks[spareSlot] = &aDevice;
       
   137         iLinkCount++;
       
   138         LOG2(_L8("CBnepBridge attaching iLinks[%d] = 0x%08x"),spareSlot,iLinks[spareSlot]);
       
   139         LOG1(_L8("CBnepBridge holds %d links"),iLinkCount);
       
   140         if (iBnepPacketNotifier) 
       
   141         	{
       
   142         	TBnepBytesTransferred counter;
       
   143         	counter.iBytesReceived=0;
       
   144         	counter.iBytesSent=0;
       
   145         	counter.iBTDevAddr=aDevice.iAddr;
       
   146         	
       
   147 	      	__ASSERT_ALWAYS(iDataTransferred.Append(counter)==KErrNone,BnepUtils::Panic(Bnep::EAppendFailed)); // Shouldn't fail as the granularity of the array is the maximum number of devices available.
       
   148 	      	
       
   149  	      	TInt pos = iDataTransferred.Find(counter);
       
   150 			__ASSERT_ALWAYS(pos != KErrNotFound, BnepUtils::Panic(Bnep::EAppendFailed));
       
   151 			TBnepBytesTransferred* countPtr = &iDataTransferred[pos];
       
   152  			aDevice.SetOwnerCountPtr(countPtr);
       
   153 	  
       
   154 	      	iBnepPacketNotifier->MbpnDeviceAdded(aDevice.iAddr);
       
   155 	      	__ASSERT_ALWAYS(iDataCounterTimer,BnepUtils::Panic(Bnep::ENullPointer));
       
   156     	    if (!iDataCounterTimer->IsActive())
       
   157     			{
       
   158     				iIdleCount=0;
       
   159     				iDataCounterTimer->Start(KBnepPacketNotifyInterval,KBnepPacketNotifyInterval,TCallBack(DataCounterCallBack,this)); // Start the timer if it's not already started
       
   160     			}
       
   161         	}
       
   162 
       
   163         }
       
   164     return err; 
       
   165     }
       
   166 
       
   167 /**
       
   168    Get the default (local) address for this bridge (i.e. address of it's local device).
       
   169 */
       
   170 const TBTDevAddr& CBnepBridge::DefaultAddress () const
       
   171     {
       
   172     LOG_FUNC
       
   173     __ASSERT_ALWAYS(iLinks[KBnepLocalDeviceArrayId],BnepUtils::Panic(Bnep::ENullPointer));
       
   174     LOG_BT(_L8("CBnepBridge::DefaultAddress: %S"),iLinks[KBnepLocalDeviceArrayId]->iAddr);
       
   175     return iLinks[KBnepLocalDeviceArrayId]->iAddr; 
       
   176     }
       
   177 
       
   178 /**
       
   179    Notify the bridge of the imminent destruction of a link.. 
       
   180    This is normally called by a CBnepLink destructor, to notify the bridge that 
       
   181    it is going down. However, it is possible for a CBnepLink instance to exist 
       
   182    for a time without being attached to the bridge. This instance is silently managed.
       
   183 */
       
   184 void CBnepBridge::LinkGoingDown (MPanDevice& aDevice)
       
   185     {
       
   186     LOG_FUNC
       
   187     // We may safely ignore the return value here.
       
   188     RemoveDevice(aDevice);
       
   189     }
       
   190 
       
   191 void CBnepBridge::RemoteDeviceReady ()
       
   192 	{
       
   193     LOG_FUNC
       
   194 	// Inform the local device that a remote device is ready
       
   195 	static_cast<CBnepLocalDevice*> (iLinks[KBnepLocalDeviceArrayId])->RemoteDeviceReady();
       
   196 	}
       
   197 
       
   198 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
   199 /**
       
   200    Create a new bnep channel as a result of an incoming request
       
   201    @param aMessage The message that requested the new channel controller
       
   202 */
       
   203 void CBnepBridge::AttemptNewBnepConnection(const Messages::TNodeId& aSender, const Messages::TSignatureBase& aMessage, TUint16 aActivityId)
       
   204     {
       
   205     LOG_FUNC
       
   206     CBnepChannelController* bnepChannelControl = NULL;
       
   207 
       
   208 	// If this assert fails check your commdb. It probably means that a non-399 commdb
       
   209 	// has been imported and is using the basic Ethernet MCPR rather than the Pan
       
   210 	// Ethernet MCPR
       
   211 	ASSERT_DEBUG(iPktDrvOwner);
       
   212 
       
   213     // The RInternalSocket pointer in the message is owned by PAN and must
       
   214     // not be deleted or used. The internal socket implementation must be
       
   215     // transfered to a local RInternalSocket (see CBnepLink)
       
   216     const TPanMessage::TCreateChannelController& msg = message_cast<const TPanMessage::TCreateChannelController>(aMessage);
       
   217     
       
   218     // msg.iSender in this case should be an instance of the CPanRemoteDeviceStateMachine
       
   219     TRAPD(err, bnepChannelControl = CBnepChannelController::NewL(*this, *msg.iSocket, aSender, *iPktDrvOwner));
       
   220     if (err != KErrNone)
       
   221         {
       
   222         // Report failure to create
       
   223         TPanMessage::TChannelControllerCreated failMsg(err);
       
   224         RClientInterface::OpenPostMessageClose(TNodeCtxId(aActivityId,Id()),aSender,failMsg);
       
   225         return;
       
   226         }
       
   227 
       
   228 	// Same timing as pre-399, give the notifier something to call into
       
   229     if (iBnepPacketNotifier) 
       
   230     	{
       
   231     	iBnepPacketNotifier->MbpnSetLinkControl(*iPanLinkControl);
       
   232     	}
       
   233 
       
   234     // Send the ack on behalf of the new channel controller
       
   235     TPanMessage::TChannelControllerCreated successMsg(KErrNone);
       
   236     RClientInterface::OpenPostMessageClose(TNodeCtxId(aActivityId,bnepChannelControl->Id()),aSender,successMsg);
       
   237     }
       
   238 
       
   239 #else
       
   240 // !SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
   241 
       
   242 /**
       
   243    Create a new bnep channel as a result of an incoming request
       
   244    @param aConnectedSocket A connected L2CAP socket, ready for BNEP signalling
       
   245    @param aNotify Object to inform of events
       
   246 */
       
   247 MBnepChannelControl& CBnepBridge::NewBnepConnectionL(RInternalSocket& aConnectedSocket, MPanConnectionNotify& aNotify)
       
   248     {
       
   249     LOG_FUNC
       
   250     MBnepChannelControl& bnepChannelControl = *CBnepChannelController::NewL(*this, aConnectedSocket, aNotify);
       
   251     if (iBnepPacketNotifier) 
       
   252     	{
       
   253     	iBnepPacketNotifier->MbpnSetLinkControl(aNotify.BnepConnectionController());
       
   254     	}
       
   255     return bnepChannelControl;
       
   256     }
       
   257 #endif
       
   258 // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
   259 
       
   260 CBnepBridge* CBnepBridge::NewL (MPanDevice& aLocalDevice)
       
   261     {
       
   262     LOG_STATIC_FUNC
       
   263     CBnepBridge* self = new(ELeave) CBnepBridge(aLocalDevice);
       
   264     CleanupStack::PushL(self);
       
   265     self->ConstructL();
       
   266     CleanupStack::Pop(self);
       
   267     return self; 
       
   268     }
       
   269 
       
   270 void CBnepBridge::ConstructL() 
       
   271 	{
       
   272     LOG_FUNC
       
   273 	        
       
   274     _LIT(KBnepPacketNotifier,"bnepPacketNotifier.dll");
       
   275     
       
   276     if (iLib.Load(KBnepPacketNotifier)==KErrNone) 
       
   277     	{
       
   278     	TLibraryFunction func=iLib.Lookup(1);
       
   279     	MBnepPacketNotifierBase* notifier;
       
   280     	notifier = (MBnepPacketNotifierBase*) (*func)();
       
   281     	iBnepPacketNotifier = (MBnepPacketNotifier*) notifier->MbpnbGetInterface(KUidBnepPacketNotifierV1);
       
   282     	__ASSERT_DEBUG(iBnepPacketNotifier, BnepUtils::Panic(Bnep::ENullPointer));
       
   283     	
       
   284     	if (iBnepPacketNotifier) 
       
   285     		{
       
   286     		iDataCounterTimer=CPeriodic::NewL(CActive::EPriorityStandard);
       
   287     		}
       
   288  		}
       
   289 
       
   290 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
   291     // Register with the comms transport so we can receive custom messages
       
   292     TPanMessage::RegisterL();
       
   293 	// Create our own MPanLinkControl implementation
       
   294 	iPanLinkControl = CPanLinkControl::NewL();
       
   295 #endif    
       
   296 	}
       
   297 
       
   298 TInt CBnepBridge::DataCounterCallBack(TAny* aThis) 
       
   299 	{
       
   300     LOG_STATIC_FUNC
       
   301 	CBnepBridge* self = static_cast<CBnepBridge*>(aThis);
       
   302 	self->DataCounterNotify();
       
   303 	return KErrNone;
       
   304 	}
       
   305 
       
   306 void CBnepBridge::DataCounterNotify()
       
   307 	{
       
   308     LOG_FUNC
       
   309 	TBool dataTransferred=EFalse;
       
   310 	iBnepPacketNotifier->MbpnBnepDataTransferred(iDataTransferred.Array()); // Notify the number of bytes transferred
       
   311 	for (TUint dev=0;dev<iDataTransferred.Count();++dev)
       
   312 		{
       
   313 		if (iDataTransferred[dev].iBytesSent!=0 || iDataTransferred[dev].iBytesReceived!=0)
       
   314 			{
       
   315 			iDataTransferred[dev].iBytesSent=0;
       
   316 			iDataTransferred[dev].iBytesReceived=0;
       
   317 			dataTransferred=ETrue;
       
   318 			}
       
   319 		} // Work out whether any bytes have been transferred
       
   320 	if (!dataTransferred)  // If not
       
   321 		{
       
   322 		iIdleCount++; // Increase the idle count by 1
       
   323 		if (iIdleCount >= KBnepPacketNotifySleepTicks) // If the idle count has been hit
       
   324 			{
       
   325 			__ASSERT_ALWAYS(iDataCounterTimer,BnepUtils::Panic(Bnep::ENullPointer));
       
   326 			iDataCounterTimer->Cancel(); // Cancel the timer
       
   327 			}
       
   328 		}
       
   329 	else  // If data has been transferred
       
   330 		{
       
   331 		iIdleCount=0; // Reset the idle counter
       
   332 		}
       
   333 	}
       
   334 
       
   335 /**
       
   336    Pass a BNEP frame onto the required device(s).
       
   337    Possible options are: local device, multicast address, single remote device.
       
   338    @return KReadyForMoreData in all cases.
       
   339 */
       
   340 TInt CBnepBridge::Process (RBnepFrame& aFrame, const TBTDevAddr& aSourceIfAddr)
       
   341     {  
       
   342     LOG_FUNC
       
   343     TBool foundDevice = EFalse;
       
   344     LOG(_L8("CBnepBridge: Delivering packet:"));
       
   345     LOG_BT(_L8("CBnepBridge: Source address: %S"), aFrame.SrcAddr());
       
   346     LOG_BT(_L8("CBnepBridge: Destination address: %S"), aFrame.DestAddr());
       
   347     TUint link;
       
   348     switch (aFrame.DestinationType())
       
   349         {
       
   350         case RBnepFrame::ELocal:
       
   351             LOG(_L8("CBnepBridge: Frame type: RBnepFrame::ELocal"));	
       
   352             iLinks[KBnepLocalDeviceArrayId]->Process(aFrame);
       
   353             break;
       
   354 
       
   355         case RBnepFrame::EMulticast:
       
   356             LOG(_L8("CBnepBridge: Frame type: RBnepFrame::EMulticast"));
       
   357             LOG_BT(_L8("Source address %S"),aSourceIfAddr);
       
   358             for (link = 0; link < KMaxPanConnections; link++)
       
   359                 {
       
   360                 LOG1(_L8("iLinks[%d]"),link);
       
   361                 if ((iLinks[link] != NULL) &&
       
   362                     (!(aSourceIfAddr == (iLinks[link]->iAddr))) &&
       
   363                     (!(aFrame.SrcAddr() == (iLinks[link]->iAddr))) )
       
   364                     {
       
   365                     LOG_BT(_L8("Multicasting to %S"), iLinks[link]->Addr());
       
   366                     iLinks[link]->Process(aFrame);
       
   367                     }
       
   368                 }
       
   369             break;
       
   370 
       
   371         case RBnepFrame::ENormal:
       
   372             LOG(_L8("CBnepBridge: Frame type: RBnepFrame::ENormal"));
       
   373             for (link = 0; link < KMaxPanConnections; link++)
       
   374                 {
       
   375                 if (iLinks[link])
       
   376                     {
       
   377                     MPanDevice* linkDev = iLinks[link];
       
   378                     if (linkDev->ForThisDevice(aFrame.DestAddr()))
       
   379                         {
       
   380                         LOG_BT(_L8("Found match, delivering to %S"), linkDev->Addr());
       
   381                         linkDev->Process(aFrame);
       
   382                         foundDevice = ETrue;
       
   383                         break;
       
   384                         }
       
   385                     }
       
   386                 }
       
   387             // unicast frame to a MAC address we haven't found.
       
   388             // We must be in U role connected to a GN/NAP.
       
   389             // In which case this bridge's link count must be EXACTLY 2 
       
   390             // - this device and the GN. 
       
   391             // Otherwise it is a GN and therefore has no
       
   392             //  sensible destination for this frame.
       
   393             if(!foundDevice && (2 == iLinkCount) )
       
   394                 {
       
   395                 // Never assume thak iLinks[0] is always going to be the local device.
       
   396                 // iLinks[KLocalDeviceArrayId] is the local device.
       
   397                 for (link = 0; link < KMaxPanConnections; ++link) 
       
   398                     {
       
   399                     // skip the local connection
       
   400                     if(KBnepLocalDeviceArrayId != link)
       
   401                         {
       
   402                         if(iLinks[link])
       
   403                             {
       
   404                             iLinks[link]->Process(aFrame);	
       
   405                             }
       
   406                         }
       
   407                     }
       
   408                 }
       
   409             break;	
       
   410 
       
   411         default:	
       
   412             // Obviously we shouldn't get here under normal circumstances.
       
   413             // In a UDEB build we'll log the event.
       
   414             // Otherwise, just drop the frame.
       
   415             LOG(_L8("CBnepBridge: Invalid destination type."));
       
   416         }
       
   417     aFrame.Reset();
       
   418     
       
   419    	return (KReadyForMoreData);
       
   420 
       
   421     }
       
   422 
       
   423 
       
   424 void CBnepBridge::DataCountUpdated()
       
   425 	{
       
   426     LOG_FUNC
       
   427 	__ASSERT_ALWAYS(iDataCounterTimer,BnepUtils::Panic(Bnep::ENullPointer));
       
   428 	if (!iDataCounterTimer->IsActive()) // If the timer is not active
       
   429 		{
       
   430 	    iIdleCount = 0; // Reset the idle counter
       
   431  	    iDataCounterTimer->Start(KBnepPacketNotifyInterval,KBnepPacketNotifyInterval,TCallBack(DataCounterCallBack,this)); // Start the timer
       
   432  	    }
       
   433  	}
       
   434 
       
   435 
       
   436 /**
       
   437 	Set a flag to enable a connection retry to occur - this means that Nifman will not be signalled when we disconnect all devices
       
   438 */
       
   439 void CBnepBridge::SetRetryConnect () 
       
   440 	{
       
   441     LOG_FUNC
       
   442 	iRetryConnect=ETrue;
       
   443 	}
       
   444 
       
   445 
       
   446 /**
       
   447    Remove a device from the bridge.
       
   448 */
       
   449 void CBnepBridge::RemoveDevice (MPanDevice& aDevice)
       
   450     {
       
   451     LOG_FUNC
       
   452     for (TUint index = 0; index < KMaxPanConnections; ++index)
       
   453         {
       
   454         if(iLinks[index] == &aDevice)
       
   455             {
       
   456             iLinks[index] = NULL;
       
   457             LOG1(_L8("CBnepBridge removed iLink[%d]"),index);
       
   458             iLinkCount--;
       
   459             LOG1(_L8("CBnepBridge has %d links"),iLinkCount);
       
   460 			if (iBnepPacketNotifier) 
       
   461         		{
       
   462         		for (TUint dataIndex=0; dataIndex < iDataTransferred.Count(); ++dataIndex)
       
   463         			{
       
   464         			if (iDataTransferred[dataIndex].iBTDevAddr==aDevice.iAddr) 
       
   465         				{
       
   466         				iDataTransferred.Remove(dataIndex);
       
   467         				}
       
   468         			}
       
   469         		iBnepPacketNotifier->MbpnDeviceRemoved(aDevice.iAddr);
       
   470         		}
       
   471 
       
   472 			// If no more remote devices, tell the local device
       
   473         	if (iLinkCount == 1 && !iRetryConnect)
       
   474         		{
       
   475 	            LOG1(_L8("CBnepBridge::RemoveDevice - Only local link remaining [0x%08x]"), iLinks[KBnepLocalDeviceArrayId]);
       
   476         		static_cast<CBnepLocalDevice*> (iLinks[KBnepLocalDeviceArrayId])->AllRemoteDevicesDisconnected ();
       
   477         		}
       
   478             
       
   479             iRetryConnect = EFalse;
       
   480             
       
   481             break;
       
   482             }
       
   483         }
       
   484     }
       
   485 
       
   486 /**
       
   487    Forces a disconnect on all links.
       
   488 */
       
   489 void CBnepBridge::StopLinks ()
       
   490     {
       
   491     LOG_FUNC
       
   492     for (TUint index = 0; index < KMaxPanConnections; ++index)
       
   493         {
       
   494         if((KBnepLocalDeviceArrayId !=index) &&
       
   495            (NULL != iLinks[index]))
       
   496             {
       
   497             iLinks[index]->Stop(); // Stops all pending reads.
       
   498             }
       
   499         }
       
   500     }
       
   501 
       
   502 /**
       
   503    Attempts to find the index of a vacant slot in the bridge device array.
       
   504    @param aSlotIndex holds the array index of the vacant slot on success
       
   505    @return KErrNone on success
       
   506    @return KErrOverflow if there is no vacant slot
       
   507 */
       
   508 TInt CBnepBridge::GetVacantSlot (TUint& aSlotIndex)
       
   509     {
       
   510     LOG_FUNC
       
   511     
       
   512     for(TUint index = 0; index < KMaxPanConnections; ++index)
       
   513         {
       
   514         if(NULL == iLinks[index])
       
   515             {
       
   516             aSlotIndex = index;
       
   517             return KErrNone;
       
   518             }
       
   519         }
       
   520     return KErrOverflow;
       
   521     }
       
   522 
       
   523 
       
   524 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
   525 /**
       
   526 Entry point from the comms transport
       
   527 */
       
   528 void CBnepBridge::ReceivedL(const Messages::TRuntimeCtxId& aSender, const Messages::TNodeId& /* aRecipient */, Messages::TSignatureBase& aCFMessage)
       
   529     {
       
   530     LOG_FUNC
       
   531 	if (aCFMessage.MessageId().Realm() == TPanMessage::ERealmId)
       
   532     	{
       
   533         switch (aCFMessage.MessageId().MessageId())
       
   534             {
       
   535             case TPanMessage::TCreateChannelController::EId:
       
   536                 {
       
   537                 const TNodeCtxId& ctxId = address_cast<TNodeCtxId> (aSender);
       
   538                 TUint activityId = ctxId.NodeCtx();
       
   539                 AttemptNewBnepConnection(ctxId.Node().NodeId(), aCFMessage, activityId);
       
   540                 }
       
   541                 break;            
       
   542             
       
   543             case TPanMessage::TSetRetryConnect::EId:
       
   544                 {
       
   545                 // iSender in this case should be the CPanAgent
       
   546                 SetRetryConnect();
       
   547                 TPanMessage::TSetRetryConnectComplete msg(KErrNone);
       
   548                 RClientInterface::OpenPostMessageClose(Id(),aSender,msg);	        
       
   549                 }
       
   550                 break;
       
   551             
       
   552             default:
       
   553                 __ASSERT_DEBUG(EFalse, BnepUtils::Panic(Bnep::EUnexpectedMessage));
       
   554             }
       
   555     	}
       
   556     else
       
   557         {
       
   558         __ASSERT_DEBUG(EFalse, BnepUtils::Panic(Bnep::EUnexpectedMessage));
       
   559         }
       
   560     
       
   561     // Absorb messages
       
   562     aCFMessage.ClearMessageId();
       
   563     }
       
   564 
       
   565 CBnepBridge::CPanLinkControl* CBnepBridge::CPanLinkControl::NewL()
       
   566     {
       
   567     LOG_STATIC_FUNC
       
   568     CBnepBridge::CPanLinkControl* self = new(ELeave) CPanLinkControl();
       
   569     CleanupStack::PushL(self);
       
   570     self->ConstructL();
       
   571     CleanupStack::Pop(self);
       
   572     return self; 
       
   573     }
       
   574 
       
   575 CBnepBridge::CPanLinkControl::CPanLinkControl()
       
   576 	{
       
   577     LOG_FUNC
       
   578 	}
       
   579 		
       
   580 void CBnepBridge::CPanLinkControl::ConstructL()
       
   581 	{
       
   582     LOG_FUNC
       
   583 	User::LeaveIfError(iSockServ.Connect());
       
   584 	}
       
   585 
       
   586 CBnepBridge::CPanLinkControl::~CPanLinkControl()
       
   587 	{
       
   588     LOG_FUNC
       
   589 	iSockServ.Close();
       
   590 	}
       
   591 
       
   592 TAny* CBnepBridge::CPanLinkControl::MplcbGetInterface(const TUid & aInterface)
       
   593 	{
       
   594     LOG_FUNC
       
   595     if (aInterface ==KUidPanLinkControlV1) 
       
   596         {    
       
   597         return this;
       
   598         }    
       
   599     return NULL;
       
   600 	}
       
   601 
       
   602 TInt CBnepBridge::CPanLinkControl::MplcRequestSniff(const TBTDevAddr &aAddr)
       
   603 	{
       
   604     LOG_FUNC
       
   605     RBTPhysicalLinkAdapter physicalLink;
       
   606     TInt err = physicalLink.Open(iSockServ, const_cast<TBTDevAddr&>(aAddr));
       
   607 	if(err == KErrNone)
       
   608 		{
       
   609     	err = physicalLink.ActivateSniffRequester();
       
   610     	physicalLink.Close();
       
   611 		}
       
   612 	return err;
       
   613 	}
       
   614 
       
   615 TInt CBnepBridge::CPanLinkControl::MplcRequestActive(const TBTDevAddr &aAddr) 
       
   616 	{
       
   617     LOG_FUNC
       
   618     RBTPhysicalLinkAdapter physicalLink;
       
   619     TInt err = physicalLink.Open(iSockServ, const_cast<TBTDevAddr&>(aAddr));
       
   620 	if(err == KErrNone)
       
   621 		{
       
   622     	physicalLink.ActivateActiveRequester();
       
   623     	physicalLink.Close();
       
   624 		}
       
   625 	return err;
       
   626 	}
       
   627 #endif
       
   628