usbmgmt/usbmgr/device/classdrivers/ncm/classcontroller/src/ncmclientmanager.cpp
branchRCL_3
changeset 15 f92a4f87e424
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbmgmt/usbmgr/device/classdrivers/ncm/classcontroller/src/ncmclientmanager.cpp	Tue Aug 31 17:01:47 2010 +0300
@@ -0,0 +1,556 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+/**
+ * @file
+ * @internalComponent
+ */
+
+#include "ncmclientmanager.h"
+
+
+#ifdef OVERDUMMY_NCMCC
+#include <usb/testncmcc/dummy_ncminternalsrv.h>
+#else
+#include "ncminternalsrv.h"
+#endif // OVERDUMMY_NCMCC
+
+#include "ncmclassdescriptor.h"
+// For OST tracing
+#include "OstTraceDefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "ncmclientmanagerTraces.h"
+#endif
+
+
+// NCM Interface MTU size
+extern const TUint KEthernetFrameSize;
+
+// NCM MAC Address String descriptor buffer length
+const TUint KMacAddrStringDescSize = 32;
+
+
+/**
+ * Construtor
+ * @param aMacAddress the NCM ethernet interface MAC address
+ */
+CNcmClientManager::CNcmClientManager(const TNcmMacAddress& aHostMacAddress):
+        iHostMacAddress(aHostMacAddress)
+    {
+    OstTraceFunctionEntryExt( CNCMCLIENTMANAGER_CNCMCLIENTMANAGER_ENTRY, this );
+    
+    // No implementation required
+    OstTraceFunctionExit1( CNCMCLIENTMANAGER_CNCMCLIENTMANAGER_EXIT, this );
+    }
+
+/**
+ * Destructor
+ */
+CNcmClientManager::~CNcmClientManager()
+    {
+    OstTraceFunctionEntry0( CNCMCLIENTMANAGER_CNCMCLIENTMANAGER_ENTRY_DESTRUCTOR );
+    
+    TInt err = KErrNone;
+    if (iCommLddInitiated)
+        {
+        RChunk* commChunk = NULL;
+        OstTrace0(TRACE_NORMAL, CNCMCLIENTMANAGER_CNCMCLIENTMANAGER_PRE_CLOSE_COMM_INTERFACE, "About to get chunk handle for communication interface!");        
+        err = iCommLdd.GetDataTransferChunk(commChunk);
+        if (KErrNone == err)
+            {
+            OstTrace0(TRACE_NORMAL, CNCMCLIENTMANAGER_CNCMCLIENTMANAGER_CLOSE_COMM_CHUNK, "About to close chunk handle for communication interface!");
+            commChunk->Close();    
+            }
+        else
+            {
+            OstTrace1(TRACE_ERROR, CNCMCLIENTMANAGER_CNCMCLIENTMANAGER_CLOSE_COMM_CHUNK_FAIL, "Can not get chunk handle for communication interface: err = %d", err);
+            }
+        
+        OstTrace0(TRACE_NORMAL, CNCMCLIENTMANAGER_CNCMCLIENTMANAGER_CLOSE_COMM_INTERFACE, "About to close device handle for communication interface!");        
+        iCommLdd.Close();
+        }
+
+    if (iDataLddInitiated)
+        {
+        RChunk* dataChunk = NULL;
+        OstTrace0(TRACE_NORMAL, CNCMCLIENTMANAGER_CNCMCLIENTMANAGER_PRE_CLOSE_DATA_INTERFACE, "About to get chunk handle for data interface!");
+        err = iDataLdd.GetDataTransferChunk(dataChunk);
+        if (KErrNone == err)
+            {
+            OstTrace0(TRACE_NORMAL, CNCMCLIENTMANAGER_CNCMCLIENTMANAGER_CLOSE_DATA_CHUNK, "About to close chunk handle for communication interface!");
+            dataChunk->Close();
+            }
+        else
+            {
+            OstTrace1(TRACE_ERROR, CNCMCLIENTMANAGER_CNCMCLIENTMANAGER_CLOSE_DATA_CHUNK_FAIL, "Can not get chunk handle for data interface: err = %d", err);
+            }
+
+        OstTrace0(TRACE_NORMAL, CNCMCLIENTMANAGER_CNCMCLIENTMANAGER_CLOSE_DATA_INTERFACE, "About to close device handle for data interface!");
+        iDataLdd.Close();
+        }
+    OstTraceFunctionExit0( CNCMCLIENTMANAGER_CNCMCLIENTMANAGER_ENTRY_DESTRUCTOR_EXIT );
+    }
+
+
+/**
+ * Setup NCM interfaces
+ * @param[out]   aDataEpBufferSize, NCM data interface EP buffer size
+ */
+void CNcmClientManager::SetNcmInterfacesL(TUint& aDataEpBufferSize)
+    {
+    OstTraceFunctionEntryExt( CNCMCLIENTMANAGER_SETNCMINTERFACESL_ENTRY, this );
+    
+    // Setup NCM communication interface
+    SetCommunicationInterfaceL();
+    
+    // Setup NCM data interface
+    SetDataInterfaceL(aDataEpBufferSize);
+    
+    // Retrieve data interface number
+    TUint8 dataInterfaceNumber = 1;
+    User::LeaveIfError(DataInterfaceNumber(dataInterfaceNumber));
+    
+    // Setup NCM class descriptor with correct interface number
+    User::LeaveIfError(SetupClassSpecificDescriptor(dataInterfaceNumber));
+    OstTraceFunctionExit1( CNCMCLIENTMANAGER_SETNCMINTERFACESL_EXIT, this );
+    }
+
+/**
+ * Transfer NCM interface handlers from NCM class controller to NCM 
+ * packet driver through NCM internal server.
+ * @param aServer a reference to RNcmInternalSrv 
+ */
+void CNcmClientManager::TransferInterfacesL(RNcmInternalSrv& aServer)
+    {
+    OstTraceFunctionEntryExt( CNCMCLIENTMANAGER_TRANSFERINTERFACESL_ENTRY, this );
+    
+    RChunk* commChunk = NULL;
+    RChunk* dataChunk = NULL;
+
+    OstTrace0(TRACE_NORMAL, CNCMCLIENTMANAGER_TRANSFERINTERFACESL_PRE_TRANSFER_INTERFACES, "About to Transfer handles to NCM internal server!");
+    User::LeaveIfError(iCommLdd.GetDataTransferChunk(commChunk));
+    User::LeaveIfError(iDataLdd.GetDataTransferChunk(dataChunk));
+    User::LeaveIfError(aServer.TransferHandle(iCommLdd, *commChunk, 
+            iDataLdd, *dataChunk));
+    OstTrace0(TRACE_NORMAL, CNCMCLIENTMANAGER_TRANSFERINTERFACESL_INTERFACES_TRANSFERED, "Transfer handles to NCM internal server Done!");
+    OstTraceFunctionExit1( CNCMCLIENTMANAGER_TRANSFERINTERFACESL_EXIT, this );
+    }
+
+/**
+ * Setup NCM communication inteface
+ */
+void CNcmClientManager::SetCommunicationInterfaceL()
+    {
+    OstTraceFunctionEntry1( CNCMCLIENTMANAGER_SETCOMMUNICATIONINTERFACEL_ENTRY, this );
+        
+    User::LeaveIfError(iCommLdd.Open(0));
+    iCommLddInitiated = ETrue;
+
+    TInt err = KErrNone;
+
+    TUsbcScInterfaceInfoBuf ifc0;
+    TUsbcDeviceState deviceStatus;
+    
+    User::LeaveIfError(iCommLdd.DeviceStatus(deviceStatus));
+
+    if (deviceStatus == EUsbcDeviceStateConfigured)
+        {
+        User::Leave( KErrInUse);
+        }
+
+    TUsbDeviceCaps dCaps;
+    User::LeaveIfError(iCommLdd.DeviceCaps(dCaps));
+
+    TInt epNum = dCaps().iTotalEndpoints;
+
+    TUsbcEndpointData data[KUsbcMaxEndpoints];
+    TPtr8 dataptr(reinterpret_cast<TUint8*> (data), sizeof(data),
+            sizeof(data));
+
+    User::LeaveIfError(iCommLdd.EndpointCaps(dataptr));
+
+    TBool foundIntIN = EFalse;
+    const TUint KEndPointType = KUsbEpTypeInterrupt | KUsbEpDirIn;
+    for (TInt i = 0; i < epNum; i++)
+        {
+        const TUsbcEndpointData* epData = &data[i];
+        if ((!epData->iInUse) && // Not in use
+            ((epData->iCaps.iTypesAndDir & KEndPointType) == KEndPointType))
+            {
+            // EEndpoint1 is going to be our INTERRUPT (IN, write) endpoint
+            ifc0().iEndpointData[0].iType = KUsbEpTypeInterrupt;
+            ifc0().iEndpointData[0].iDir = KUsbEpDirIn;
+            ifc0().iEndpointData[0].iSize = epData->iCaps.MinPacketSize();
+            ifc0().iEndpointData[0].iInterval = 0x01;
+            ifc0().iEndpointData[0].iInterval_Hs = 0x01;
+
+            foundIntIN = ETrue;
+            break;
+            }
+        }
+    if (EFalse == foundIntIN)
+        {
+        OstTrace0( TRACE_ERROR, CNCMCLIENTMANAGER_SETCOMMUNICATIONINTERFACEL, "Can not find proper endpint for NCM communication interface" );
+        User::Leave( KErrNotFound);
+        }
+    
+    /*********************************************************************************************/
+    //Communication Class Interface (0x00)
+    /*********************************************************************************************/
+    _LIT16(KIfClassName0, "USB Networking (NCM)");
+    HBufC16* string0 = KIfClassName0().AllocLC();
+
+    ifc0().iString = string0;
+    ifc0().iTotalEndpointsUsed = 1;
+    ifc0().iClass.iClassNum = 0x02;
+    ifc0().iClass.iSubClassNum = 0x0D;
+    ifc0().iClass.iProtocolNum = 0x00;
+
+    User::LeaveIfError(iCommLdd.SetInterface(0, ifc0));
+
+    err = iCommLdd.FinalizeInterface();
+    if (KErrNone != err)
+        {
+        OstTrace1(TRACE_ERROR, CNCMCLIENTMANAGER_SETCOMMUNICATIONINTERFACEL_FAIL_TO_INIT, "Failed to FinalizeInterface, err %d", err);
+        User::Leave(err);
+        }
+    CleanupStack::PopAndDestroy(string0);
+    OstTraceFunctionExit1( CNCMCLIENTMANAGER_SETCOMMUNICATIONINTERFACEL_EXIT, this );
+    }
+
+/**
+ * Setup NCM data interface
+ * @param   aDataEpBufferSize, the determined data interface 
+ *          endpoint buffer size.
+ */
+void CNcmClientManager::SetDataInterfaceL(TUint& aDataEpBufferSize)
+    {
+    OstTraceFunctionEntryExt( CNCMCLIENTMANAGER_SETDATAINTERFACEL_ENTRY, this );
+    
+    const TUint KMaxScBufferSize = 1048576; // Up limit of end point buffer
+    const TUint KMinScBufferSize = 262144;  // Lower limit of end point buffer
+    const TUint KMaxScReadSize = 65536;
+
+    User::LeaveIfError(iDataLdd.Open(0));
+    iDataLddInitiated = ETrue;
+
+    TUsbcScInterfaceInfoBuf ifc0, ifc1;
+    TUsbDeviceCaps dCaps;
+    User::LeaveIfError(iDataLdd.DeviceCaps(dCaps));
+
+    TBool isResourceAllocationV2 = ((dCaps().iFeatureWord1
+            & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) != 0);
+    
+    TUsbcDeviceState deviceStatus;
+    
+    User::LeaveIfError(iDataLdd.DeviceStatus(deviceStatus));
+    if (deviceStatus == EUsbcDeviceStateConfigured)
+        {
+        User::Leave(KErrInUse);
+        }
+
+    TInt epNum = dCaps().iTotalEndpoints;
+    TUsbcEndpointData data[KUsbcMaxEndpoints];
+    TPtr8 dataptr(reinterpret_cast<TUint8*> (data), sizeof(data),
+            sizeof(data));
+
+    User::LeaveIfError(iDataLdd.EndpointCaps(dataptr));
+
+    const TUint KNcmDataInterfaceEpNumber = 2;
+    TBool foundBulkIN = EFalse;
+    TBool foundBulkOUT = EFalse;
+    TInt maxPacketSize = 0;
+    const TUint KEndPointBulkInType = KUsbEpTypeBulk | KUsbEpDirIn;
+    const TUint KEndPointBulkOutType = KUsbEpTypeBulk | KUsbEpDirOut;
+    for (TInt i = 0; i < epNum; i++)
+        {
+        const TUsbcEndpointData* epData = &data[i];
+        
+        // Check if this endpoint is in use 
+        if (epData->iInUse)
+            {
+            continue;
+            }
+        
+        maxPacketSize = epData->iCaps.MaxPacketSize();
+        if (!foundBulkIN && 
+                ((epData->iCaps.iTypesAndDir & KEndPointBulkInType) == KEndPointBulkInType))
+            {
+            // EEndpoint1 is going to be our TX (IN, write) endpoint
+            ifc1().iEndpointData[0].iType = KUsbEpTypeBulk;
+            ifc1().iEndpointData[0].iDir = KUsbEpDirIn;
+            ifc1().iEndpointData[0].iSize = maxPacketSize;
+            ifc1().iEndpointData[0].iInterval_Hs = 0x0;
+            ifc1().iEndpointData[0].iBufferSize = KMaxScBufferSize;
+
+            if (isResourceAllocationV2)
+                {
+                ifc1().iEndpointData[0].iFeatureWord1 |= 
+                    (KUsbcEndpointInfoFeatureWord1_DMA | KUsbcEndpointInfoFeatureWord1_DoubleBuffering);
+                }
+            
+            foundBulkIN = ETrue;
+            if (foundBulkIN && foundBulkOUT)
+                {
+                break;
+                }
+            continue;
+            }
+
+        if (!foundBulkOUT && 
+                ((epData->iCaps.iTypesAndDir & KEndPointBulkOutType) == KEndPointBulkOutType))
+            {
+            // EEndpoint2 is going to be our RX (OUT, read) endpoint
+            ifc1().iEndpointData[1].iType = KUsbEpTypeBulk;
+            ifc1().iEndpointData[1].iDir = KUsbEpDirOut;
+            ifc1().iEndpointData[1].iSize = maxPacketSize;
+            ifc1().iEndpointData[1].iInterval_Hs = 0x1;
+            ifc1().iEndpointData[1].iBufferSize = KMaxScBufferSize;
+            ifc1().iEndpointData[1].iReadSize = KMaxScReadSize;
+
+            if (isResourceAllocationV2)
+                {
+                ifc1().iEndpointData[1].iFeatureWord1 |= 
+                    (KUsbcEndpointInfoFeatureWord1_DMA | KUsbcEndpointInfoFeatureWord1_DoubleBuffering);
+                }
+
+            foundBulkOUT = ETrue;
+            if (foundBulkIN && foundBulkOUT)
+                {
+                break;
+                }
+            continue;
+            }
+        }
+
+    // Leave if no properly endpoint is found
+    if (EFalse == foundBulkIN || EFalse == foundBulkOUT)
+        {
+        User::Leave(KErrNotFound);
+        }
+    
+    _LIT16(KIfClassName0, "NCM Data Interface 0");
+
+    HBufC16* string0 = KIfClassName0().AllocL();
+    CleanupStack::PushL(string0);    
+    ifc0().iString = string0;
+    ifc0().iTotalEndpointsUsed = 0;
+    ifc0().iClass.iClassNum = 0x0A;
+    ifc0().iClass.iSubClassNum = 0x00;
+    ifc0().iClass.iProtocolNum = 0x01;    
+    User::LeaveIfError(iDataLdd.SetInterface(0, ifc0));
+        
+    _LIT16(KIfClassName1, "NCM Data Interface 1");
+    HBufC16* string1 = KIfClassName1().AllocL();
+    CleanupStack::PushL(string1);
+    ifc1().iString = string1;
+    ifc1().iTotalEndpointsUsed = KNcmDataInterfaceEpNumber;
+    ifc1().iClass.iClassNum = 0x0A;
+    ifc1().iClass.iSubClassNum = 0x00;
+    ifc1().iClass.iProtocolNum = 0x01;
+    
+    // Try to allocate expected memory for data interface endpoints
+    aDataEpBufferSize = KMaxScBufferSize;
+    
+    TInt err = KErrNone; 
+    FOREVER
+        {
+        OstTrace1(TRACE_NORMAL, CNCMCLIENTMANAGER_SETDATAINTERFACEL_TRY_NEW_BUF_SIZE, "Try buffer size: %d", aDataEpBufferSize);
+        err = iDataLdd.SetInterface(1, ifc1);
+        if (KErrNoMemory == err)
+            {
+            // Reduce buffer size and retry
+            aDataEpBufferSize = aDataEpBufferSize / 2;
+            if (aDataEpBufferSize < KMinScBufferSize)
+                {
+                User::Leave(KErrNoMemory);
+                }
+            ifc1().iEndpointData[0].iBufferSize = aDataEpBufferSize;
+            ifc1().iEndpointData[1].iBufferSize = aDataEpBufferSize;
+            continue;
+            }
+        else
+            {
+            OstTrace1(TRACE_ERROR, CNCMCLIENTMANAGER_SETDATAINTERFACEL_SET_INTERFACE_FAIL, "Set data interface and the returned err code is %d", err);
+            // Leave with error code
+            User::LeaveIfError(err);
+            break;
+            }
+        }
+    
+    CleanupStack::PopAndDestroy(2, string0);
+
+    User::LeaveIfError(iDataLdd.FinalizeInterface());
+    OstTraceFunctionExit1( CNCMCLIENTMANAGER_SETDATAINTERFACEL_EXIT, this );
+    }
+
+/**
+ * Setup the Class Descriptors
+ * @param aDataInterfaceNumber The interface number of the data class
+ * @return Error.
+ */
+TInt CNcmClientManager::SetupClassSpecificDescriptor(TUint8 aDataInterfaceNumber)
+    {
+    OstTraceFunctionEntryExt( CNCMCLIENTMANAGER_SETUPCLASSSPECIFICDESCRIPTOR_ENTRY, this );
+    
+    TInt res;
+
+    TNcmClassDescriptor descriptor;   
+
+    // Header Functional Descriptor- CDC spec table 15
+    descriptor.iHdrSize = 0x05;
+    descriptor.iHdrType = 0x24;
+    descriptor.iHdrSubType = 0x00;
+    descriptor.iHdrBcdCDC = 0x0120;
+
+    // Ethernet Networking Functional Descriptor-    ECM spec table 3
+    descriptor.iEthFunLength = 0x0D;
+    descriptor.iEthFunType = 0x24;
+    descriptor.iEthFunSubtype = 0x0F;
+    
+    // Generate the MAC address new NCM interface
+    res = SetMacAddressString(descriptor.iMACAddress);
+
+    if (res != KErrNone)
+        {
+        OstTraceFunctionExitExt( CNCMCLIENTMANAGER_SETUPCLASSSPECIFICDESCRIPTOR_EXIT, this, res );
+        return res;
+        }
+
+    descriptor.iEthernetStatistics = 0;
+    descriptor.iMaxSegmentSize = KEthernetFrameSize;
+    descriptor.iNumberMCFilters = 0;
+    descriptor.iNumberPowerFilters = 0;
+
+    // NCM Functional Descriptor-    NCM spec table 5-2
+    descriptor.iNcmFunLength = 0x06;
+    descriptor.iNcmFunType = 0x24;
+    descriptor.iNcmFunSubtype = 0x1A;
+    descriptor.iNcmVersion = 0x0100;
+    descriptor.iNetworkCapabilities = 0;
+
+    // Union functional descriptor- CDC spec table 16
+    descriptor.iUnSize = 0x05;
+    descriptor.iUnType = 0x24;
+    descriptor.iUnSubType = 0x06;
+    descriptor.iUnMasterInterface = 0;
+    descriptor.iUnSlaveInterface = aDataInterfaceNumber;
+
+    OstTrace0( TRACE_NORMAL, CNCMCLIENTMANAGER_SETUPCLASSSPECIFICDESCRIPTOR_PRE_SET_BLOCK, "About to call SetCSInterfaceDescriptorBlock" );
+    res = iCommLdd.SetCSInterfaceDescriptorBlock(0, descriptor.Des());
+    if (res != KErrNone)
+        {
+        OstTraceFunctionExitExt( CNCMCLIENTMANAGER_SETUPCLASSSPECIFICDESCRIPTOR_EXIT_DUP1, this, res );
+        return res;
+        }
+
+    OstTraceFunctionExitExt( CNCMCLIENTMANAGER_SETUPCLASSSPECIFICDESCRIPTOR_EXIT_DUP2, this, KErrNone );
+    return KErrNone;
+    }
+
+/**
+ * Set the MAC address string in descriptor
+ * @param aStrIndex the MAC address string index
+ */
+TInt CNcmClientManager::SetMacAddressString(TUint8& aStrIndex)
+    {
+    OstTraceFunctionEntryExt( CNCMCLIENTMANAGER_SETMACADDRESSSTRING_ENTRY, this );
+    
+    TBuf16<KMacAddrStringDescSize> str;
+    
+    // Search for MAC address string from index 0x10
+    aStrIndex = 0x10;
+
+    TInt ret = KErrNone;
+#ifndef OVERDUMMY_NCMCC
+    while (aStrIndex++ < 0xFF && ret != KErrNotFound)
+        {
+        ret = iDataLdd.GetStringDescriptor(aStrIndex, str);
+        }
+#endif // OVERDUMMY_NCMCC
+
+    if (aStrIndex < 0xFF)
+        {
+        TBuf8<KEthernetAddressLength*2> macAddrStr;
+        _LIT8(KMacAddressFormat, "%02X%02X%02X%02X%02X%02X");
+        OstTraceExt1(TRACE_NORMAL, CNCMCLIENTMANAGER_SETMACADDRESSSTRING, "The MAC address is %s", iHostMacAddress);
+        macAddrStr.AppendFormat(KMacAddressFormat, iHostMacAddress[0],
+                iHostMacAddress[1], iHostMacAddress[2], iHostMacAddress[3],
+                iHostMacAddress[4], iHostMacAddress[5]);
+        str.Copy(macAddrStr);
+        ret = iDataLdd.SetStringDescriptor(aStrIndex, str);
+        }
+    
+    OstTraceFunctionExitExt( CNCMCLIENTMANAGER_SETMACADDRESSSTRING_EXIT, this, ret );
+    return ret;
+    }
+
+/**
+ * Get NCM data interface number
+ * @param aInterfaceNumber NCM data interface number
+ * @return Error.
+ */
+TInt CNcmClientManager::DataInterfaceNumber(TUint8& aInterfaceNumber)
+    {
+    OstTraceFunctionEntryExt( CNCMCLIENTMANAGER_DATAINTERFACENUMBER_ENTRY, this );
+    
+    TInt interfaceSize = 0;
+
+    // 0 means the main interface in the LDD API
+    TInt res = iDataLdd.GetInterfaceDescriptorSize(0, interfaceSize);
+
+    if ( KErrNone == res )
+        {
+        OstTraceFunctionExitExt( CNCMCLIENTMANAGER_DATAINTERFACENUMBER_EXIT, this, res );
+        return res;
+        }
+
+    HBufC8* interfaceBuf = HBufC8::New(interfaceSize);
+    if ( !interfaceBuf )
+        {
+        OstTraceFunctionExitExt( CNCMCLIENTMANAGER_DATAINTERFACENUMBER_EXIT_DUP1, this, KErrNoMemory);
+        return KErrNoMemory;
+        }
+
+    TPtr8 interfacePtr = interfaceBuf->Des();
+    interfacePtr.SetLength(0);
+    // 0 means the main interface in the LDD API
+    res = iDataLdd.GetInterfaceDescriptor(0, interfacePtr); 
+
+    if ( KErrNone == res )
+        {
+        delete interfaceBuf;
+        OstTraceFunctionExitExt( CNCMCLIENTMANAGER_DATAINTERFACENUMBER_EXIT_DUP2, this, res );
+        return res;
+        }
+
+    OstTrace1(TRACE_NORMAL, CNCMCLIENTMANAGER_DATAINTERFACENUMBER_INTERFACE_INFO, "***Interface length =% d", interfacePtr.Length());
+    for ( TInt i = 0 ; i < interfacePtr.Length() ; i++ )
+        {
+        OstTrace1(TRACE_NORMAL, CNCMCLIENTMANAGER_DATAINTERFACENUMBER_INTERFACE_INFO2, "***** %x", interfacePtr[i]);
+        }
+
+    const TUint8* buffer = reinterpret_cast<const TUint8*>(interfacePtr.Ptr());
+    // 2 is where the interface number is, according to the LDD API
+    aInterfaceNumber = buffer[2];
+    OstTraceExt1(TRACE_NORMAL, CNCMCLIENTMANAGER_DATAINTERFACENUMBER, "Interface number = %hhu", aInterfaceNumber);
+
+    delete interfaceBuf;
+
+    OstTraceFunctionExitExt( CNCMCLIENTMANAGER_DATAINTERFACENUMBER_EXIT_DUP3, this, KErrNone );
+    return KErrNone;
+    }