|
1 // Copyright (c) 2007-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 // Thread for reading and writing to a drive. |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 @internalTechnology |
|
21 */ |
|
22 |
|
23 #ifndef __RWDRIVETHREAD_H__ |
|
24 #define __RWDRIVETHREAD_H__ |
|
25 |
|
26 #ifdef MSDC_MULTITHREADED |
|
27 |
|
28 typedef void (*ProcessWriteCompleteFunc)(TUint8* aAddress, TAny* aPtr); |
|
29 |
|
30 |
|
31 /** |
|
32 Class contains buffer for data with associated drive offset and length in bytes. |
|
33 */ |
|
34 |
|
35 class TBlockDesc |
|
36 { |
|
37 public: |
|
38 |
|
39 TBlockDesc(); |
|
40 void SetPtr(TPtr8& aDes); |
|
41 |
|
42 TPtr8 GetReadBuffer(); |
|
43 TPtr8 GetReadBuffer(TUint aLength, const TInt64& aOffset); |
|
44 |
|
45 public: |
|
46 TInt64 iByteOffset; |
|
47 TUint iLength; |
|
48 TPtr8 iBuf; |
|
49 }; |
|
50 |
|
51 |
|
52 /** |
|
53 Class contains two buffers. Whilst one buffer is being read the |
|
54 other buffer can be written to. The buffers should be accessed |
|
55 by the buffer pointers iDescReadPtr and iDescWritePtr. |
|
56 */ |
|
57 |
|
58 class TBlockDescBuffer |
|
59 { |
|
60 public: |
|
61 TBlockDescBuffer(); |
|
62 |
|
63 void SwapDesc(); |
|
64 TInt MaxLength() const {return iDesc2.iBuf.MaxLength();} |
|
65 TInt GetBufferNumber(const TPtr8* aBufferPtr) const; |
|
66 void SetUpReadBuf(TPtr8& aDes1, TPtr8& aDes2); |
|
67 |
|
68 public: |
|
69 /** Points to block descriptor containing buffer to read from */ |
|
70 TBlockDesc* iDescReadPtr; |
|
71 /** Points to block descriptor containing buffer to write to */ |
|
72 TBlockDesc* iDescWritePtr; |
|
73 |
|
74 private: |
|
75 /** Block descriptor for read/write operations */ |
|
76 TBlockDesc iDesc1; |
|
77 /** Block descriptor for read/write operations */ |
|
78 TBlockDesc iDesc2; |
|
79 }; |
|
80 |
|
81 |
|
82 /** |
|
83 Provides the common thread context used by CReadDriveThread and CWriteDriveThread |
|
84 classes. |
|
85 */ |
|
86 class CThreadContext : public CBase |
|
87 { |
|
88 public: |
|
89 static CThreadContext* NewL(const TDesC& aName, |
|
90 TThreadFunction aThreadFunction, |
|
91 TAny* aOwner); |
|
92 ~CThreadContext(); |
|
93 |
|
94 private: |
|
95 CThreadContext(); |
|
96 void ConstructL(const TDesC& aName, TThreadFunction aThreadFunction, TAny* aOwner); |
|
97 |
|
98 |
|
99 public: |
|
100 void Resume() {iThread.Resume();} |
|
101 |
|
102 TInt MaxBufferLength() const {return iBuffer.MaxLength();} |
|
103 TPtr8 GetReadBuffer(); |
|
104 TPtr8 GetReadBuffer(TInt aLength); |
|
105 |
|
106 TPtrC8 WriteBuf(); |
|
107 |
|
108 public: |
|
109 /** Used to tell thread which drive to use */ |
|
110 CMassStorageDrive* iDrive; |
|
111 /** Used by the thread to return error code */ |
|
112 TInt iError; |
|
113 /** CS to regulate read/write buffer access */ |
|
114 RCriticalSection iCritSect; |
|
115 |
|
116 /** buffer for reading and writing */ |
|
117 TBlockDescBuffer iBuffer; |
|
118 |
|
119 public: |
|
120 RThread iThread; |
|
121 }; |
|
122 |
|
123 |
|
124 /** |
|
125 Separate disk writer thread, used to implement OUT transfer double-buffering. |
|
126 */ |
|
127 class CWriteDriveThread : public CBase |
|
128 { |
|
129 public: |
|
130 static CWriteDriveThread* NewL(); |
|
131 ~CWriteDriveThread(); |
|
132 |
|
133 private: |
|
134 CWriteDriveThread(); |
|
135 void ConstructL(); |
|
136 |
|
137 public: |
|
138 TBlockDesc* GetReadDesc(); |
|
139 |
|
140 TInt WriteDriveData(CMassStorageDrive* aDrive, const TInt64& aOffset, TPtrC8& aDes, ProcessWriteCompleteFunc aFunc, TAny* aPtr); |
|
141 |
|
142 TUint WriteBufferLength() const {return iThreadContext->iBuffer.iDescWritePtr->iBuf.Length();} |
|
143 TUint ReadBufferLength() const {return iThreadContext->iBuffer.iDescReadPtr->iBuf.Length();} |
|
144 |
|
145 TInt DeferredError() const {return iThreadContext->iError;} |
|
146 void ClearDeferredError() {iThreadContext->iError = KErrNone;} |
|
147 void WaitForWriteEmpty(); |
|
148 |
|
149 TBool IsRecentlyWritten(TInt64 aOffset, TInt aLength); |
|
150 inline void SetCommandWrite10(TBool aIsWriteCommand) {iIsCommandWrite10 = aIsWriteCommand;}; |
|
151 |
|
152 private: |
|
153 static TInt ThreadFunction(TAny* aSelf); |
|
154 TInt WriteToDrive(); |
|
155 |
|
156 public: |
|
157 /** Thread context */ |
|
158 CThreadContext* iThreadContext; |
|
159 |
|
160 TInt iWriteCounter; |
|
161 private: |
|
162 /** Semaphore for reading USB */ |
|
163 RSemaphore iProducerSem; |
|
164 /** Semaphore for writing to drive */ |
|
165 RSemaphore iConsumerSem; |
|
166 /* Call back to tell transport that 'transfer' was written and the corresponding buffer can be overwriiten (mainly for SC LDD) */ |
|
167 ProcessWriteCompleteFunc iCallback; |
|
168 TAny* iCallbackParameter; |
|
169 /* Flag set to true if the command is Write10. Used in Read10 to ignore pre-read if the previous command was Write10 */ |
|
170 TBool iIsCommandWrite10; |
|
171 }; |
|
172 |
|
173 |
|
174 /** |
|
175 Separate disk reader thread, used to implement IN transfer double-buffering. |
|
176 */ |
|
177 class CReadDriveThread : public CBase |
|
178 { |
|
179 public: |
|
180 static CReadDriveThread* NewL(); |
|
181 ~CReadDriveThread(); |
|
182 |
|
183 private: |
|
184 CReadDriveThread(); |
|
185 void ConstructL(); |
|
186 |
|
187 public: |
|
188 TBool ReadDriveData(CMassStorageDrive* aDrive, const TInt64& aOffset, TUint32 aLength, TBool aIgnoreCache); |
|
189 void DiscardRead(); |
|
190 |
|
191 private: |
|
192 static TInt ThreadFunction(TAny* aSelf); |
|
193 TInt ReadFromDrive(); |
|
194 |
|
195 public: |
|
196 /** Thread context */ |
|
197 CThreadContext* iThreadContext; |
|
198 TBool iCompleted; |
|
199 |
|
200 private: |
|
201 TBool iThreadRunning; |
|
202 }; |
|
203 |
|
204 |
|
205 //----------------------------------------------- |
|
206 |
|
207 /** |
|
208 Swap the buffer which the read and write buffer pointers are pointing to. |
|
209 */ |
|
210 inline void TBlockDescBuffer::SwapDesc() |
|
211 { |
|
212 TBlockDesc* const tmp = iDescReadPtr; |
|
213 iDescReadPtr = iDescWritePtr; |
|
214 iDescWritePtr = tmp; |
|
215 } |
|
216 |
|
217 inline TPtr8 TBlockDesc::GetReadBuffer() |
|
218 { |
|
219 return iBuf.LeftTPtr(iBuf.Length()); |
|
220 } |
|
221 |
|
222 |
|
223 inline TPtr8 TBlockDesc::GetReadBuffer(TUint aLength, const TInt64& aOffset) |
|
224 { |
|
225 iByteOffset = aOffset; |
|
226 iLength = aLength; |
|
227 iBuf.SetLength(aLength); |
|
228 |
|
229 return GetReadBuffer(); |
|
230 } |
|
231 |
|
232 //----------------------------------------------- |
|
233 |
|
234 /** |
|
235 Returns the id of the buffer |
|
236 |
|
237 @param bufferPtr pointer to the buffer. |
|
238 @return returns the buffer ID or -1 if the buffer is not found. |
|
239 */ |
|
240 inline TInt TBlockDescBuffer::GetBufferNumber(const TPtr8* aBufferPtr) const |
|
241 { |
|
242 TInt no = -1; |
|
243 if (aBufferPtr == &iDesc1.iBuf) |
|
244 no = 1; |
|
245 else if (aBufferPtr == &iDesc2.iBuf) |
|
246 no = 2; |
|
247 return no; |
|
248 } |
|
249 |
|
250 |
|
251 //----------------------------------------------- |
|
252 |
|
253 inline TPtr8 CThreadContext::GetReadBuffer() |
|
254 { |
|
255 TInt len = iBuffer.iDescReadPtr->iBuf.Length(); |
|
256 return iBuffer.iDescReadPtr->iBuf.LeftTPtr(len); |
|
257 } |
|
258 |
|
259 |
|
260 inline TPtr8 CThreadContext::GetReadBuffer(TInt aLength) |
|
261 { |
|
262 iBuffer.iDescReadPtr->iBuf.SetLength(aLength); |
|
263 return GetReadBuffer(); |
|
264 } |
|
265 |
|
266 |
|
267 inline TPtrC8 CThreadContext::WriteBuf() |
|
268 { |
|
269 return iBuffer.iDescWritePtr->iBuf; |
|
270 } |
|
271 |
|
272 //----------------------------------------------- |
|
273 |
|
274 inline TBlockDesc* CWriteDriveThread::GetReadDesc() |
|
275 { |
|
276 return iThreadContext->iBuffer.iDescReadPtr; |
|
277 } |
|
278 |
|
279 //----------------------------------------------- |
|
280 |
|
281 #endif // MSDC_MULTITHREADED |
|
282 |
|
283 #endif // __RWDRIVETHREAD_H__ |