os/kernelhwsrv/userlibandfileserver/fileserver/shostmassstorage/server/protocol/tsbcclientinterface.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 /**
    17  @file
    18  @internalTechnology
    19 */
    20 
    21 #include <e32base.h>
    22 
    23 #include "msdebug.h"
    24 #include "debug.h"
    25 #include "msctypes.h"
    26 
    27 #include "mtransport.h"
    28 #include "mprotocol.h"
    29 #include "tscsiclientreq.h"
    30 
    31 #include "tblocktransfer.h"
    32 #include "mscutils.h"
    33 #include "usbmshostpanic.h"
    34 #include "tscsiblockcmds.h"
    35 #include "tsbcclientinterface.h"
    36 
    37 /**
    38 Constructor.
    39 
    40 @param aTransport The Transport interface to be used
    41 */
    42 TSbcClientInterface::TSbcClientInterface(MTransport& aTransport)
    43 :   iTransport(aTransport)
    44     {
    45     __MSFNLOG
    46     }
    47 
    48 
    49 TSbcClientInterface::~TSbcClientInterface()
    50     {
    51     __MSFNLOG
    52     }
    53 
    54 
    55 /**
    56 Constructor to create and send SCSI MODE SENSE (6) request to obtain the
    57 medium's Write Protect status. The function leaves if the device response is not
    58 compliant with the protocol standard.
    59 
    60 @param aPageCode The SCSI PAGE CODE value
    61 @param aWriteProtected The SCSI WP value
    62 
    63 @return TInt KErrNone if successful, KErrCommandFailed to indicate a
    64 device status error, KErrCommandStalled to indicate device stall
    65 */
    66 TInt TSbcClientInterface::ModeSense6L(TUint aPageCode, TBool& aWriteProtected)
    67     {
    68     __MSFNLOG
    69     TScsiClientModeSense6Req modeSense6Req(TScsiClientModeSense6Req::ECurrentValues,
    70                                            aPageCode);
    71     TScsiClientModeSense6Resp modeSense6Resp;
    72     TInt err = iTransport.SendControlCmdL(&modeSense6Req, &modeSense6Resp);
    73     if (!err)
    74         {
    75         __SCSIPRINT1(_L("SCSI MODE SENSE (6) INFO WrProtect=%d"),
    76                      modeSense6Resp.iWriteProtected);
    77         aWriteProtected = modeSense6Resp.iWriteProtected;
    78         }
    79     else
    80         {
    81         aWriteProtected = EFalse;
    82         }
    83 	return err;
    84     }
    85 
    86 
    87 /**
    88 Create and send SCSI MODE SENSE (10) request to obtain the mediums Write Protect
    89 status. The function leaves if the device response is not compliant with the
    90 protocol standard.
    91 
    92 @param aPageCode The SCSI PAGE CODE value
    93 @param aWriteProtected The SCSI WP value
    94 
    95 @return TInt KErrNone if successful, KErrCommandFailed to indicate a
    96 device status error, KErrCommandStalled to indicate a device stall
    97 */
    98 TInt TSbcClientInterface::ModeSense10L(TUint aPageCode, TBool& aWriteProtected)
    99     {
   100     __MSFNLOG
   101     TScsiClientModeSense10Req modeSense10Req(TScsiClientModeSense10Req::ECurrentValues,
   102                                              aPageCode);
   103     TScsiClientModeSense10Resp modeSense10Resp;
   104     TInt err = iTransport.SendControlCmdL(&modeSense10Req, &modeSense10Resp);
   105 
   106     if (!err)
   107         {
   108         __SCSIPRINT1(_L("SCSI MODE SENSE (10) INFO WrProtect=%d"),
   109                      modeSense10Resp.iWriteProtected);
   110         aWriteProtected = modeSense10Resp.iWriteProtected;
   111         }
   112     else
   113         {
   114         aWriteProtected = EFalse;
   115         }
   116 	return err;
   117     }
   118 
   119 
   120 /**
   121 Constructor to create SCSI MODE SENSE (10) request.
   122 
   123 @param aPageControl The SCSI PAGE CODE value
   124 @param aPageCode The SCSI WP value
   125 @param aSubPageCode The SCSI SUB PAGE CODE value
   126 */
   127 TScsiClientModeSense10Req::TScsiClientModeSense10Req(TPageControl aPageControl,
   128                                                      TUint aPageCode,
   129                                                      TUint aSubPageCode)
   130     :
   131     TScsiClientReq(EModeSense10),
   132     iPageControl(aPageControl),
   133     iPageCode(aPageCode),
   134     iSubPageCode(aSubPageCode),
   135     iAllocationLength(KResponseLength)
   136     {
   137     __MSFNLOG
   138     }
   139 
   140 
   141 TInt TScsiClientModeSense10Req::EncodeRequestL(TDes8& aBuffer) const
   142     {
   143     __MSFNSLOG
   144     __SCSIPRINT(_L("<-- SCSI MODE SENSE (10)"));
   145     TInt length = TScsiClientReq::EncodeRequestL(aBuffer);
   146 
   147     // PC
   148     aBuffer[2] = iPageCode;
   149     aBuffer[2] |= iPageControl << 6;
   150     aBuffer[3] = iSubPageCode;
   151 
   152     BigEndian::Put16(&aBuffer[7], iAllocationLength);
   153     return length;
   154     }
   155 
   156 /**
   157 Create READ (10) request and send to the transport layer. This performs a
   158 logical block read of the device server. The received data is appended into the
   159 copy buffer. The function leaves if the device response is not compliant with
   160 the protocol standard.
   161 Note that TBlockTransfer must be initialised beforehand.
   162 
   163 @param aLba The Logical Block address to read from
   164 @param aBuffer The buffer to copy data to
   165 @param aLen The number of bytes to be read (IN) and returns the number of bytes
   166 actually read (OUT)
   167 
   168 @return TInt KErrNone if successful otherwise KErrCommandFailed to indicate a
   169 device status error or KErrArgument to indicate that aLen is too large for the
   170 protocol.
   171 */
   172 TInt TSbcClientInterface::Read10L(TLba aLba, TDes8& aBuffer, TInt& aLen)
   173     {
   174     __MSFNLOG
   175 	__ASSERT_DEBUG(iBlockTransfer.BlockLength(), User::Panic(KUsbMsHostPanicCat, EBlockLengthNotSet));
   176     __ASSERT_DEBUG(aLen % iBlockTransfer.BlockLength() == 0, User::Panic(KUsbMsHostPanicCat, EBlockDevice));
   177 
   178     TScsiClientRead10Req read10Req;
   179 
   180     read10Req.iLogicalBlockAddress = aLba;
   181 
   182     TInt blockTransferLength = aLen / iBlockTransfer.BlockLength();
   183     if (blockTransferLength > static_cast<TInt>(KMaxTUint16))
   184         {
   185         User::Leave(KErrArgument);
   186         }
   187     read10Req.iBlockTransferLength = static_cast<TUint16>(blockTransferLength);
   188     TInt err = iTransport.SendDataRxCmdL(&read10Req, aBuffer, aLen);
   189 	return err;
   190     }
   191 
   192 /**
   193 Create READ CAPACITY (10) request and send to the transport layer. The request
   194 returns the device servers capacity information. The device server's response
   195 values are also used here to initialise the TBlockTransfer values. The function
   196 leaves if the device response is not compliant with the protocol standard.
   197 
   198 @param aLba The Logical Block Address returned by the LU
   199 @param aBlockSize The Block Size returned by the LU
   200 
   201 @return TInt KErrNone if successful, KErrCommandFailed to indicate a
   202 device status error, KErrCommandStalled to indicate a device stall
   203 */
   204 TInt TSbcClientInterface::ReadCapacity10L(TLba& aLba, TUint32& aBlockSize)
   205     {
   206     __MSFNLOG
   207     TScsiClientReadCapacity10Req capacity10Req;
   208     TScsiClientReadCapacity10Resp capacity10Resp;
   209 
   210     TInt err = iTransport.SendControlCmdL(&capacity10Req, &capacity10Resp);
   211     if (!err)
   212         {
   213         aLba = capacity10Resp.iLba;
   214         aBlockSize = capacity10Resp.iBlockSize;
   215 
   216         __SCSIPRINT2(_L("Capacity LBA=0x%08x SIZE=0x%08x"),
   217                      aLba, aBlockSize);
   218 
   219         iBlockTransfer.SetCapacityL(aBlockSize, aLba);
   220         }
   221 	return err;
   222     }
   223 
   224 
   225 /**
   226 Create START STOP UNIT request. The function leaves if the device response is
   227 not compliant with the protocol standard.
   228 
   229 @param aStart SCSI START value
   230 
   231 @return TInt KErrNone if successful otherwise KErrCommandFailed to indicate a
   232 device status error
   233 */
   234 TInt TSbcClientInterface::StartStopUnitL(TBool aStart)
   235     {
   236     __MSFNLOG
   237     TScsiClientStartStopUnitReq startStopUnitReq;
   238 
   239     startStopUnitReq.iImmed = ETrue;
   240     startStopUnitReq.iLoej = EFalse;
   241     startStopUnitReq.iStart = aStart;
   242 
   243     TInt err = iTransport.SendControlCmdL(&startStopUnitReq);
   244 
   245 	return err;
   246     }
   247 
   248 
   249 /**
   250 Create WRITE (10) request and send to the transport layer. This performs a
   251 logical block write of the device server. Note that TBlockTransfer must be
   252 initialised beforehand.  The function leaves if the device response is not
   253 compliant with the protocol standard.
   254 
   255 @param aLba Logical Block Address to write the data to
   256 @param aBuffer Buffer containing the data
   257 @param aPos Offset into the buffer to the data
   258 @param aLen The number of bytes to be written (IN) and returns the bytes
   259 actually transferred (OUT)
   260 
   261 @return TInt KErrNone if successful otherwise KErrCommandFailed to indicate a
   262 device status error or KErrArgument to indicate that aLen is too large for the
   263 protocol.
   264 */
   265 TInt TSbcClientInterface::Write10L(TLba aLba, TDesC8& aBuffer, TUint aPos, TInt& aLen)
   266     {
   267     __MSFNLOG
   268 	__ASSERT_DEBUG(iBlockTransfer.BlockLength(), User::Panic(KUsbMsHostPanicCat, EBlockLengthNotSet));
   269     __ASSERT_DEBUG(aLen % iBlockTransfer.BlockLength() == 0, User::Panic(KUsbMsHostPanicCat, EBlockDevice));
   270 
   271     // check that buffer size is large enough
   272 	if (aBuffer.Length() < (aPos + aLen))
   273 		{
   274         User::Leave(KErrArgument);
   275 		}
   276 
   277     TScsiClientWrite10Req write10Req;
   278     write10Req.iLogicalBlockAddress = aLba;
   279 
   280     TInt blockTransferLength = aLen / iBlockTransfer.BlockLength();
   281     if (blockTransferLength > static_cast<TInt>(KMaxTUint16))
   282         {
   283         User::Leave(KErrArgument);
   284         }
   285     write10Req.iBlockTransferLength = static_cast<TUint16>(blockTransferLength);
   286 
   287     TInt err = iTransport.SendDataTxCmdL(&write10Req, aBuffer, aPos, aLen);
   288 	return err;
   289     }
   290