|
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 #include <e32base_private.h> |
|
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 |