kerneltest/f32test/shostmassstorage/msman/src/cusbmsmountmanager.cpp
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:29:07 +0100
changeset 30 8aab599e3476
parent 0 a41df078684a
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "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:
//

#include <f32file.h>
#include <d32usbdi_hubdriver.h>
#include <d32usbdi.h>
#include <d32otgdi.h>
#include <d32usbdescriptors.h>
#include <d32usbtransfers.h>

#include <shared.h>

#include "rusbhostmsdevice.h"

#include "rextfilesystem.h"
#include "usbtypes.h"
#include "cusbmsmountmanager.h"
#include "tmslog.h"
#include "debug.h"


CDevice* CDevice::NewL()
    {
    __MSFNSLOG
	CDevice* r = new (ELeave) CDevice();
	CleanupStack::PushL(r);

	r->ConstructL();
	CleanupStack::Pop();
	return r;
    }


void CDevice::ConstructL()
    {
    __MSFNLOG
    }


CDevice::CDevice()
    {
    __MSFNLOG
    }


CDevice::~CDevice()
    {
    __MSFNLOG
    __USBHOSTPRINT1(_L("~CDevice Token=%d"), iDeviceToken);
    }


TToken CDevice::OpenDeviceL(TUint aDeviceHandle, RUsbHubDriver& aHub)
    {
    __MSFNLOG
    __USBHOSTPRINT1(_L("CDevice::OpenDeviceL Handle=%d"), aDeviceHandle);

    TInt err = iUsbDevice.Open(aHub, aDeviceHandle);
    __USBHOSTPRINT1(_L(" - returned %d\n"), err);
    User::LeaveIfError(err);

    /* Retrieve the device descriptor */
    TUsbDeviceDescriptor devDescriptor;
    User::LeaveIfError(iUsbDevice.GetDeviceDescriptor(devDescriptor));
    iUsbPrint.PrintDescriptor(devDescriptor, 0, &iUsbDevice);

    iUsbPrint.PrintTree(devDescriptor);

    /* Retrieve the configuration descriptor */
    TUsbConfigurationDescriptor configDescriptor;
    User::LeaveIfError(iUsbDevice.GetConfigurationDescriptor(configDescriptor));
    iUsbPrint.PrintDescriptor(configDescriptor, 0, &iUsbDevice);

    /* Get the token for interface 0 */
    TUint32 token;
    err = iUsbDevice.GetTokenForInterface(0, token);
    __USBHOSTPRINT2(_L("RUsbDevice::GetTokenForInterface returned error %d, token %08x"), err, token);
    User::LeaveIfError(err);

    /* open the interface */
    RUsbInterface interface_ep0;
    err = interface_ep0.Open(token);
    __USBHOSTPRINT1(_L("RUsbInterface::Open returned error %d"), err);
    User::LeaveIfError(err);

    /* Retrieve the interface and device descriptors */
    TUsbInterfaceDescriptor ifDescriptor;
    User::LeaveIfError(interface_ep0.GetInterfaceDescriptor(ifDescriptor));
    iUsbPrint.PrintDescriptor(ifDescriptor);

    if (!IsDeviceMassStorage(ifDescriptor, devDescriptor))
        {
        RDebug::Print(_L("ATTACHED DEVICE IS NOT A MASS STORAGE DEVICE!\n"));
        User::Leave(KErrGeneral);
        }

	TUint8 iProtocolId = ifDescriptor.InterfaceSubClass();
	TUint8 iTransportId = ifDescriptor.InterfaceProtocol();

    interface_ep0.Close();

    THostMassStorageConfig msConfig;
    msConfig.iInterfaceToken = token;
	msConfig.iProtocolId =iProtocolId;
	msConfig.iTransportId = iTransportId;
	msConfig.iStatusPollingInterval = 10; // 10 secs

    TUint32 numLun;

    TRequestStatus status;
    iUsbHostMsDevice.Add(msConfig, status);
	User::WaitForRequest(status);
	if (status.Int() != KErrNone)
        {
		__USBHOSTPRINT(_L("Add device failed"));
		User::Leave(status.Int());
        }
	TInt r = iUsbHostMsDevice.GetNumLun(numLun);
	if (r != KErrNone)
        {
		__USBHOSTPRINT(_L("GetNumLun failed"));
		User::Leave(r);
        }

    if (numLun > KMaxLun)
        {
        __USBHOSTPRINT1(_L("Device MaxLun = %d. Error MaxLun > MAXLUN !"), numLun);
        User::Leave(KErrGeneral);
        }

    __USBHOSTPRINT1(_L("MSC registered with %d Luns"), numLun);

    iDeviceToken = token;
    iNumLuns = numLun;
    iDeviceHandle = aDeviceHandle;
    return token;
    }


