diff -r 000000000000 -r a41df078684a userlibandfileserver/fileserver/shostmassstorage/server/protocol/tsbcclientinterface.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/userlibandfileserver/fileserver/shostmassstorage/server/protocol/tsbcclientinterface.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,290 @@ +// Copyright (c) 2008-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: +// + +/** + @file + @internalTechnology +*/ + +#include +#include +#include "msdebug.h" +#include "debug.h" +#include "msctypes.h" + +#include "mtransport.h" +#include "mprotocol.h" +#include "tscsiclientreq.h" + +#include "tblocktransfer.h" +#include "mscutils.h" +#include "usbmshostpanic.h" +#include "tscsiblockcmds.h" +#include "tsbcclientinterface.h" + +/** +Constructor. + +@param aTransport The Transport interface to be used +*/ +TSbcClientInterface::TSbcClientInterface(MTransport& aTransport) +: iTransport(aTransport) + { + __MSFNLOG + } + + +TSbcClientInterface::~TSbcClientInterface() + { + __MSFNLOG + } + + +/** +Constructor to create and send SCSI MODE SENSE (6) request to obtain the +medium's Write Protect status. The function leaves if the device response is not +compliant with the protocol standard. + +@param aPageCode The SCSI PAGE CODE value +@param aWriteProtected The SCSI WP value + +@return TInt KErrNone if successful, KErrCommandFailed to indicate a +device status error, KErrCommandStalled to indicate device stall +*/ +TInt TSbcClientInterface::ModeSense6L(TUint aPageCode, TBool& aWriteProtected) + { + __MSFNLOG + TScsiClientModeSense6Req modeSense6Req(TScsiClientModeSense6Req::ECurrentValues, + aPageCode); + TScsiClientModeSense6Resp modeSense6Resp; + TInt err = iTransport.SendControlCmdL(&modeSense6Req, &modeSense6Resp); + if (!err) + { + __SCSIPRINT1(_L("SCSI MODE SENSE (6) INFO WrProtect=%d"), + modeSense6Resp.iWriteProtected); + aWriteProtected = modeSense6Resp.iWriteProtected; + } + else + { + aWriteProtected = EFalse; + } + return err; + } + + +/** +Create and send SCSI MODE SENSE (10) request to obtain the mediums Write Protect +status. The function leaves if the device response is not compliant with the +protocol standard. + +@param aPageCode The SCSI PAGE CODE value +@param aWriteProtected The SCSI WP value + +@return TInt KErrNone if successful, KErrCommandFailed to indicate a +device status error, KErrCommandStalled to indicate a device stall +*/ +TInt TSbcClientInterface::ModeSense10L(TUint aPageCode, TBool& aWriteProtected) + { + __MSFNLOG + TScsiClientModeSense10Req modeSense10Req(TScsiClientModeSense10Req::ECurrentValues, + aPageCode); + TScsiClientModeSense10Resp modeSense10Resp; + TInt err = iTransport.SendControlCmdL(&modeSense10Req, &modeSense10Resp); + + if (!err) + { + __SCSIPRINT1(_L("SCSI MODE SENSE (10) INFO WrProtect=%d"), + modeSense10Resp.iWriteProtected); + aWriteProtected = modeSense10Resp.iWriteProtected; + } + else + { + aWriteProtected = EFalse; + } + return err; + } + + +/** +Constructor to create SCSI MODE SENSE (10) request. + +@param aPageControl The SCSI PAGE CODE value +@param aPageCode The SCSI WP value +@param aSubPageCode The SCSI SUB PAGE CODE value +*/ +TScsiClientModeSense10Req::TScsiClientModeSense10Req(TPageControl aPageControl, + TUint aPageCode, + TUint aSubPageCode) + : + TScsiClientReq(EModeSense10), + iPageControl(aPageControl), + iPageCode(aPageCode), + iSubPageCode(aSubPageCode), + iAllocationLength(KResponseLength) + { + __MSFNLOG + } + + +TInt TScsiClientModeSense10Req::EncodeRequestL(TDes8& aBuffer) const + { + __MSFNSLOG + __SCSIPRINT(_L("<-- SCSI MODE SENSE (10)")); + TInt length = TScsiClientReq::EncodeRequestL(aBuffer); + + // PC + aBuffer[2] = iPageCode; + aBuffer[2] |= iPageControl << 6; + aBuffer[3] = iSubPageCode; + + BigEndian::Put16(&aBuffer[7], iAllocationLength); + return length; + } + +/** +Create READ (10) request and send to the transport layer. This performs a +logical block read of the device server. The received data is appended into the +copy buffer. The function leaves if the device response is not compliant with +the protocol standard. +Note that TBlockTransfer must be initialised beforehand. + +@param aLba The Logical Block address to read from +@param aBuffer The buffer to copy data to +@param aLen The number of bytes to be read (IN) and returns the number of bytes +actually read (OUT) + +@return TInt KErrNone if successful otherwise KErrCommandFailed to indicate a +device status error or KErrArgument to indicate that aLen is too large for the +protocol. +*/ +TInt TSbcClientInterface::Read10L(TLba aLba, TDes8& aBuffer, TInt& aLen) + { + __MSFNLOG + __ASSERT_DEBUG(iBlockTransfer.BlockLength(), User::Panic(KUsbMsHostPanicCat, EBlockLengthNotSet)); + __ASSERT_DEBUG(aLen % iBlockTransfer.BlockLength() == 0, User::Panic(KUsbMsHostPanicCat, EBlockDevice)); + + TScsiClientRead10Req read10Req; + + read10Req.iLogicalBlockAddress = aLba; + + TInt blockTransferLength = aLen / iBlockTransfer.BlockLength(); + if (blockTransferLength > static_cast(KMaxTUint16)) + { + User::Leave(KErrArgument); + } + read10Req.iBlockTransferLength = static_cast(blockTransferLength); + TInt err = iTransport.SendDataRxCmdL(&read10Req, aBuffer, aLen); + return err; + } + +/** +Create READ CAPACITY (10) request and send to the transport layer. The request +returns the device servers capacity information. The device server's response +values are also used here to initialise the TBlockTransfer values. The function +leaves if the device response is not compliant with the protocol standard. + +@param aLba The Logical Block Address returned by the LU +@param aBlockSize The Block Size returned by the LU + +@return TInt KErrNone if successful, KErrCommandFailed to indicate a +device status error, KErrCommandStalled to indicate a device stall +*/ +TInt TSbcClientInterface::ReadCapacity10L(TLba& aLba, TUint32& aBlockSize) + { + __MSFNLOG + TScsiClientReadCapacity10Req capacity10Req; + TScsiClientReadCapacity10Resp capacity10Resp; + + TInt err = iTransport.SendControlCmdL(&capacity10Req, &capacity10Resp); + if (!err) + { + aLba = capacity10Resp.iLba; + aBlockSize = capacity10Resp.iBlockSize; + + __SCSIPRINT2(_L("Capacity LBA=0x%08x SIZE=0x%08x"), + aLba, aBlockSize); + + iBlockTransfer.SetCapacity(aBlockSize, aLba); + } + return err; + } + + +/** +Create START STOP UNIT request. The function leaves if the device response is +not compliant with the protocol standard. + +@param aStart SCSI START value + +@return TInt KErrNone if successful otherwise KErrCommandFailed to indicate a +device status error +*/ +TInt TSbcClientInterface::StartStopUnitL(TBool aStart) + { + __MSFNLOG + TScsiClientStartStopUnitReq startStopUnitReq; + + startStopUnitReq.iImmed = ETrue; + startStopUnitReq.iLoej = EFalse; + startStopUnitReq.iStart = aStart; + + TInt err = iTransport.SendControlCmdL(&startStopUnitReq); + + return err; + } + + +/** +Create WRITE (10) request and send to the transport layer. This performs a +logical block write of the device server. Note that TBlockTransfer must be +initialised beforehand. The function leaves if the device response is not +compliant with the protocol standard. + +@param aLba Logical Block Address to write the data to +@param aBuffer Buffer containing the data +@param aPos Offset into the buffer to the data +@param aLen The number of bytes to be written (IN) and returns the bytes +actually transferred (OUT) + +@return TInt KErrNone if successful otherwise KErrCommandFailed to indicate a +device status error or KErrArgument to indicate that aLen is too large for the +protocol. +*/ +TInt TSbcClientInterface::Write10L(TLba aLba, TDesC8& aBuffer, TUint aPos, TInt& aLen) + { + __MSFNLOG + __ASSERT_DEBUG(iBlockTransfer.BlockLength(), User::Panic(KUsbMsHostPanicCat, EBlockLengthNotSet)); + __ASSERT_DEBUG(aLen % iBlockTransfer.BlockLength() == 0, User::Panic(KUsbMsHostPanicCat, EBlockDevice)); + + // check that buffer size is large enough + if (aBuffer.Length() < (aPos + aLen)) + { + User::Leave(KErrArgument); + } + + TScsiClientWrite10Req write10Req; + write10Req.iLogicalBlockAddress = aLba; + + TInt blockTransferLength = aLen / iBlockTransfer.BlockLength(); + if (blockTransferLength > static_cast(KMaxTUint16)) + { + User::Leave(KErrArgument); + } + write10Req.iBlockTransferLength = static_cast(blockTransferLength); + + TInt err = iTransport.SendDataTxCmdL(&write10Req, aBuffer, aPos, aLen); + return err; + } +