|
1 // Copyright (c) 2004-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 // f32test\testusbcldd\src\misc.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #include "dtestusblogdev.h" |
|
19 |
|
20 TUsbcInterface::TUsbcInterface(TUsbcInterfaceSet* aIfcSet, TUint8 aSetting) |
|
21 : iEndpoints(2), iInterfaceSet(aIfcSet), iSettingCode(aSetting) |
|
22 { |
|
23 __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcInterface::TUsbcInterface()"))); |
|
24 } |
|
25 |
|
26 |
|
27 TUsbcInterface::~TUsbcInterface() |
|
28 { |
|
29 __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcInterface::~TUsbcInterface()"))); |
|
30 iEndpoints.ResetAndDestroy(); |
|
31 } |
|
32 |
|
33 |
|
34 TUsbcInterfaceSet::TUsbcInterfaceSet(const DBase* aClientId, TUint8 aIfcNum) |
|
35 : iInterfaces(2), iClientId(aClientId), iInterfaceNumber(aIfcNum), iCurrentInterface(0) |
|
36 { |
|
37 __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcInterfaceSet::TUsbcInterfaceSet()"))); |
|
38 } |
|
39 |
|
40 |
|
41 TUsbcInterfaceSet::~TUsbcInterfaceSet() |
|
42 { |
|
43 __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcInterfaceSet::~TUsbcInterfaceSet()"))); |
|
44 iInterfaces.ResetAndDestroy(); |
|
45 } |
|
46 |
|
47 const TUsbcInterface* TUsbcInterfaceSet::CurrentInterface() const |
|
48 /** Returns a pointer to the currently selected (active) setting of this interface. |
|
49 |
|
50 @return A pointer to the currently selected (active) setting of this interface. |
|
51 */ |
|
52 { |
|
53 return iInterfaces[iCurrentInterface]; |
|
54 } |
|
55 |
|
56 |
|
57 TUsbcInterface* TUsbcInterfaceSet::CurrentInterface() |
|
58 /** Returns a pointer to the currently selected (active) setting of this interface. |
|
59 |
|
60 @return A pointer to the currently selected (active) setting of this interface. |
|
61 */ |
|
62 { |
|
63 return iInterfaces[iCurrentInterface]; |
|
64 } |
|
65 |
|
66 TUsbcLogicalEndpoint::TUsbcLogicalEndpoint(TUint aEndpointNum, const TUsbcEndpointInfo& aInfo, |
|
67 TUsbcInterface* aInterface) |
|
68 : iLEndpointNum(aEndpointNum), iInfo(aInfo), iInterface(aInterface) |
|
69 { |
|
70 __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcLogicalEndpoint::TUsbcLogicalEndpoint()"))); |
|
71 } |
|
72 |
|
73 |
|
74 TUsbcLogicalEndpoint::~TUsbcLogicalEndpoint() |
|
75 { |
|
76 __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcLogicalEndpoint::~TUsbcLogicalEndpoint: #%d"), iLEndpointNum)); |
|
77 } |
|
78 |
|
79 DTestUsbcEndpoint::DTestUsbcEndpoint() |
|
80 { |
|
81 } |
|
82 |
|
83 DTestUsbcEndpoint::~DTestUsbcEndpoint() |
|
84 { |
|
85 __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Deleting buffer 0x%x"), iBuffer)); |
|
86 delete iBuffer; |
|
87 __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Buffer deleted"))); |
|
88 } |
|
89 |
|
90 TInt DTestUsbcEndpoint::Create(const TUsbcEndpointCaps& aCaps) |
|
91 { |
|
92 iCaps = aCaps; |
|
93 if (iBuffer == NULL) |
|
94 { |
|
95 __NEWPLATBUF(iBuffer, KEndpointBufferSize); |
|
96 if (iBuffer == NULL) |
|
97 return KErrNoMemory; |
|
98 } |
|
99 __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Allocated buffer 0x%x"), iBuffer)); |
|
100 return KErrNone; |
|
101 } |
|
102 |
|
103 void DTestUsbcEndpoint::DoCancel() |
|
104 { |
|
105 if (iRequestPending) |
|
106 { |
|
107 //Cancel client request |
|
108 iRequestPending = EFalse; |
|
109 Kern::RequestComplete(iClient, iClientStatus, KErrCancel); |
|
110 } |
|
111 if (iHostRequestPending) |
|
112 { |
|
113 //Cancel host request |
|
114 iHostRequestPending = EFalse; |
|
115 Kern::RequestComplete(iHost, iHostStatus, KErrCancel); |
|
116 } |
|
117 } |
|
118 |
|
119 TInt DTestUsbcEndpoint::NewRequest(DThread* aClient, TRequestStatus* aStatus, |
|
120 TEndpointTransferInfo& aInfo, TTransferType aType) |
|
121 { |
|
122 __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("DTestUsbcEndpoint::NewRequest"))); |
|
123 //Only supports one request pending per endpoint |
|
124 if (iRequestPending) |
|
125 { |
|
126 return ERequestAlreadyPending; |
|
127 } |
|
128 iClient = aClient; |
|
129 iClientStatus = aStatus; |
|
130 iClientTransferInfo = aInfo; |
|
131 iDataTransferred = 0; |
|
132 iRequestPending = ETrue; |
|
133 iRequestType = aType; |
|
134 |
|
135 //Copy data to local buffer if this is a write request |
|
136 if (iRequestType == ETransferTypeWrite) |
|
137 { |
|
138 __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Write request"))); |
|
139 TInt err; |
|
140 __THREADREADPLATBUF(aClient, iClientTransferInfo.iDes, iBuffer, err); |
|
141 if (err != KErrNone) |
|
142 { |
|
143 iRequestPending = EFalse; |
|
144 return err; |
|
145 } |
|
146 } |
|
147 else |
|
148 { |
|
149 __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Read request"))); |
|
150 } |
|
151 |
|
152 if (iHostRequestPending) |
|
153 { |
|
154 TryToComplete(); |
|
155 } |
|
156 |
|
157 return KErrNone; |
|
158 } |
|
159 |
|
160 TInt DTestUsbcEndpoint::NewHostRequest(DThread* aHost, TRequestStatus* aStatus, |
|
161 TEndpointTransferInfo& aInfo, TTransferType aType) |
|
162 { |
|
163 __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("DTestUsbcEndpoint::NewHostRequest"))); |
|
164 //Only supports one request pending per endpoint |
|
165 if (iHostRequestPending) |
|
166 { |
|
167 return ERequestAlreadyPending; |
|
168 } |
|
169 iHost = aHost; |
|
170 iHostStatus = aStatus; |
|
171 iHostTransferInfo = aInfo; |
|
172 iHostDataTransferred = 0; |
|
173 iHostRequestPending = ETrue; |
|
174 iHostRequestType = aType; |
|
175 |
|
176 //Copy data to local buffer if this is a write request |
|
177 if (iHostRequestType == ETransferTypeWrite) |
|
178 { |
|
179 __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Write request"))); |
|
180 TInt err; |
|
181 __THREADREADPLATBUF(aHost, iHostTransferInfo.iDes, iBuffer, err); |
|
182 if (err != KErrNone) |
|
183 { |
|
184 iRequestPending = EFalse; |
|
185 return err; |
|
186 } |
|
187 } |
|
188 else |
|
189 { |
|
190 __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Read request"))); |
|
191 } |
|
192 |
|
193 if (iRequestPending) |
|
194 { |
|
195 TryToComplete(); |
|
196 } |
|
197 |
|
198 return KErrNone; |
|
199 } |
|
200 |
|
201 TInt DTestUsbcEndpoint::TryToComplete() |
|
202 { |
|
203 __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("DTestUsbcEndpoint::TryToComplete"))); |
|
204 TInt err = KErrNone; |
|
205 TInt len = iHostTransferInfo.iTransferSize - iHostDataTransferred; |
|
206 |
|
207 if (SupportsDir(KUsbEpDirBidirect)) |
|
208 { |
|
209 //Make sure host and client transfer types don't conflict |
|
210 if (iRequestType == iHostRequestType) |
|
211 { |
|
212 iRequestPending = EFalse; |
|
213 iHostRequestPending = EFalse; |
|
214 Kern::RequestComplete(iClient, iClientStatus, KErrUsbEpBadDirection); |
|
215 Kern::RequestComplete(iHost, iHostStatus, KErrUsbEpBadDirection); |
|
216 return KErrUsbEpBadDirection; |
|
217 } |
|
218 } |
|
219 |
|
220 if (SupportsDir(KUsbEpDirIn) || (SupportsDir(KUsbEpDirBidirect) && iRequestType == ETransferTypeWrite)) |
|
221 { |
|
222 err = CopyData(iDataTransferred, iHost, iHostTransferInfo.iDes, iHostDataTransferred, len); |
|
223 } |
|
224 else if (SupportsDir(KUsbEpDirOut) || (SupportsDir(KUsbEpDirBidirect) && iRequestType == ETransferTypeReadData)) |
|
225 { |
|
226 err = CopyData(iHostDataTransferred, iClient, iClientTransferInfo.iDes, iDataTransferred, len); |
|
227 } |
|
228 else |
|
229 { |
|
230 err = KErrNotSupported; |
|
231 } |
|
232 |
|
233 if (err != KErrNone) |
|
234 { |
|
235 //Problems copying data. Complete requests with error and return. |
|
236 iRequestPending = EFalse; |
|
237 iHostRequestPending = EFalse; |
|
238 Kern::RequestComplete(iClient, iClientStatus, err); |
|
239 Kern::RequestComplete(iHost, iHostStatus, err); |
|
240 return err; |
|
241 } |
|
242 iDataTransferred += len; |
|
243 iHostDataTransferred += len; |
|
244 |
|
245 iRequestPending = EFalse; |
|
246 Kern::RequestComplete(iClient, iClientStatus, KErrNone); |
|
247 iHostRequestPending = EFalse; |
|
248 Kern::RequestComplete(iHost, iHostStatus, KErrNone); |
|
249 return KErrNone; |
|
250 } |
|
251 |
|
252 /** |
|
253 Copies data from a source descriptor to a destination descriptor, both in user space. |
|
254 |
|
255 @param aSrcClient The thread that owns the source descriptor |
|
256 @param aSrc Pointer to the source descriptor |
|
257 @param aSrcOffset Offset in aSrc from where to start reading data |
|
258 @param aDestClient The thread that owns the destination descriptor |
|
259 @param aDest Pointer to the destination descriptor |
|
260 @param aDestOffset Offset in aDest from where to start writing data |
|
261 @param aLen Amount of bytes to copy |
|
262 @return KErrNone is successful, otherwise a standard Symbian error code |
|
263 */ |
|
264 TInt DTestUsbcEndpoint::CopyData(TInt aSrcOffset, DThread* aDestClient, TDesC8* aDest, |
|
265 TInt aDestOffset, TInt aLen) |
|
266 { |
|
267 TInt err; |
|
268 |
|
269 // Get the descriptor length in the client's context. |
|
270 TInt rxLen[2] = {0,0}; |
|
271 err=Kern::ThreadRawRead(aDestClient,aDest,&rxLen,sizeof(rxLen)); |
|
272 if (err!=KErrNone) |
|
273 return err; |
|
274 |
|
275 // copy mo more than max number of chars in receive buffer |
|
276 aLen = Min(aLen, rxLen[1]); |
|
277 |
|
278 while(aLen > 0) |
|
279 { |
|
280 TInt len = iBuffer->Length() - aSrcOffset; |
|
281 //Make sure we only copy aLen bytes, no more |
|
282 if (len > aLen) |
|
283 { |
|
284 len = aLen; |
|
285 } |
|
286 TPtrC8 src(iBuffer->Ptr() + aSrcOffset, len); |
|
287 err = __THREADWRITEOFFSET(aDestClient, aDest, src, aDestOffset); |
|
288 if (err != KErrNone) |
|
289 { |
|
290 return err; |
|
291 } |
|
292 aLen -= len; |
|
293 aSrcOffset += len; |
|
294 aDestOffset += len; |
|
295 } |
|
296 |
|
297 return KErrNone; |
|
298 } |
|
299 |
|
300 TInt DTestUsbcEndpoint::Halt() |
|
301 { |
|
302 iHalted = ETrue; |
|
303 if (iNotifyHost != NULL) |
|
304 { |
|
305 Kern::RequestComplete(iNotifyHost, iHostNotifyStatus, KErrNone); |
|
306 iNotifyHost = NULL; |
|
307 } |
|
308 return KErrNone; |
|
309 } |
|
310 |
|
311 TInt DTestUsbcEndpoint::Clear() |
|
312 { |
|
313 iHalted = EFalse; |
|
314 if (iRequestPending) |
|
315 { |
|
316 iRequestPending = EFalse; |
|
317 Kern::RequestComplete(iClient, iClientStatus, KErrNone); |
|
318 } |
|
319 if (iHostRequestPending) |
|
320 { |
|
321 iHostRequestPending = EFalse; |
|
322 Kern::RequestComplete(iHost, iHostStatus, KErrNone); |
|
323 } |
|
324 if (iClearCallback != NULL) |
|
325 { |
|
326 iClearCallback->EndpointStatusNotifyCallback(); |
|
327 } |
|
328 return KErrNone; |
|
329 } |
|
330 |
|
331 void DTestUsbcEndpoint::SetClearCallback(DLddTestUsbcChannel* aCallback) |
|
332 { |
|
333 iClearCallback = aCallback; |
|
334 } |
|
335 |
|
336 TBool DTestUsbcEndpoint::IsHalted() |
|
337 { |
|
338 return iHalted; |
|
339 } |
|
340 |
|
341 TInt DTestUsbcEndpoint::HostStatusNotify(DThread* aHost, TRequestStatus* aStatus) |
|
342 { |
|
343 const TRequestStatus s(KRequestPending); |
|
344 __THREADRAWWRITE(aHost, aStatus, (TUint8*)&s, (TInt)sizeof(TRequestStatus)); |
|
345 iNotifyHost = aHost; |
|
346 iHostNotifyStatus = aStatus; |
|
347 return KErrNone; |
|
348 } |
|
349 |
|
350 TBool DTestUsbcEndpoint::SupportsDir(TUint aDir) |
|
351 { |
|
352 if ((iCaps.iTypesAndDir & aDir) == aDir) |
|
353 { |
|
354 return ETrue; |
|
355 } |
|
356 return EFalse; |
|
357 } |
|
358 |
|
359 TBool DTestUsbcEndpoint::EndpointSuitable(const TUsbcEndpointInfo& aInfo) |
|
360 { |
|
361 return (!iReserve && |
|
362 (iCaps.iSizes == (TUint)aInfo.iSize) && |
|
363 ((iCaps.iTypesAndDir & aInfo.iDir) == aInfo.iDir) && |
|
364 ((iCaps.iTypesAndDir & aInfo.iType) == aInfo.iType)); |
|
365 } |
|
366 |