void CDevice::CloseDeviceL()
    {
    __MSFNLOG

    THostMassStorageConfig msConfig;
    msConfig.iInterfaceToken = iDeviceToken;

    iUsbHostMsDevice.Remove();
    iUsbDevice.Close();
    }


void CDevice::MountLogicalUnitsL()
    {
    __MSFNLOG
    iExt.OpenL();

    for (TInt lun = 0; lun < iNumLuns; lun++)
        {
        TDriveNumber driveNumber = iExt.GetDriveL();
        __PRINT2(_L("Mounting drive=%d lun=%d..."), driveNumber, lun);
        RDebug::Print(_L("Mounting drive=%d lun=%d..."), driveNumber, lun);
        TRAPD(err, iExt.MountL(iUsbHostMsDevice, driveNumber, iDeviceToken, lun));
        if (err == KErrNone || err == KErrNotReady || err == KErrCorrupt)
            {
            iLuList.Append(driveNumber);
            }
        __PRINT1(_L("%d"), err);
        RDebug::Print(_L("err=%d"), err);
        }
    }


void CDevice::DismountLogicalUnitsL()
    {
    __MSFNLOG
    for (TInt lun = 0; lun < iLuList.Count(); lun++)
        {
        TDriveNumber driveNumber = iLuList[lun];
        iExt.DismountL(iUsbHostMsDevice, driveNumber);
        }
    iLuList.Reset();

    iExt.CloseL();
    }


TInt CDevice::GetEndpointAddress(RUsbInterface& aUsbInterface,
                                 TInt aInterfaceSetting,
                                 TUint8 aTransferType,
                                 TUint8 aDirection,
                                 TInt& aEndpointAddress) const
	{
    __MSFNSLOG

	// Get the interface descriptor
	RDebug::Print(_L("GetEndpointAddress : Getting the interface descriptor for this alternate setting"));

	TUsbInterfaceDescriptor alternateInterfaceDescriptor;
	TInt err = aUsbInterface.GetAlternateInterfaceDescriptor(aInterfaceSetting, alternateInterfaceDescriptor);

	if (err)
		{
		RDebug::Print(_L("GetEndpointAddress : <Error %d> Unable to get alternate interface (%d) descriptor"),err,aInterfaceSetting);
		return err;
		}

	// Parse the descriptor tree from the interface
	RDebug::Print(_L("Search the child descriptors for matching endpoint attributes"));

	TUsbGenericDescriptor* descriptor = alternateInterfaceDescriptor.iFirstChild;

	while (descriptor)
		{
		RDebug::Print(_L("GetEndpointAddress : Check descriptor type for endpoint"));

		// Cast the descriptor to an endpoint descriptor
		TUsbEndpointDescriptor* endpoint = TUsbEndpointDescriptor::Cast(descriptor);

		if (endpoint)
			{
			RDebug::Print(_L("GetEndpointAddress : Match attributes for transfer type"));

			if ( (endpoint->Attributes() & aTransferType) == aTransferType)
				{
				RDebug::Print(_L("GetEndpointAddress : Match attributes for endpoint direction"));

				if ( (endpoint->EndpointAddress() & 0x80) == aDirection)
					{
					aEndpointAddress = endpoint->EndpointAddress();
					RDebug::Print(_L("GetEndpointAddress : Endpoint address found"));
					return KErrNone;
					}
				}
			}

		descriptor = descriptor->iNextPeer;
		}

	// Unable to find the endpoint address
	RDebug::Print(_L("GetEndpointAddress : Unable to find endpoint address matching the specified attributes"));

	return KErrNotFound;
	}


