sl@0: // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // f32test\testusbcldd\src\misc.cpp sl@0: // sl@0: // sl@0: sl@0: #include "dtestusblogdev.h" sl@0: sl@0: TUsbcInterface::TUsbcInterface(TUsbcInterfaceSet* aIfcSet, TUint8 aSetting) sl@0: : iEndpoints(2), iInterfaceSet(aIfcSet), iSettingCode(aSetting) sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcInterface::TUsbcInterface()"))); sl@0: } sl@0: sl@0: sl@0: TUsbcInterface::~TUsbcInterface() sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcInterface::~TUsbcInterface()"))); sl@0: iEndpoints.ResetAndDestroy(); sl@0: } sl@0: sl@0: sl@0: TUsbcInterfaceSet::TUsbcInterfaceSet(const DBase* aClientId, TUint8 aIfcNum) sl@0: : iInterfaces(2), iClientId(aClientId), iInterfaceNumber(aIfcNum), iCurrentInterface(0) sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcInterfaceSet::TUsbcInterfaceSet()"))); sl@0: } sl@0: sl@0: sl@0: TUsbcInterfaceSet::~TUsbcInterfaceSet() sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcInterfaceSet::~TUsbcInterfaceSet()"))); sl@0: iInterfaces.ResetAndDestroy(); sl@0: } sl@0: sl@0: const TUsbcInterface* TUsbcInterfaceSet::CurrentInterface() const sl@0: /** Returns a pointer to the currently selected (active) setting of this interface. sl@0: sl@0: @return A pointer to the currently selected (active) setting of this interface. sl@0: */ sl@0: { sl@0: return iInterfaces[iCurrentInterface]; sl@0: } sl@0: sl@0: sl@0: TUsbcInterface* TUsbcInterfaceSet::CurrentInterface() sl@0: /** Returns a pointer to the currently selected (active) setting of this interface. sl@0: sl@0: @return A pointer to the currently selected (active) setting of this interface. sl@0: */ sl@0: { sl@0: return iInterfaces[iCurrentInterface]; sl@0: } sl@0: sl@0: TUsbcLogicalEndpoint::TUsbcLogicalEndpoint(TUint aEndpointNum, const TUsbcEndpointInfo& aInfo, sl@0: TUsbcInterface* aInterface) sl@0: : iLEndpointNum(aEndpointNum), iInfo(aInfo), iInterface(aInterface) sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcLogicalEndpoint::TUsbcLogicalEndpoint()"))); sl@0: } sl@0: sl@0: sl@0: TUsbcLogicalEndpoint::~TUsbcLogicalEndpoint() sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcLogicalEndpoint::~TUsbcLogicalEndpoint: #%d"), iLEndpointNum)); sl@0: } sl@0: sl@0: DTestUsbcEndpoint::DTestUsbcEndpoint() sl@0: { sl@0: } sl@0: sl@0: DTestUsbcEndpoint::~DTestUsbcEndpoint() sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Deleting buffer 0x%x"), iBuffer)); sl@0: delete iBuffer; sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Buffer deleted"))); sl@0: } sl@0: sl@0: TInt DTestUsbcEndpoint::Create(const TUsbcEndpointCaps& aCaps) sl@0: { sl@0: iCaps = aCaps; sl@0: if (iBuffer == NULL) sl@0: { sl@0: __NEWPLATBUF(iBuffer, KEndpointBufferSize); sl@0: if (iBuffer == NULL) sl@0: return KErrNoMemory; sl@0: } sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Allocated buffer 0x%x"), iBuffer)); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void DTestUsbcEndpoint::DoCancel() sl@0: { sl@0: if (iRequestPending) sl@0: { sl@0: //Cancel client request sl@0: iRequestPending = EFalse; sl@0: Kern::RequestComplete(iClient, iClientStatus, KErrCancel); sl@0: } sl@0: if (iHostRequestPending) sl@0: { sl@0: //Cancel host request sl@0: iHostRequestPending = EFalse; sl@0: Kern::RequestComplete(iHost, iHostStatus, KErrCancel); sl@0: } sl@0: } sl@0: sl@0: TInt DTestUsbcEndpoint::NewRequest(DThread* aClient, TRequestStatus* aStatus, sl@0: TEndpointTransferInfo& aInfo, TTransferType aType) sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("DTestUsbcEndpoint::NewRequest"))); sl@0: //Only supports one request pending per endpoint sl@0: if (iRequestPending) sl@0: { sl@0: return ERequestAlreadyPending; sl@0: } sl@0: iClient = aClient; sl@0: iClientStatus = aStatus; sl@0: iClientTransferInfo = aInfo; sl@0: iDataTransferred = 0; sl@0: iRequestPending = ETrue; sl@0: iRequestType = aType; sl@0: sl@0: //Copy data to local buffer if this is a write request sl@0: if (iRequestType == ETransferTypeWrite) sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Write request"))); sl@0: TInt err; sl@0: __THREADREADPLATBUF(aClient, iClientTransferInfo.iDes, iBuffer, err); sl@0: if (err != KErrNone) sl@0: { sl@0: iRequestPending = EFalse; sl@0: return err; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Read request"))); sl@0: } sl@0: sl@0: if (iHostRequestPending) sl@0: { sl@0: TryToComplete(); sl@0: } sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt DTestUsbcEndpoint::NewHostRequest(DThread* aHost, TRequestStatus* aStatus, sl@0: TEndpointTransferInfo& aInfo, TTransferType aType) sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("DTestUsbcEndpoint::NewHostRequest"))); sl@0: //Only supports one request pending per endpoint sl@0: if (iHostRequestPending) sl@0: { sl@0: return ERequestAlreadyPending; sl@0: } sl@0: iHost = aHost; sl@0: iHostStatus = aStatus; sl@0: iHostTransferInfo = aInfo; sl@0: iHostDataTransferred = 0; sl@0: iHostRequestPending = ETrue; sl@0: iHostRequestType = aType; sl@0: sl@0: //Copy data to local buffer if this is a write request sl@0: if (iHostRequestType == ETransferTypeWrite) sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Write request"))); sl@0: TInt err; sl@0: __THREADREADPLATBUF(aHost, iHostTransferInfo.iDes, iBuffer, err); sl@0: if (err != KErrNone) sl@0: { sl@0: iRequestPending = EFalse; sl@0: return err; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Read request"))); sl@0: } sl@0: sl@0: if (iRequestPending) sl@0: { sl@0: TryToComplete(); sl@0: } sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt DTestUsbcEndpoint::TryToComplete() sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("DTestUsbcEndpoint::TryToComplete"))); sl@0: TInt err = KErrNone; sl@0: TInt len = iHostTransferInfo.iTransferSize - iHostDataTransferred; sl@0: sl@0: if (SupportsDir(KUsbEpDirBidirect)) sl@0: { sl@0: //Make sure host and client transfer types don't conflict sl@0: if (iRequestType == iHostRequestType) sl@0: { sl@0: iRequestPending = EFalse; sl@0: iHostRequestPending = EFalse; sl@0: Kern::RequestComplete(iClient, iClientStatus, KErrUsbEpBadDirection); sl@0: Kern::RequestComplete(iHost, iHostStatus, KErrUsbEpBadDirection); sl@0: return KErrUsbEpBadDirection; sl@0: } sl@0: } sl@0: sl@0: if (SupportsDir(KUsbEpDirIn) || (SupportsDir(KUsbEpDirBidirect) && iRequestType == ETransferTypeWrite)) sl@0: { sl@0: err = CopyData(iDataTransferred, iHost, iHostTransferInfo.iDes, iHostDataTransferred, len); sl@0: } sl@0: else if (SupportsDir(KUsbEpDirOut) || (SupportsDir(KUsbEpDirBidirect) && iRequestType == ETransferTypeReadData)) sl@0: { sl@0: err = CopyData(iHostDataTransferred, iClient, iClientTransferInfo.iDes, iDataTransferred, len); sl@0: } sl@0: else sl@0: { sl@0: err = KErrNotSupported; sl@0: } sl@0: sl@0: if (err != KErrNone) sl@0: { sl@0: //Problems copying data. Complete requests with error and return. sl@0: iRequestPending = EFalse; sl@0: iHostRequestPending = EFalse; sl@0: Kern::RequestComplete(iClient, iClientStatus, err); sl@0: Kern::RequestComplete(iHost, iHostStatus, err); sl@0: return err; sl@0: } sl@0: iDataTransferred += len; sl@0: iHostDataTransferred += len; sl@0: sl@0: iRequestPending = EFalse; sl@0: Kern::RequestComplete(iClient, iClientStatus, KErrNone); sl@0: iHostRequestPending = EFalse; sl@0: Kern::RequestComplete(iHost, iHostStatus, KErrNone); sl@0: return KErrNone; sl@0: } sl@0: sl@0: /** sl@0: Copies data from a source descriptor to a destination descriptor, both in user space. sl@0: sl@0: @param aSrcClient The thread that owns the source descriptor sl@0: @param aSrc Pointer to the source descriptor sl@0: @param aSrcOffset Offset in aSrc from where to start reading data sl@0: @param aDestClient The thread that owns the destination descriptor sl@0: @param aDest Pointer to the destination descriptor sl@0: @param aDestOffset Offset in aDest from where to start writing data sl@0: @param aLen Amount of bytes to copy sl@0: @return KErrNone is successful, otherwise a standard Symbian error code sl@0: */ sl@0: TInt DTestUsbcEndpoint::CopyData(TInt aSrcOffset, DThread* aDestClient, TDesC8* aDest, sl@0: TInt aDestOffset, TInt aLen) sl@0: { sl@0: TInt err; sl@0: sl@0: // Get the descriptor length in the client's context. sl@0: TInt rxLen[2] = {0,0}; sl@0: err=Kern::ThreadRawRead(aDestClient,aDest,&rxLen,sizeof(rxLen)); sl@0: if (err!=KErrNone) sl@0: return err; sl@0: sl@0: // copy mo more than max number of chars in receive buffer sl@0: aLen = Min(aLen, rxLen[1]); sl@0: sl@0: while(aLen > 0) sl@0: { sl@0: TInt len = iBuffer->Length() - aSrcOffset; sl@0: //Make sure we only copy aLen bytes, no more sl@0: if (len > aLen) sl@0: { sl@0: len = aLen; sl@0: } sl@0: TPtrC8 src(iBuffer->Ptr() + aSrcOffset, len); sl@0: err = __THREADWRITEOFFSET(aDestClient, aDest, src, aDestOffset); sl@0: if (err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: aLen -= len; sl@0: aSrcOffset += len; sl@0: aDestOffset += len; sl@0: } sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt DTestUsbcEndpoint::Halt() sl@0: { sl@0: iHalted = ETrue; sl@0: if (iNotifyHost != NULL) sl@0: { sl@0: Kern::RequestComplete(iNotifyHost, iHostNotifyStatus, KErrNone); sl@0: iNotifyHost = NULL; sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt DTestUsbcEndpoint::Clear() sl@0: { sl@0: iHalted = EFalse; sl@0: if (iRequestPending) sl@0: { sl@0: iRequestPending = EFalse; sl@0: Kern::RequestComplete(iClient, iClientStatus, KErrNone); sl@0: } sl@0: if (iHostRequestPending) sl@0: { sl@0: iHostRequestPending = EFalse; sl@0: Kern::RequestComplete(iHost, iHostStatus, KErrNone); sl@0: } sl@0: if (iClearCallback != NULL) sl@0: { sl@0: iClearCallback->EndpointStatusNotifyCallback(); sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: void DTestUsbcEndpoint::SetClearCallback(DLddTestUsbcChannel* aCallback) sl@0: { sl@0: iClearCallback = aCallback; sl@0: } sl@0: sl@0: TBool DTestUsbcEndpoint::IsHalted() sl@0: { sl@0: return iHalted; sl@0: } sl@0: sl@0: TInt DTestUsbcEndpoint::HostStatusNotify(DThread* aHost, TRequestStatus* aStatus) sl@0: { sl@0: const TRequestStatus s(KRequestPending); sl@0: __THREADRAWWRITE(aHost, aStatus, (TUint8*)&s, (TInt)sizeof(TRequestStatus)); sl@0: iNotifyHost = aHost; sl@0: iHostNotifyStatus = aStatus; sl@0: return KErrNone; sl@0: } sl@0: sl@0: TBool DTestUsbcEndpoint::SupportsDir(TUint aDir) sl@0: { sl@0: if ((iCaps.iTypesAndDir & aDir) == aDir) sl@0: { sl@0: return ETrue; sl@0: } sl@0: return EFalse; sl@0: } sl@0: sl@0: TBool DTestUsbcEndpoint::EndpointSuitable(const TUsbcEndpointInfo& aInfo) sl@0: { sl@0: return (!iReserve && sl@0: (iCaps.iSizes == (TUint)aInfo.iSize) && sl@0: ((iCaps.iTypesAndDir & aInfo.iDir) == aInfo.iDir) && sl@0: ((iCaps.iTypesAndDir & aInfo.iType) == aInfo.iType)); sl@0: } sl@0: