bluetoothengine/btmac/src/btmac/btmrfcommsock.cpp
changeset 0 f63038272f30
child 6 6a29d5ad0713
equal deleted inserted replaced
-1:000000000000 0:f63038272f30
       
     1 /*
       
     2 * Copyright (c) 2005-2006 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:  BT RFComm socket
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <badesca.h>
       
    20 #include "btmrfcommsock.h"
       
    21 #include "btmsockobserver.h"
       
    22 #include "debug.h"
       
    23 
       
    24 // Constant for listening queue size
       
    25 const TInt KListenQueSize = 1;
       
    26 
       
    27 // ======== MEMBER FUNCTIONS ========
       
    28 
       
    29 CBtmRfcommSock* CBtmRfcommSock::NewL(MBtmSockObserver& aObserver, RSocketServ& aServer)
       
    30     {
       
    31     CBtmRfcommSock* self = new (ELeave) CBtmRfcommSock(aObserver, aServer);
       
    32     CleanupStack::PushL(self);
       
    33     self->ConstructL();
       
    34     CleanupStack::Pop(self);
       
    35     return self;
       
    36     }
       
    37 
       
    38 CBtmRfcommSock::~CBtmRfcommSock()
       
    39     {
       
    40 	TRACE_FUNC_ENTRY
       
    41 	iAda.Close();
       
    42     delete iDataSocket;
       
    43     delete iListenSocket;
       
    44     iInData.Close();
       
    45     iOutData.Close();
       
    46     delete iOutDataQueue;
       
    47     TRACE_FUNC_EXIT
       
    48     }
       
    49 
       
    50 // ---------------------------------------------------------
       
    51 // CBtmRfcommSock::Connect
       
    52 // ---------------------------------------------------------
       
    53 //
       
    54 void CBtmRfcommSock::ConnectL(TBTSockAddr& aAddr, TUint aService)
       
    55     {
       
    56     TRACE_FUNC_ENTRY
       
    57     TProtocolDesc pInfo;
       
    58     LEAVE_IF_ERROR(iServer.FindProtocol(TProtocolName(KRFCOMMDesC), pInfo));
       
    59     if (!iDataSocket)
       
    60         {
       
    61         iDataSocket = CBluetoothSocket::NewL(*this, iServer, pInfo.iSockType, pInfo.iProtocol);
       
    62         }
       
    63     LEAVE_IF_ERROR(iDataSocket->Connect(aAddr));
       
    64     iService = aService;
       
    65     iRemote = TBTDevAddr();
       
    66     iRemoteHasConnected = EFalse;
       
    67     TRACE_FUNC_EXIT
       
    68     }
       
    69 
       
    70 // ---------------------------------------------------------
       
    71 // CBtmRfcommSock::CancelActiveConnectSocket
       
    72 // ---------------------------------------------------------
       
    73 //
       
    74 void CBtmRfcommSock::CancelConnect()
       
    75     {
       
    76     if (iDataSocket)
       
    77         {
       
    78         TRACE_FUNC_ENTRY
       
    79         iDataSocket->CancelConnect();
       
    80         TRACE_FUNC_EXIT
       
    81         }
       
    82     }
       
    83 
       
    84 TBool CBtmRfcommSock::AccessoryInitiatedConnection()
       
    85 	{
       
    86 	return iRemoteHasConnected;
       
    87 	}
       
    88 	
       
    89 
       
    90 TUint CBtmRfcommSock::ListenL(TUint aService, const TBTServiceSecurity& aSec, TUint aLastUsedPort)
       
    91     {
       
    92     TRACE_FUNC_ENTRY
       
    93     TRACE_ASSERT(!iListenSocket, EBTPanicRfcommAlreadyListen)
       
    94     TRACE_ASSERT(!iDataSocket, EBTPanicRfcommSockInuse)
       
    95 	TProtocolDesc pInfo;
       
    96 	LEAVE_IF_ERROR(iServer.FindProtocol(TProtocolName(KRFCOMMDesC), pInfo));
       
    97 	iListenSocket = CBluetoothSocket::NewL(*this, iServer, pInfo.iSockType, pInfo.iProtocol);
       
    98 	TRfcommSockAddr addr;
       
    99 	addr.SetSecurity(aSec);
       
   100 	
       
   101 	TRACE_INFO((_L("Trying lastused port %d"), aLastUsedPort))
       
   102 	addr.SetPort(aLastUsedPort);
       
   103 	TInt error = iListenSocket->Bind(addr);
       
   104 	if ( error )
       
   105 	    {
       
   106 	    TRACE_INFO((_L("Trying KRfcommPassiveAutoBind")))
       
   107 	    addr.SetPort(KRfcommPassiveAutoBind);
       
   108 	    LEAVE_IF_ERROR(iListenSocket->Bind(addr));
       
   109 	    }	
       
   110 	LEAVE_IF_ERROR(iListenSocket->Listen(KListenQueSize));
       
   111 	iDataSocket = CBluetoothSocket::NewL(*this, iServer);
       
   112 	LEAVE_IF_ERROR(iListenSocket->Accept(*iDataSocket));
       
   113 	iService = aService;
       
   114 	TRACE_FUNC_EXIT
       
   115 	iRemote = TBTDevAddr();
       
   116 	return iListenSocket->LocalPort();
       
   117     }
       
   118 
       
   119 void CBtmRfcommSock::CancelListen()
       
   120     {
       
   121     if (iListenSocket)
       
   122         {
       
   123         TRACE_FUNC_ENTRY
       
   124         iListenSocket->CancelAccept();
       
   125         TRACE_FUNC_EXIT
       
   126         }
       
   127     }
       
   128 
       
   129 void CBtmRfcommSock::Disconnect(RSocket::TShutdown aHow)
       
   130     {
       
   131     TRACE_FUNC_ENTRY
       
   132     if (iDataSocket)
       
   133         {
       
   134 	    iAda.ActivateActiveRequester();
       
   135         iDataSocket->CancelWrite();
       
   136         iDataSocket->CancelRecv();
       
   137         iDataSocket->CancelIoctl();
       
   138         iDataSocket->Shutdown(aHow);
       
   139         }
       
   140     iRemote = TBTDevAddr();
       
   141     TRACE_FUNC_EXIT
       
   142     }
       
   143 
       
   144 void CBtmRfcommSock::WriteL(const TDesC8& aData)
       
   145     {
       
   146     TRACE_FUNC_ENTRY
       
   147     TRACE_ASSERT(iDataSocket != NULL, EBTPanicObjectUninitialized)
       
   148     if (!iOutDataQueue)
       
   149         {
       
   150         iOutDataQueue = new (ELeave) CDesC8ArrayFlat(1);
       
   151         }
       
   152     iOutDataQueue->AppendL(aData);
       
   153     SendPacketL();
       
   154     TRACE_FUNC_EXIT
       
   155     }
       
   156 
       
   157 void CBtmRfcommSock::CancelWrite()
       
   158     {
       
   159     if (iDataSocket)
       
   160         {
       
   161         TRACE_FUNC_ENTRY
       
   162         iDataSocket->CancelWrite();
       
   163         iOutDataQueue->Reset();
       
   164         TRACE_FUNC_EXIT
       
   165         }
       
   166     }
       
   167 
       
   168 const TBTDevAddr& CBtmRfcommSock::Remote() const
       
   169     {
       
   170     return iRemote;
       
   171     }
       
   172 
       
   173 TInt CBtmRfcommSock::RequestMasterRole()
       
   174     {
       
   175     TRACE_FUNC
       
   176     TRACE_ASSERT(iDataSocket, EBTPanicNullPointer)
       
   177     TUint32 basebandState = 0;
       
   178     TInt err = iDataSocket->PhysicalLinkState( basebandState );
       
   179     if (!err && (basebandState & ENotifySlave))
       
   180         {
       
   181         err = iDataSocket->RequestMasterRole();
       
   182         }
       
   183     return err;
       
   184     }
       
   185 
       
   186 TBool CBtmRfcommSock::IsInSniff() const
       
   187     {
       
   188     return iInSniff;
       
   189     }
       
   190 
       
   191 TInt CBtmRfcommSock::ActivateBasebandEventNotification(TInt aNotification)
       
   192     {
       
   193     TRACE_FUNC
       
   194     TRACE_ASSERT(iDataSocket, EBTPanicNullPointer)
       
   195     iBBNotificationMode = aNotification;
       
   196     return iDataSocket->ActivateBasebandEventNotifier(aNotification);
       
   197     }
       
   198 
       
   199 void CBtmRfcommSock::SetObserver(MBtmSockObserver& aObserver)
       
   200     {
       
   201     TRACE_FUNC
       
   202     iObserver = &aObserver;
       
   203     }
       
   204 
       
   205 TUint CBtmRfcommSock::Service() const
       
   206     {
       
   207     return iService;
       
   208     }
       
   209 
       
   210 TInt CBtmRfcommSock::ActivateSniffRequester()
       
   211     {
       
   212     if (iDataSocket)
       
   213         return iAda.ActivateSniffRequester();
       
   214     else
       
   215         return KErrGeneral;
       
   216     }
       
   217 
       
   218 void CBtmRfcommSock::RequestLinkToActiveMode()
       
   219     {
       
   220     if (iDataSocket)
       
   221         {
       
   222     	TInt err = iAda.ActivateActiveRequester();
       
   223     	TRACE_INFO((_L("ada.ActivateActiveRequester err %d"), err))    
       
   224         }
       
   225     TRACE_FUNC
       
   226     }
       
   227 
       
   228 void CBtmRfcommSock::HandleConnectCompleteL(TInt aErr)
       
   229     {
       
   230     TRACE_FUNC_ENTRY
       
   231     TRACE_INFO((_L("err %d"), aErr))
       
   232 
       
   233     // Process the connect complete before issuing a receive request to ensure that
       
   234     // we are ready to process the data when it is received.
       
   235     iObserver->RfcommConnectCompletedL(aErr);
       
   236 
       
   237     if (!aErr)
       
   238         {
       
   239         TBTSockAddr sockAddr;
       
   240         iDataSocket->RemoteName(sockAddr);
       
   241         iRemote = sockAddr.BTAddr();
       
   242         iInData.ReAllocL(256);
       
   243         RequestMasterRole();
       
   244         TInt err = iAda.Open(iServer, iRemote);
       
   245         TRACE_INFO((_L("ada.Open err %d"), err))
       
   246         iDataSocket->ActivateBasebandEventNotifier(ENotifyAnyPowerMode | ENotifyAnyRole | 
       
   247                                                    ENotifySCOLinkUp | ENotifySCOLinkDown | 
       
   248                                                    ENotifySCOLinkError | ENotifyPhysicalLinkUp | 
       
   249                                                    ENotifyPhysicalLinkDown | ENotifyPhysicalLinkError);
       
   250         ReceiveL();
       
   251         }
       
   252     TRACE_FUNC_EXIT
       
   253     }
       
   254 
       
   255 void CBtmRfcommSock::HandleAcceptCompleteL(TInt aErr)
       
   256     {
       
   257     TRACE_FUNC_ENTRY
       
   258 
       
   259     iRemoteHasConnected = ETrue;
       
   260 
       
   261     // Process the accept complete before issuing a receive request to ensure that
       
   262     // we are ready to process the data when it is received.
       
   263     iObserver->RfcommAcceptCompletedL(aErr, iService);
       
   264 
       
   265    if (!aErr)
       
   266         {
       
   267         TBTSockAddr sockAddr;
       
   268         iDataSocket->RemoteName(sockAddr);
       
   269         iRemote = sockAddr.BTAddr();
       
   270         iInData.ReAllocL(256);
       
   271         RequestMasterRole();
       
   272         TInt err = iAda.Open(iServer, iRemote);
       
   273         TRACE_INFO((_L("ada.Open err %d"), err))
       
   274         iDataSocket->ActivateBasebandEventNotifier(ENotifyAnyPowerMode | ENotifyAnyRole |
       
   275                                                    ENotifySCOLinkUp | ENotifySCOLinkDown | 
       
   276                                                    ENotifySCOLinkError | ENotifyPhysicalLinkUp | 
       
   277                                                    ENotifyPhysicalLinkDown | ENotifyPhysicalLinkError);
       
   278         ReceiveL();
       
   279         }
       
   280     TRACE_FUNC_EXIT   
       
   281     }
       
   282 
       
   283 void CBtmRfcommSock::HandleShutdownCompleteL(TInt aErr)
       
   284     {
       
   285     TRACE_FUNC
       
   286     iObserver->RfcommShutdownCompletedL(aErr);
       
   287     }
       
   288 
       
   289 void CBtmRfcommSock::HandleSendCompleteL(TInt aErr)
       
   290     {
       
   291     TRACE_FUNC
       
   292     TRACE_INFO((_L("err %d"), aErr))
       
   293     iWriting = EFalse;
       
   294     if (!aErr)
       
   295         {
       
   296         SendPacketL();
       
   297         }
       
   298     else
       
   299         {
       
   300         iObserver->RfcommSendCompletedL(aErr);
       
   301         }
       
   302     }
       
   303 
       
   304 void CBtmRfcommSock::HandleReceiveCompleteL(TInt aErr)
       
   305     {
       
   306     TRACE_FUNC
       
   307     TRACE_INFO((_L("err %d"), aErr))
       
   308 
       
   309     iObserver->RfcommReceiveCompletedL(aErr, iInData);
       
   310     if (!aErr)
       
   311         {
       
   312         ReceiveL();
       
   313         }
       
   314     }
       
   315 
       
   316 void CBtmRfcommSock::HandleIoctlCompleteL(TInt aErr)
       
   317     {
       
   318     TRACE_FUNC
       
   319     TRACE_INFO((_L("KL2CAPEchoRequestIoctl callback code: %d"), aErr ))
       
   320     
       
   321     if (aErr)
       
   322         {
       
   323         iObserver->RfcommSendCompletedL(aErr);
       
   324         }
       
   325     }
       
   326 
       
   327 void CBtmRfcommSock::HandleActivateBasebandEventNotifierCompleteL(
       
   328     TInt aErr, TBTBasebandEventNotification& aEventNotification)
       
   329     {
       
   330     TRACE_FUNC_ENTRY
       
   331     if (!aErr)
       
   332         {
       
   333     	switch(aEventNotification.EventType())
       
   334     		{
       
   335     		case ENotifyActiveMode:
       
   336     			{
       
   337     			TRACE_INFO(_L( "BB Notif: Active mode" ))
       
   338     			iInSniff = EFalse;
       
   339     			break;
       
   340     			}
       
   341     		case ENotifySniffMode:
       
   342     			{
       
   343     			TRACE_INFO(_L( "BB Notif: Sniff mode" ))
       
   344     			break;
       
   345     			}
       
   346     		case ENotifyMaster:
       
   347     			{
       
   348     			TRACE_INFO(_L( "BB Notif: Master role"))
       
   349     			break;
       
   350     			}
       
   351     		case ENotifySlave:
       
   352     			{
       
   353     			TRACE_INFO(_L("BB Notif: Slave role"))
       
   354     			break;
       
   355     			}
       
   356     		case ENotifySCOLinkUp:
       
   357     			{
       
   358     			TRACE_INFO(_L("BB Notif: SCO up"))
       
   359     			break;
       
   360     			}
       
   361     		case ENotifySCOLinkDown:
       
   362     			{
       
   363     			TRACE_INFO(_L("BB Notif: SCO down"))
       
   364     			
       
   365                 TInt err = iDataSocket->Ioctl( KL2CAPEchoRequestIoctl, NULL, KSolBtL2CAP );
       
   366                 
       
   367                 TRACE_INFO((_L("KL2CAPEchoRequestIoctl return code: %d"), err ))
       
   368     			break;
       
   369     			}
       
   370     		case ENotifySCOLinkError:
       
   371     			{
       
   372     			TRACE_INFO(_L("BB Notif: SCO error"))
       
   373     			break;
       
   374     			}
       
   375     		case ENotifyPhysicalLinkUp:
       
   376     		    {
       
   377                 TRACE_INFO(_L("BB Notif: Physical link up"))    		        
       
   378     		    break;
       
   379     		    }
       
   380     		case ENotifyPhysicalLinkDown:
       
   381     		    {
       
   382                 TRACE_INFO(_L("BB Notif: Physical link down"))    		        
       
   383     		    break;
       
   384     		    }
       
   385     		case ENotifyPhysicalLinkError:
       
   386     		    {
       
   387                 TRACE_INFO(_L("BB Notif: Physical link error"))    		        
       
   388     		    break;
       
   389     		    }
       
   390     		default:
       
   391     			{
       
   392     			TRACE_INFO((_L( "BB Notif: Uninteresting event (0x%08X)"), aEventNotification.EventType()))
       
   393     			}
       
   394     		};
       
   395         }
       
   396     TRACE_FUNC_EXIT
       
   397     }
       
   398 
       
   399 void CBtmRfcommSock::ConstructL()
       
   400     {
       
   401     }
       
   402 
       
   403 CBtmRfcommSock::CBtmRfcommSock(MBtmSockObserver& aObserver, RSocketServ& aServer)
       
   404     : iObserver(&aObserver), iServer(aServer), iInSniff(EFalse)
       
   405     {
       
   406     TRACE_FUNC
       
   407     }
       
   408 
       
   409 // -----------------------------------------------------------------------------
       
   410 // CBtmAtPipe::HandleAccessoryDataEventL
       
   411 // -----------------------------------------------------------------------------
       
   412 //
       
   413 void CBtmRfcommSock::SendPacketL()
       
   414     {
       
   415     if (!iWriting && iOutDataQueue && iOutDataQueue->MdcaCount() > 0)
       
   416         {
       
   417         if (iOutData.MaxLength() < iOutDataQueue->MdcaPoint(0).Length())
       
   418             {
       
   419             iOutData.ReAllocL(iOutDataQueue->MdcaPoint(0).Length());
       
   420             } 
       
   421         iOutData.Copy(iOutDataQueue->MdcaPoint(0));
       
   422         iDataSocket->Write(iOutData);
       
   423         iOutDataQueue->Delete(0);
       
   424         TRACE_INFO((_L8("[HFP] [O] %S"), &iOutData))
       
   425         iWriting = ETrue;
       
   426         }
       
   427     }
       
   428 
       
   429 void CBtmRfcommSock::ReceiveL()
       
   430     {
       
   431     TRACE_FUNC
       
   432     TRACE_ASSERT(iDataSocket != NULL, EBTPanicObjectUninitialized)
       
   433     iInData.Zero();
       
   434     LEAVE_IF_ERROR(iDataSocket->RecvOneOrMore(iInData, 0, iXfrLength));
       
   435     }
       
   436 
       
   437 void CBtmRfcommSock::CancelReceive()
       
   438     {
       
   439     if (iDataSocket)
       
   440         {
       
   441         TRACE_FUNC_ENTRY
       
   442         iDataSocket->CancelRecv();
       
   443         TRACE_FUNC_EXIT
       
   444         }
       
   445     }
       
   446 
       
   447 void CBtmRfcommSock::SetService(TUint aService)
       
   448 		{
       
   449 		iService = aService;
       
   450 		}