TBool CDevice::IsDeviceMassStorage(const TUsbInterfaceDescriptor& aInterfaceDesc,
                                   const TUsbDeviceDescriptor& aDeviceDesc) const
    {
    __MSFNSLOG
	/* check the interface descriptor */
	if(aInterfaceDesc.InterfaceClass() == 0x08 &&
		aInterfaceDesc.InterfaceSubClass() == 0x06 &&
		aInterfaceDesc.InterfaceProtocol() == 0x50)
        {
		if(aDeviceDesc.DeviceClass() == 0x00 &&
			aDeviceDesc.DeviceSubClass() == 0x00 &&
			aDeviceDesc.DeviceProtocol() == 0x00)
			return ETrue;
        }

	return EFalse;

    }


TLun CDevice::DriveMap(TDriveMap& aDriveMap) const
    {
    __MSFNSLOG
    TDriveNumber driveNumber;
    RDebug::Printf("LuList.Count=%d", iLuList.Count());
    for (TInt i = 0; i < iLuList.Count(); i++)
        {
        driveNumber = iLuList[i];
        aDriveMap[driveNumber] = iDeviceToken;
        RDebug::Printf("Device %d token=%d driveNumber=%d", i, iDeviceToken, driveNumber);
        }

    return iNumLuns;
    }


TLun CDevice::DeviceMap(TDeviceMap& aDeviceMap) const
    {
    __MSFNSLOG
    TDriveNumber driveNumber;
    RDebug::Printf("LuList.Count=%d", iLuList.Count());
    for (TInt i = 0; i < iLuList.Count(); i++)
        {
        driveNumber = iLuList[i];
        aDeviceMap[i] = driveNumber;
        RDebug::Printf("CDevice LUN=%d driveNumber=%d", i, driveNumber);
        }

    return iNumLuns;
    }


CUsbMsMountManager* CUsbMsMountManager::NewL()
    {
    __MSFNSLOG
	CUsbMsMountManager* r = new (ELeave) CUsbMsMountManager();
	CleanupStack::PushL(r);

	r->ConstructL();
	CleanupStack::Pop();
	return r;
    }


void CUsbMsMountManager::ConstructL()
    {
    __MSFNLOG
    }


CUsbMsMountManager::CUsbMsMountManager()
    {
    __MSFNLOG
    }


CUsbMsMountManager::~CUsbMsMountManager()
    {
    __MSFNLOG
    iDeviceList.ResetAndDestroy();
    }


// adds new entry for this device
void CUsbMsMountManager::AddDeviceL(CDevice* aDevice)
    {
    __MSFNLOG
    iDeviceList.Append(aDevice);
    }


CDevice* CUsbMsMountManager::RemoveDeviceL(TUint aDeviceHandle)
    {
    __MSFNLOG
	TInt index = GetHandleIndexL(aDeviceHandle);
	CDevice* device = iDeviceList[index];
    iDeviceList.Remove(index);
    return device;
    }

void CUsbMsMountManager::CloseAllDevicesL()
    {
    __MSFNLOG
    for (TInt i = 0; i < iDeviceList.Count(); i++)
        {
        iDeviceList[i]->CloseDeviceL();
        }
    }


TInt CUsbMsMountManager::GetDeviceIndexL(TToken aDeviceToken) const
    {
    __MSFNSLOG
    TInt index;
    for (index = 0; index < iDeviceList.Count(); index++)
        {
        if (aDeviceToken == iDeviceList[index]->DeviceToken())
            {
            break;
            }
        }

    if (index == iDeviceList.Count())
        {
        User::Leave(KErrNotFound);
        }

    return index;
    }


