--- /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;
+ }