|
1 /* |
|
2 * Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * |
|
15 */ |
|
16 |
|
17 /** |
|
18 @file |
|
19 */ |
|
20 |
|
21 #include <e32svr.h> |
|
22 #include "transferserver.h" |
|
23 #include "transfersession.h" |
|
24 #include "transfersrv.h" |
|
25 #include "transferserversecuritypolicy.h" |
|
26 #include "transferhandle.h" |
|
27 #include "tranhandlesrv.h" |
|
28 |
|
29 |
|
30 |
|
31 TBool gVerbose = ETrue; |
|
32 extern RTest test; |
|
33 |
|
34 |
|
35 CTransferServer* CTransferServer::NewLC() |
|
36 { |
|
37 RDebug::Printf("CTransferServer::NewLC"); |
|
38 CTransferServer* self = new(ELeave) CTransferServer; |
|
39 CleanupStack::PushL(self); |
|
40 self->StartL(KTransferServerName); |
|
41 self->ConstructL(); |
|
42 return self; |
|
43 } |
|
44 |
|
45 CTransferServer::~CTransferServer() |
|
46 { |
|
47 RDebug::Printf("CTransferServer::~CTransferServer"); |
|
48 while (iLddPtr->iIFPtr) |
|
49 { |
|
50 IFConfigPtr* ifPtrPtr = & iLddPtr->iIFPtr; |
|
51 while ((*ifPtrPtr)->iPtrNext) |
|
52 { |
|
53 ifPtrPtr = &(*ifPtrPtr)->iPtrNext; |
|
54 } |
|
55 delete (*ifPtrPtr)->iInfoPtr->iString; |
|
56 delete (*ifPtrPtr)->iInfoPtr; |
|
57 delete (*ifPtrPtr); |
|
58 * ifPtrPtr = NULL; |
|
59 } |
|
60 |
|
61 while (iLddPtr) |
|
62 { |
|
63 LDDConfigPtr* lddPtrPtr = &iLddPtr; |
|
64 while ((*lddPtrPtr)->iPtrNext) |
|
65 { |
|
66 lddPtrPtr = &(*lddPtrPtr)->iPtrNext; |
|
67 } |
|
68 delete (*lddPtrPtr)->iManufacturer; |
|
69 delete (*lddPtrPtr)->iProduct; |
|
70 delete (*lddPtrPtr)->iSerialNumber; |
|
71 delete (*lddPtrPtr); |
|
72 * lddPtrPtr = NULL; |
|
73 } |
|
74 |
|
75 delete iShutdownTimer; |
|
76 delete iTransferHandle; |
|
77 RDebug::Printf("<<<CTransferServer::~CTransferServer"); |
|
78 } |
|
79 |
|
80 |
|
81 CTransferServer::CTransferServer() |
|
82 : CPolicyServer(EPriorityHigh,KTransferServerPolicy) |
|
83 { |
|
84 } |
|
85 |
|
86 void CTransferServer::ConstructL() |
|
87 { |
|
88 iShutdownTimer = new(ELeave) CShutdownTimer; |
|
89 iShutdownTimer->ConstructL(); |
|
90 |
|
91 iTransferHandle = CTransferHandle::NewL(*this); |
|
92 RDebug::Printf("CTransferServer::ConstructL"); |
|
93 } |
|
94 |
|
95 |
|
96 CSession2* CTransferServer::NewSessionL(const TVersion &aVersion, const RMessage2& aMessage) const |
|
97 { |
|
98 (void)aMessage;//Remove compiler warning |
|
99 (void)aVersion;//Remove compiler warning |
|
100 |
|
101 CTransferServer* ncThis = const_cast<CTransferServer*>(this); |
|
102 |
|
103 CTransferSession* sess = CTransferSession::NewL(ncThis); |
|
104 |
|
105 return sess; |
|
106 } |
|
107 |
|
108 |
|
109 void CTransferServer::Error(TInt aError) |
|
110 { |
|
111 RDebug::Printf("CTransferServer::Error"); |
|
112 Message().Complete(aError); |
|
113 ReStart(); |
|
114 } |
|
115 |
|
116 void CTransferServer::IncrementSessionCount() |
|
117 { |
|
118 RDebug::Printf("CTransferServer::IncrementSessionCount"); |
|
119 |
|
120 ++iSessionCount; |
|
121 iShutdownTimer->Cancel(); |
|
122 |
|
123 } |
|
124 |
|
125 void CTransferServer::DecrementSessionCount() |
|
126 { |
|
127 --iSessionCount; |
|
128 RDebug::Printf("CTransferServer::DecrementSessionCount"); |
|
129 if (iSessionCount == 0) |
|
130 { |
|
131 iShutdownTimer->After(KShutdownDelay); |
|
132 RDebug::Printf("CTransferServer::DecrementSessionCount1"); |
|
133 } |
|
134 } |
|
135 |
|
136 void CTransferServer::LaunchShutdownTimerIfNoSessions() |
|
137 { |
|
138 if (iSessionCount == 0) |
|
139 iShutdownTimer->After(KShutdownDelay); |
|
140 } |
|
141 |
|
142 CTransferServer::CShutdownTimer::CShutdownTimer() |
|
143 : CTimer(EPriorityStandard) |
|
144 { |
|
145 CActiveScheduler::Add(this); |
|
146 } |
|
147 |
|
148 |
|
149 void CTransferServer::CShutdownTimer::ConstructL() |
|
150 { |
|
151 RDebug::Printf("CTransferServer::CShutdownTimer::ConstructL"); |
|
152 CTimer::ConstructL(); |
|
153 } |
|
154 |
|
155 |
|
156 void CTransferServer::CShutdownTimer::RunL() |
|
157 { |
|
158 RDebug::Printf("CShutdownTimer::RunL"); |
|
159 CActiveScheduler::Stop(); |
|
160 } |
|
161 |
|
162 |
|
163 void CTransferServer::TransferHandleL() |
|
164 { |
|
165 RTranHandleSrv aServer; |
|
166 RChunk* commChunk = NULL; |
|
167 User::LeaveIfError(aServer.Connect()); |
|
168 User::LeaveIfError(iPort[0].GetDataTransferChunk(commChunk)); |
|
169 User::LeaveIfError(aServer.TransferHandle(iPort[0], *commChunk)); |
|
170 aServer.Close(); |
|
171 commChunk->Close(); |
|
172 iPort[0].Close(); |
|
173 } |
|
174 |
|
175 void CTransferServer::FillEndpointsResourceAllocation(IFConfigPtr aIfCfg) |
|
176 { |
|
177 |
|
178 #ifdef USB_SC |
|
179 TUsbcScInterfaceInfo* iInfoPtr = aIfCfg->iInfoPtr; |
|
180 #else |
|
181 TUsbcInterfaceInfo* iInfoPtr = aIfCfg->iInfoPtr; |
|
182 #endif |
|
183 |
|
184 // fill resource allocation info in the endpoint info with resource allocation v2 |
|
185 for (TUint8 i = 1; i <= iInfoPtr->iTotalEndpointsUsed; i++) |
|
186 { |
|
187 if (aIfCfg->iEpDMA[i-1]) |
|
188 { |
|
189 iInfoPtr->iEndpointData[i-1].iFeatureWord1 |= KUsbcEndpointInfoFeatureWord1_DMA; |
|
190 } |
|
191 else |
|
192 { |
|
193 iInfoPtr->iEndpointData[i-1].iFeatureWord1 &= (~KUsbcEndpointInfoFeatureWord1_DMA); |
|
194 } |
|
195 #ifndef USB_SC |
|
196 if (aIfCfg->iEpDoubleBuff[i-1]) |
|
197 { |
|
198 iInfoPtr->iEndpointData[i-1].iFeatureWord1 |= KUsbcEndpointInfoFeatureWord1_DoubleBuffering; |
|
199 } |
|
200 else |
|
201 { |
|
202 iInfoPtr->iEndpointData[i-1].iFeatureWord1 &= (~KUsbcEndpointInfoFeatureWord1_DoubleBuffering); |
|
203 } |
|
204 #endif |
|
205 } |
|
206 } |
|
207 |
|
208 |
|
209 void CTransferServer::PopulateInterfaceResourceAllocation(IFConfigPtr aFirstIfCfg, TInt aPortNumber) |
|
210 { |
|
211 FillEndpointsResourceAllocation(aFirstIfCfg); |
|
212 |
|
213 IFConfigPtr ifCfgPtr = aFirstIfCfg->iPtrNext; |
|
214 while (ifCfgPtr != NULL) |
|
215 { |
|
216 if (ifCfgPtr->iAlternateSetting) |
|
217 { |
|
218 FillEndpointsResourceAllocation(ifCfgPtr); |
|
219 ifCfgPtr = ifCfgPtr->iPtrNext; |
|
220 } |
|
221 else |
|
222 { |
|
223 ifCfgPtr = NULL; |
|
224 } |
|
225 } |
|
226 } |
|
227 |
|
228 void CTransferServer::SetupInterface(IFConfigPtr* aIfPtr, TInt aPortNumber) |
|
229 { |
|
230 test.Start (_L("Setup Interface")); |
|
231 |
|
232 // first of all set the default interface |
|
233 TUSB_PRINT2 ("Set Default Interface with %d endpoints bandwidth 0x%x",(*aIfPtr)->iInfoPtr->iTotalEndpointsUsed,(*aIfPtr)->iBandwidthIn | (*aIfPtr)->iBandwidthOut); |
|
234 #ifdef USB_SC |
|
235 TUsbcScInterfaceInfoBuf ifc = *((*aIfPtr)->iInfoPtr); |
|
236 TInt r = iPort[aPortNumber].SetInterface(0, ifc); |
|
237 #else |
|
238 TUsbcInterfaceInfoBuf ifc = *((*aIfPtr)->iInfoPtr); |
|
239 TInt r = iPort[aPortNumber].SetInterface(0, ifc, (*aIfPtr)->iBandwidthIn | (*aIfPtr)->iBandwidthOut); |
|
240 #endif |
|
241 test_KErrNone(r); |
|
242 |
|
243 TBuf8<KUsbDescSize_Interface> ifDescriptor; |
|
244 r = iPort[aPortNumber].GetInterfaceDescriptor(0, ifDescriptor); |
|
245 test_KErrNone(r); |
|
246 |
|
247 // Check the interface descriptor |
|
248 test(ifDescriptor[KIfcDesc_SettingOffset] == 0 && ifDescriptor[KIfcDesc_NumEndpointsOffset] == (*aIfPtr)->iInfoPtr->iTotalEndpointsUsed && |
|
249 ifDescriptor[KIfcDesc_ClassOffset] == (*aIfPtr)->iInfoPtr->iClass.iClassNum && |
|
250 ifDescriptor[KIfcDesc_SubClassOffset] == (*aIfPtr)->iInfoPtr->iClass.iSubClassNum && |
|
251 ifDescriptor[KIfcDesc_ProtocolOffset] == (*aIfPtr)->iInfoPtr->iClass.iProtocolNum); |
|
252 |
|
253 if ((*aIfPtr)->iNumber != 0 && ifDescriptor[KIfcDesc_NumberOffset] != (*aIfPtr)->iNumber) |
|
254 { |
|
255 ifDescriptor[KIfcDesc_NumberOffset] = (*aIfPtr)->iNumber; |
|
256 r = iPort[aPortNumber].SetInterfaceDescriptor(0, ifDescriptor); |
|
257 test_KErrNone(r); |
|
258 } |
|
259 else |
|
260 { |
|
261 (*aIfPtr)->iNumber = ifDescriptor[KIfcDesc_NumberOffset]; |
|
262 } |
|
263 TUint8 interfaceNumber = (*aIfPtr)->iNumber; |
|
264 TUSB_PRINT1 ("Interface Number %d",interfaceNumber); |
|
265 test.End(); |
|
266 } |
|
267 |
|
268 |
|
269 TInt CTransferServer::SetupLdds(TDes& aFileName) |
|
270 { |
|
271 TInt r; |
|
272 User::LeaveIfError(iFs.Connect()); |
|
273 |
|
274 RDebug::Printf ("Configuration"); |
|
275 |
|
276 RDebug::Printf ("Open configuration file"); |
|
277 // set the session path to use the ROM if no drive specified |
|
278 r=iFs.SetSessionPath(_L("Z:\\test\\")); |
|
279 test_KErrNone(r); |
|
280 |
|
281 r = iConfigFile.Open(iFs, aFileName, EFileShareReadersOnly | EFileStreamText | EFileRead); |
|
282 test_KErrNone(r); |
|
283 RDebug::Printf("Configuration file %s Opened successfully", aFileName.PtrZ()); |
|
284 |
|
285 RDebug::Printf ("Process configuration file"); |
|
286 test(ProcessConfigFile (iConfigFile,NULL,&iLddPtr)); |
|
287 |
|
288 iConfigFile.Close(); |
|
289 iFs.Close(); |
|
290 |
|
291 RDebug::Printf ("LDD in configuration file"); |
|
292 test_NotNull(iLddPtr); |
|
293 |
|
294 LDDConfigPtr lddPtr = iLddPtr; |
|
295 TInt nextPort = 0; |
|
296 while (lddPtr != NULL) |
|
297 { |
|
298 // Load logical driver (LDD) |
|
299 // (There's no physical driver (PDD) with USB: it's a kernel extension DLL which |
|
300 // was already loaded at boot time.) |
|
301 RDebug::Printf ("Loading USB LDD"); |
|
302 TUSB_PRINT1("Loading USB LDD ",lddPtr->iName.PtrZ()); |
|
303 r = User::LoadLogicalDevice(lddPtr->iName); |
|
304 test(r == KErrNone || r == KErrAlreadyExists); |
|
305 |
|
306 IFConfigPtr ifPtr = lddPtr->iIFPtr; |
|
307 |
|
308 RDebug::Printf ("Opening Channels"); |
|
309 for (TInt portNumber = nextPort; portNumber < nextPort+lddPtr->iNumChannels; portNumber++) |
|
310 { |
|
311 test_Compare(lddPtr->iNumChannels,>,0); |
|
312 test_Compare(lddPtr->iNumChannels,==,1); |
|
313 |
|
314 // Open USB channel |
|
315 r = iPort[portNumber].Open(0); |
|
316 test_KErrNone(r); |
|
317 TUSB_PRINT("Successfully opened USB port"); |
|
318 |
|
319 // Query the USB device/Setup the USB interface |
|
320 if (portNumber == nextPort) |
|
321 { |
|
322 // Change some descriptors to contain suitable values |
|
323 //SetupDescriptors(lddPtr, &iPort[portNumber]); |
|
324 } |
|
325 |
|
326 |
|
327 test_NotNull(ifPtr); |
|
328 |
|
329 if (iSupportResourceAllocationV2) |
|
330 { |
|
331 PopulateInterfaceResourceAllocation(ifPtr, portNumber); |
|
332 } |
|
333 |
|
334 SetupInterface(&ifPtr,portNumber); |
|
335 |
|
336 #ifdef USB_SC |
|
337 // RChunk *tChunk = &gChunk; |
|
338 test_KErrNone(iPort[portNumber].FinalizeInterface()); |
|
339 #endif |
|
340 |
|
341 } |
|
342 |
|
343 iTotalChannels += lddPtr->iNumChannels; |
|
344 nextPort += lddPtr->iNumChannels; |
|
345 lddPtr = lddPtr->iPtrNext; |
|
346 } |
|
347 |
|
348 TUSB_PRINT("All Interfaces and Alternate Settings successfully set up"); |
|
349 |
|
350 iTransferHandle->StartTimer(); |
|
351 |
|
352 return KErrNone; |
|
353 } |
|
354 |
|
355 void CTransferServer::QueryUsbClientL(LDDConfigPtr aLddPtr, RDEVCLIENT* aPort) |
|
356 { |
|
357 test.Start(_L("Query device and Endpoint Capabilities")); |
|
358 |
|
359 |
|
360 TUsbDeviceCaps d_caps; |
|
361 TInt r = aPort->DeviceCaps(d_caps); |
|
362 test_KErrNone(r); |
|
363 |
|
364 const TInt n = d_caps().iTotalEndpoints; |
|
365 |
|
366 TUSB_PRINT("### USB device capabilities:"); |
|
367 TUSB_PRINT1("Number of endpoints: %d", n); |
|
368 TUSB_PRINT1("Supports Software-Connect: %s", |
|
369 d_caps().iConnect ? _S("yes") : _S("no")); |
|
370 TUSB_PRINT1("Device is Self-Powered: %s", |
|
371 d_caps().iSelfPowered ? _S("yes") : _S("no")); |
|
372 TUSB_PRINT1("Supports Remote-Wakeup: %s", |
|
373 d_caps().iRemoteWakeup ? _S("yes") : _S("no")); |
|
374 TUSB_PRINT1("Supports High-speed: %s", |
|
375 d_caps().iHighSpeed ? _S("yes") : _S("no")); |
|
376 TUSB_PRINT1("Supports unpowered cable detection: %s\n", |
|
377 (d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_CableDetectWithoutPower) ? |
|
378 _S("yes") : _S("no")); |
|
379 TUSB_PRINT1("Supports endpoint resource allocation v2 scheme: %s\n", |
|
380 (d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) ? |
|
381 _S("yes") : _S("no")); |
|
382 TUSB_PRINT(""); |
|
383 |
|
384 iSoftwareConnect = d_caps().iConnect; // we need to remember this |
|
385 test_Equal(aLddPtr->iSoftConnect,iSoftwareConnect); |
|
386 |
|
387 iSupportResourceAllocationV2 = ((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) != 0); |
|
388 |
|
389 // only check capabilities if set; therefore allowing them to be disabled |
|
390 if (aLddPtr->iSelfPower) |
|
391 { |
|
392 test(d_caps().iSelfPowered); |
|
393 } |
|
394 |
|
395 // only check capabilities if set; therefore allowing them to be disabled |
|
396 if (aLddPtr->iRemoteWakeup) |
|
397 { |
|
398 test(d_caps().iRemoteWakeup); |
|
399 } |
|
400 |
|
401 test_Equal(d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_CableDetectWithoutPower,aLddPtr->iFeatures); |
|
402 |
|
403 // only check capability if set; therefore allowing it to be disabled |
|
404 if (aLddPtr->iHighSpeed) |
|
405 { |
|
406 test(d_caps().iHighSpeed); |
|
407 } |
|
408 |
|
409 test_Equal(aLddPtr->iNumEndpoints,n); |
|
410 |
|
411 // Endpoints |
|
412 TUsbcEndpointData data[KUsbcMaxEndpoints]; |
|
413 TPtr8 dataptr(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data)); |
|
414 r = aPort->EndpointCaps(dataptr); |
|
415 test_KErrNone(r); |
|
416 |
|
417 TUSB_PRINT("### USB device endpoint capabilities:"); |
|
418 for (TInt i = 0; i < n; i++) |
|
419 { |
|
420 const TUsbcEndpointCaps* caps = &data[i].iCaps; |
|
421 |
|
422 |
|
423 TBuf<40> sizeStr(_S("unknown")); |
|
424 if (caps->iSizes == KUsbEpNotAvailable) |
|
425 { |
|
426 sizeStr = _S("Not Available"); |
|
427 } |
|
428 else |
|
429 { |
|
430 sizeStr.SetLength(0); |
|
431 if (caps->iSizes & KUsbEpSizeCont) |
|
432 sizeStr.Append(_S(" Continuous"),11); |
|
433 if (caps->iSizes & KUsbEpSize8) |
|
434 sizeStr.Append(_S(" 8"),2); |
|
435 if (caps->iSizes & KUsbEpSize16) |
|
436 sizeStr.Append(_S(" 16"),3); |
|
437 if (caps->iSizes & KUsbEpSize32) |
|
438 sizeStr.Append(_S(" 32"),3); |
|
439 if (caps->iSizes & KUsbEpSize64) |
|
440 sizeStr.Append(_S(" 64"),3); |
|
441 if (caps->iSizes & KUsbEpSize128) |
|
442 sizeStr.Append(_S(" 128"),4); |
|
443 if (caps->iSizes & KUsbEpSize256) |
|
444 sizeStr.Append(_S(" 256"),4); |
|
445 if (caps->iSizes & KUsbEpSize512) |
|
446 sizeStr.Append(_S(" 512"),4); |
|
447 if (caps->iSizes & KUsbEpSize1023) |
|
448 sizeStr.Append(_S(" 1023"),5); |
|
449 if (caps->iSizes & KUsbEpSize1024) |
|
450 sizeStr.Append(_S(" 1024"),5); |
|
451 } |
|
452 |
|
453 TBuf<40> typeStr(_S("unknown")); |
|
454 if (caps->iTypesAndDir == KUsbEpNotAvailable) |
|
455 typeStr = _S("Not Available"); |
|
456 if (caps->iTypesAndDir & (KUsbEpTypeControl | KUsbEpTypeBulk | KUsbEpTypeInterrupt | KUsbEpTypeIsochronous)) |
|
457 { |
|
458 typeStr.SetLength(0); |
|
459 if (caps->iTypesAndDir & KUsbEpTypeBulk) |
|
460 typeStr.Append(_S("Control "),8); |
|
461 if (caps->iTypesAndDir & KUsbEpTypeBulk) |
|
462 typeStr.Append(_S("Bulk "),5); |
|
463 if (caps->iTypesAndDir & KUsbEpTypeInterrupt) |
|
464 typeStr.Append(_S("Interrupt "),10); |
|
465 if (caps->iTypesAndDir & KUsbEpTypeIsochronous) |
|
466 typeStr.Append(_S("Isochronous"),11); |
|
467 } |
|
468 |
|
469 TBuf<20> directionStr(_S("unknown")); |
|
470 |
|
471 if (caps->iTypesAndDir & KUsbEpDirIn) |
|
472 directionStr = _S("In"); |
|
473 if (caps->iTypesAndDir & KUsbEpDirOut) |
|
474 directionStr = _S("Out"); |
|
475 if (caps->iTypesAndDir & KUsbEpDirBidirect) |
|
476 directionStr = _S("Both"); |
|
477 |
|
478 TUSB_PRINT4("Endpoint:%d Sizes =%s Type = %s - %s", |
|
479 i+1,sizeStr.PtrZ(), typeStr.PtrZ(), directionStr.PtrZ()); |
|
480 } |
|
481 TUSB_PRINT(""); |
|
482 |
|
483 test.End(); |
|
484 |
|
485 } |
|
486 |