TInt CUsbMsMountManager::GetHandleIndexL(TUint aDeviceHandle) const
    {
    __MSFNSLOG
    TInt index;
    for (index = 0; index < iDeviceList.Count(); index++)
        {
        if (aDeviceHandle == iDeviceList[index]->DeviceHandle())
            {
            break;
            }
        }

    if (index == iDeviceList.Count())
        {
        User::Leave(KErrNotFound);
        }

    return index;
    }



// mounts all LUNs for the device
void CUsbMsMountManager::MountDeviceL(TUint aDeviceHandle)
    {
    __MSFNLOG
    TInt index = GetHandleIndexL(aDeviceHandle);
    iDeviceList[index]->MountLogicalUnitsL();
    }



// dismount all LUNs for this device
void CUsbMsMountManager::DismountDeviceL(TUint aDeviceHandle)
    {
    __MSFNLOG
    TInt index = GetHandleIndexL(aDeviceHandle);
    iDeviceList[index]->DismountLogicalUnitsL();
    }


// dismount all LUNs
void CUsbMsMountManager::DismountL()
    {
    __MSFNLOG
    for (TInt i = 0; i < iDeviceList.Count(); i++)
        {
        iDeviceList[i]->DismountLogicalUnitsL();
        }
    }


void CUsbMsMountManager::DriveMap(TDriveMap& aDriveMap) const
    {
    __MSFNSLOG
    TInt maxLun = 0;
    RDebug::Printf("DeviceList.Count=%d", iDeviceList.Count());
    for (TInt i = 0; i < iDeviceList.Count(); i++)
        {
        maxLun = iDeviceList[i]->DriveMap(aDriveMap);
        RDebug::Printf("%d %d", i, maxLun);
        }
    }


void CUsbMsMountManager::DeviceMap(TInt aDeviceIndex, TDeviceMap& aDeviceMap) const
    {
    __MSFNSLOG
    RDebug::Printf("Device=%d", aDeviceIndex);

    __ASSERT_DEBUG(aDeviceIndex < iDeviceList.Count(), User::Invariant());
    iDeviceList[aDeviceIndex]->DeviceMap(aDeviceMap);
    }



TUsbPrint::TUsbPrint()
:   iDebug(EFalse)
    {
    }

void TUsbPrint::PrintTree(const TUsbGenericDescriptor& aDesc, TInt aDepth)
	{
    if (!iDebug)
        {
        return;
        }

	TBuf<20> buf;
	for(TInt depth=aDepth;depth>=0;--depth)
		{
		buf.Append(_L("  "));
		}
	if(aDesc.iRecognisedAndParsed == TUsbGenericDescriptor::ERecognised)
		{
		RDebug::Print(_L("%S+0x%08x - %d 0x%02x"), &buf, &aDesc, aDesc.ibLength, aDesc.ibDescriptorType);
		}
	else
		{
		RDebug::Print(_L("%S-0x%08x - %d 0x%02x"), &buf, &aDesc, aDesc.ibLength, aDesc.ibDescriptorType);
		}
	HBufC* blob = HBufC::New(5*aDesc.iBlob.Length()); // 5* for " 0x" + 2*bytes for hex representation
	if(blob)
		{
		for(TInt i=0;i<aDesc.iBlob.Length();++i)
			{
			blob->Des().AppendFormat(_L("0x%02x "), aDesc.iBlob[i]);
			}
		RDebug::Print(_L("%S >%S"), &buf, blob);
		delete blob;
		}
	if(aDesc.iFirstChild)
		{
		RDebug::Print(_L("%S \\ "), &buf);
		PrintTree(*(aDesc.iFirstChild), aDepth+1);
		RDebug::Print(_L("%S / "), &buf);
		}
	if(aDesc.iNextPeer)
		{
		PrintTree(*(aDesc.iNextPeer), aDepth);
		}
	}


static TUint16 gLangId = 0x0000;

void TUsbPrint::SetLanguageToPrintL(RUsbDevice& aDevice)
	{
    if (!iDebug) return;

	// Try to set language to US Eng, otherwise take the first one listed.
	if(gLangId == 0x0000) // Only make the request if not been made before.
		{
		// Get string descriptor 0.
		TBuf8<256> stringBuf;
		TUsbStringDescriptor* stringDesc = NULL;
		User::LeaveIfError(aDevice.GetStringDescriptor(stringDesc, stringBuf, 0));
		CleanupStack::PushL(*stringDesc);

		// Search for US English
		TBool usEngLang = EFalse;
		TInt langId = 0;
		TInt index = 0;
		const TUint16 KLangIdUsEng = 0x0409;
		while(!usEngLang && langId != KErrNotFound)
			{
			langId = stringDesc->GetLangId(index);
			usEngLang = (langId == KLangIdUsEng);
			index++;
			}

		// Set the language appropriately
		if(usEngLang)
			{
        	gLangId = KLangIdUsEng;
			}
		else
			{
			gLangId = stringDesc->GetLangId(0);
			}

		CleanupStack::PopAndDestroy(); // stringDesc
		}
	}


void TUsbPrint::PrintStringFromIndex(const TDesC& aFormatString,
                                     TInt aIndex,
                                     RUsbDevice* aDevice)
	{
    if (!iDebug) return;

	// If we have no device handle, we cannot go and get any strings.
	// If we have index 0, this indicates we don't have a string for this entry.
	if(aDevice && aIndex != 0)
		{
		TRAPD(err, SetLanguageToPrintL(*aDevice));
		if(err == KErrNone)
			{
			TBuf8<255> stringBuf;
			TUsbStringDescriptor* stringDesc = NULL;
			err = aDevice->GetStringDescriptor(stringDesc, stringBuf, aIndex, gLangId);
			if(err == KErrNone)
				{
				TBuf<128> buf;
				stringDesc->StringData(buf);
				RDebug::Print(aFormatString, &buf);
				stringDesc->DestroyTree();
				}
			delete stringDesc;
			}
		else
			{
			RDebug::Print(_L("Error while Selecting Langauge %d\n"), err);
			}
		}
	}


void TUsbPrint::PrintDescriptor(const TUsbDeviceDescriptor& aDeviceDesc,
                                TInt /*aVariant*/,
                                RUsbDevice* aDevice)
	{
    if (!iDebug) return;

	RDebug::Print(_L("USBBcd = 0x%04x\n"), aDeviceDesc.USBBcd());
	RDebug::Print(_L("DeviceClass = 0x%02x\n"), aDeviceDesc.DeviceClass());
	RDebug::Print(_L("DeviceSubClass = 0x%02x\n"), aDeviceDesc.DeviceSubClass());
	RDebug::Print(_L("DeviceProtocol = 0x%02x\n"), aDeviceDesc.DeviceProtocol());
	RDebug::Print(_L("MaxPacketSize0 = 0x%02x\n"), aDeviceDesc.MaxPacketSize0());
	RDebug::Print(_L("VendorId = 0x%04x\n"), aDeviceDesc.VendorId());
	RDebug::Print(_L("ProductId = 0x%04x\n"), aDeviceDesc.ProductId());
	RDebug::Print(_L("DeviceBcd = 0x%04x\n"), aDeviceDesc.DeviceBcd());
	RDebug::Print(_L("ManufacturerIndex = 0x%02x\n"), aDeviceDesc.ManufacturerIndex());
	PrintStringFromIndex(_L("ManufacturerString = %S\n"), aDeviceDesc.ManufacturerIndex(), aDevice);
	RDebug::Print(_L("ProductIndex = 0x%02x\n"), aDeviceDesc.ProductIndex());
	PrintStringFromIndex(_L("ProductString = %S\n"), aDeviceDesc.ProductIndex(), aDevice);
	RDebug::Print(_L("SerialNumberIndex = 0x%02x\n"), aDeviceDesc.SerialNumberIndex());
	PrintStringFromIndex(_L("SerialNumberString = %S\n"), aDeviceDesc.SerialNumberIndex(), aDevice);
	RDebug::Print(_L("NumConfigurations = 0x%02x\n"), aDeviceDesc.NumConfigurations());
	}


void TUsbPrint::PrintDescriptor(const TUsbConfigurationDescriptor& aConfigDesc,
                                TInt /*aVariant*/,
                                RUsbDevice* aDevice)
	{
    if (!iDebug) return;
	RDebug::Print(_L("TotalLength = 0x%04x\n"), aConfigDesc.TotalLength());
	RDebug::Print(_L("NumInterfaces = 0x%02x\n"), aConfigDesc.NumInterfaces());
	RDebug::Print(_L("ConfigurationValue = 0x%02x\n"), aConfigDesc.ConfigurationValue());
	RDebug::Print(_L("ConfigurationIndex = 0x%02x\n"), aConfigDesc.ConfigurationIndex());
	PrintStringFromIndex(_L("ConfigurationString = %S\n"), aConfigDesc.ConfigurationIndex(), aDevice);
	RDebug::Print(_L("Attributes = 0x%02x\n"), aConfigDesc.Attributes());
	RDebug::Print(_L("MaxPower = 0x%02x\n"), aConfigDesc.MaxPower());
	}


void TUsbPrint::PrintDescriptor(const TUsbEndpointDescriptor& aEndpointDesc,
                                TInt /*aVariant*/,
                                RUsbDevice* /*aDevice*/)
	{
    if (!iDebug) return;
	RDebug::Print(_L("EndpointAddress = 0x%02x\n"), aEndpointDesc.EndpointAddress());
	RDebug::Print(_L("Attributes = 0x%02x\n"), aEndpointDesc.Attributes());
	RDebug::Print(_L("MaxPacketSize = 0x%04x\n"), aEndpointDesc.MaxPacketSize());
	RDebug::Print(_L("Interval = 0x%02x\n"), aEndpointDesc.Interval());
	}


void TUsbPrint::PrintDescriptor(const TUsbInterfaceDescriptor& aInterfaceDesc,
                                TInt /*aVariant*/,
                                RUsbDevice* /*aDevice*/)
	{
    if (!iDebug) return;
	RDebug::Print(_L("InterfaceNumber = 0x%02x\n"), aInterfaceDesc.InterfaceNumber());
	RDebug::Print(_L("AlternateSetting = 0x%02x\n"), aInterfaceDesc.AlternateSetting());
	RDebug::Print(_L("NumEndpoints = 0x%02x\n"), aInterfaceDesc.NumEndpoints());
	RDebug::Print(_L("InterfaceClass = 0x%02x\n"), aInterfaceDesc.InterfaceClass());
	RDebug::Print(_L("InterfaceSubClass = 0x%02x\n"), aInterfaceDesc.InterfaceSubClass());
	RDebug::Print(_L("InterfaceProtocol = 0x%02x\n"), aInterfaceDesc.InterfaceProtocol());
	RDebug::Print(_L("Interface = 0x%02x\n"), aInterfaceDesc.Interface());
	}


void TUsbPrint::PrintDescriptor(const TUsbStringDescriptor& aStringDesc,
                                TInt aVariant,
                                RUsbDevice* /*aDevice*/)
	{
    if (!iDebug) return;
	if(aVariant == 0)
		{
		RDebug::Print(_L("String Descriptor Zero\n"));
		TInt index = 0;
		TInt langId = 0;
		while((langId = aStringDesc.GetLangId(index)) != KErrNotFound)
			{
			RDebug::Print(_L("  >0x%04x\n"), langId);
			++index;
			}
		}
	else
		{
		RDebug::Print(_L("Generic String Descriptor\n"));
		HBufC16* string = HBufC16::New(128);
		if(string)
			{
			TPtr16 stringPtr = string->Des();
			aStringDesc.StringData(stringPtr);
			RDebug::Print(_L("  >%S\n"), string);
			}
		delete string;
		}
	}