|
1 /* |
|
2 * Copyright (c) 2007-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 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 /** |
|
19 @file |
|
20 @internalComponent |
|
21 */ |
|
22 |
|
23 #include "fdf.h" |
|
24 #include <usb/usblogger.h> |
|
25 #include "utils.h" |
|
26 #include <usbhost/internal/fdcplugin.hrh> |
|
27 #include "eventqueue.h" |
|
28 |
|
29 #ifdef __FLOG_ACTIVE |
|
30 _LIT8(KLogComponent, "fdf "); |
|
31 #endif |
|
32 |
|
33 _LIT(KDriverUsbhubLddFileName,"usbhubdriver"); |
|
34 _LIT(KDriverUsbdiLddFileName,"usbdi"); |
|
35 |
|
36 PANICCATEGORY("fdf"); |
|
37 |
|
38 const TUint KVendorSpecificDeviceClassValue = 0xFF; |
|
39 const TUint KVendorSpecificInterfaceClassValue = 0xFF; |
|
40 const TUint KMaxSearchKeyLength = 64; |
|
41 |
|
42 // Factory function for TInterfaceInfo objects. |
|
43 CFdf::TInterfaceInfo* CFdf::TInterfaceInfo::NewL(RPointerArray<CFdf::TInterfaceInfo>& aInterfaces) |
|
44 { |
|
45 LOG_STATIC_FUNC_ENTRY |
|
46 |
|
47 TInterfaceInfo* self = new(ELeave) TInterfaceInfo; |
|
48 CleanupStack::PushL(self); |
|
49 aInterfaces.AppendL(self); |
|
50 CLEANUPSTACK_POP1(self); |
|
51 return self; |
|
52 } |
|
53 |
|
54 |
|
55 CFdf* CFdf::NewL() |
|
56 { |
|
57 LOG_STATIC_FUNC_ENTRY |
|
58 |
|
59 CFdf* self = new(ELeave) CFdf; |
|
60 CleanupStack::PushL(self); |
|
61 self->ConstructL(); |
|
62 CLEANUPSTACK_POP1(self); |
|
63 return self; |
|
64 } |
|
65 |
|
66 CFdf::CFdf() |
|
67 : iDevices(_FOFF(CDeviceProxy, iLink)), |
|
68 iFunctionDrivers(_FOFF(CFdcProxy, iLink)) |
|
69 { |
|
70 LOG_FUNC |
|
71 } |
|
72 |
|
73 void CFdf::ConstructL() |
|
74 { |
|
75 LOG_FUNC |
|
76 |
|
77 #ifndef __OVER_DUMMYUSBDI__ |
|
78 // If we're using the DummyUSBDI we don't need the real USBDI. |
|
79 TInt err = User::LoadLogicalDevice(KDriverUsbhubLddFileName); |
|
80 if ( err != KErrAlreadyExists ) |
|
81 { |
|
82 LEAVEIFERRORL(err); |
|
83 } |
|
84 #endif // __OVER_DUMMYUSBDI__ |
|
85 |
|
86 LEAVEIFERRORL(iHubDriver.Open()); |
|
87 |
|
88 #ifdef __OVER_DUMMYUSBDI__ |
|
89 LEAVEIFERRORL(iHubDriver.StartHost()); |
|
90 #endif |
|
91 |
|
92 iActiveWaitForBusEvent = CActiveWaitForBusEvent::NewL(iHubDriver, iBusEvent, *this); |
|
93 iActiveWaitForBusEvent->Wait(); |
|
94 |
|
95 CreateFunctionDriverProxiesL(); |
|
96 |
|
97 iActiveWaitForEComEvent = CActiveWaitForEComEvent::NewL(*this); |
|
98 iActiveWaitForEComEvent->Wait(); |
|
99 |
|
100 iEventQueue = CEventQueue::NewL(*this); |
|
101 } |
|
102 |
|
103 void CFdf::CreateFunctionDriverProxiesL() |
|
104 { |
|
105 |
|
106 LOG_FUNC |
|
107 REComSession::ListImplementationsL(TUid::Uid(KFdcEcomInterfaceUid), iImplInfoArray); |
|
108 const TUint count = iImplInfoArray.Count(); |
|
109 LOGTEXT2(_L8("\tiImplInfoArray.Count() upon FDF creation = %d"), count); |
|
110 #ifdef __FLOG_ACTIVE |
|
111 if ( count == 0 ) |
|
112 { |
|
113 LOGTEXT(_L8("\tTHERE ARE NO FUNCTION DRIVERS PRESENT IN THE SYSTEM")); |
|
114 } |
|
115 else |
|
116 { |
|
117 for (TInt kk = 0; kk < count; ++kk) |
|
118 LOGTEXT3(_L8("\t\tFDC implementation Index:%d UID: 0x%08x"), kk, iImplInfoArray[kk]->ImplementationUid()); |
|
119 } |
|
120 #endif |
|
121 |
|
122 for ( TUint i = 0 ; i < count ; ++i ) |
|
123 { |
|
124 CFdcProxy* proxy = CFdcProxy::NewL(*this, *iImplInfoArray[i]); |
|
125 |
|
126 // If this proxy is rom based then put it in the first place |
|
127 // this will save time when trying to load the FDC with the rule of |
|
128 // ROM-based ones have higher priority than installed ones. |
|
129 if (proxy->RomBased()) |
|
130 iFunctionDrivers.AddFirst(*proxy); |
|
131 else |
|
132 iFunctionDrivers.AddLast(*proxy); |
|
133 } |
|
134 } |
|
135 |
|
136 CFdf::~CFdf() |
|
137 { |
|
138 LOG_FUNC |
|
139 |
|
140 // Mimic the detachment of each attached device. |
|
141 TSglQueIter<CDeviceProxy> deviceIter(iDevices); |
|
142 deviceIter.SetToFirst(); |
|
143 CDeviceProxy* device; |
|
144 while ( ( device = deviceIter++ ) != NULL ) |
|
145 { |
|
146 const TUint deviceId = device->DeviceId(); |
|
147 LOGTEXT2(_L8("\tmimicking detachment of device with id %d"), device); |
|
148 TellFdcsOfDeviceDetachment(deviceId); |
|
149 iDevices.Remove(*device); |
|
150 delete device; |
|
151 } |
|
152 |
|
153 // Destroy all the FDC proxies. They should each now have no 'attached |
|
154 // devices' and no plugin instance. |
|
155 TSglQueIter<CFdcProxy> fdcIter(iFunctionDrivers); |
|
156 fdcIter.SetToFirst(); |
|
157 CFdcProxy* fdc; |
|
158 while ( ( fdc = fdcIter++ ) != NULL ) |
|
159 { |
|
160 iFunctionDrivers.Remove(*fdc); |
|
161 delete fdc; |
|
162 } |
|
163 |
|
164 delete iActiveWaitForBusEvent; |
|
165 |
|
166 delete iActiveWaitForEComEvent; |
|
167 |
|
168 if ( iHubDriver.Handle() ) |
|
169 { |
|
170 iHubDriver.StopHost(); // NB this has no return value |
|
171 } |
|
172 iHubDriver.Close(); |
|
173 |
|
174 #ifndef __OVER_DUMMYUSBDI__ |
|
175 //If we're using the DummyUSBDI the real USBDI isn't loaded. |
|
176 TInt err = User::FreeLogicalDevice(KDriverUsbhubLddFileName); |
|
177 LOGTEXT2(_L8("\tFreeLogicalDevice( usbhubdriver ) returned %d"), err); |
|
178 |
|
179 err = User::FreeLogicalDevice(KDriverUsbdiLddFileName); |
|
180 LOGTEXT2(_L8("\tFreeLogicalDevice( usbdi ) returned %d"), err); |
|
181 #endif // __OVER_DUMMYUSBDI__ |
|
182 |
|
183 delete iEventQueue; |
|
184 |
|
185 // This is a worthwhile check to do at this point. If we ever don't clean |
|
186 // up iInterfaces at the *right* time, then this will be easier to debug |
|
187 // than a memory leak. |
|
188 ASSERT_DEBUG(iInterfaces.Count() == 0); |
|
189 |
|
190 iImplInfoArray.ResetAndDestroy(); |
|
191 REComSession::FinalClose(); |
|
192 } |
|
193 |
|
194 void CFdf::EnableDriverLoading() |
|
195 { |
|
196 LOG_FUNC |
|
197 |
|
198 iDriverLoadingEnabled = ETrue; |
|
199 } |
|
200 |
|
201 void CFdf::DisableDriverLoading() |
|
202 { |
|
203 LOG_FUNC |
|
204 |
|
205 iDriverLoadingEnabled = EFalse; |
|
206 } |
|
207 |
|
208 void CFdf::SetSession(CFdfSession* aSession) |
|
209 { |
|
210 LOG_FUNC |
|
211 LOGTEXT2(_L8("\taSession = 0x%08x"), aSession); |
|
212 |
|
213 iSession = aSession; |
|
214 } |
|
215 |
|
216 CFdfSession* CFdf::Session() |
|
217 { |
|
218 return iSession; |
|
219 } |
|
220 |
|
221 TBool CFdf::GetDeviceEvent(TDeviceEvent& aEvent) |
|
222 { |
|
223 LOG_FUNC |
|
224 |
|
225 ASSERT_DEBUG(iEventQueue); |
|
226 return iEventQueue->GetDeviceEvent(aEvent); |
|
227 } |
|
228 |
|
229 TBool CFdf::GetDevmonEvent(TInt& aEvent) |
|
230 { |
|
231 LOG_FUNC |
|
232 |
|
233 ASSERT_DEBUG(iEventQueue); |
|
234 return iEventQueue->GetDevmonEvent(aEvent); |
|
235 } |
|
236 |
|
237 |
|
238 // An ECom plugin has been installed or removed |
|
239 void CFdf::EComEventReceived() |
|
240 { |
|
241 TRAPD(ret, HandleEComEventReceivedL()); |
|
242 if (ret != KErrNone) |
|
243 HandleDevmonEvent(KErrUsbUnableToUpdateFDProxyList); |
|
244 |
|
245 } |
|
246 |
|
247 void CFdf::HandleEComEventReceivedL() |
|
248 { |
|
249 LOG_FUNC |
|
250 |
|
251 // There is no way to filter ecom notification to only receive ones we are interested in, also there is no way |
|
252 // to query ecom as to what has changed. Hence there is no option but to call ListImplementations(). |
|
253 iImplInfoArray.ResetAndDestroy(); |
|
254 |
|
255 REComSession::ListImplementationsL(TUid::Uid(KFdcEcomInterfaceUid), iImplInfoArray); |
|
256 TUint implementationsCount = iImplInfoArray.Count(); |
|
257 LOGTEXT2(_L8("\tiImplInfoArray.Count() after ECom notification= %d"), implementationsCount); |
|
258 |
|
259 #ifdef __FLOG_ACTIVE |
|
260 if ( implementationsCount == 0 ) |
|
261 { |
|
262 LOGTEXT(_L8("\tTHERE ARE NO FUNCTION DRIVERS PRESENT IN THE SYSTEM")); |
|
263 } |
|
264 |
|
265 TSglQueIter<CFdcProxy> proxiesIterDebug(iFunctionDrivers); |
|
266 CFdcProxy* fdcDebug = NULL; |
|
267 while ( ( fdcDebug = proxiesIterDebug++ ) != NULL ) |
|
268 { |
|
269 TUid fdcUid = fdcDebug->ImplUid(); |
|
270 LOGTEXT2(_L8("\t\tOld FDC Proxy implementation UID: 0x%08x"), fdcUid.iUid); |
|
271 TInt fdcVersion = fdcDebug->Version(); |
|
272 LOGTEXT2(_L8("\t\tFDC Proxy version UID: %d"), fdcVersion); |
|
273 } |
|
274 LOGTEXT(_L8("\t\t------------------------------------------------------------------")); |
|
275 for (TInt kk = 0; kk < implementationsCount; ++kk) |
|
276 { |
|
277 TUid fdcUid2 = iImplInfoArray[kk]->ImplementationUid(); |
|
278 LOGTEXT2(_L8("\t\tNew FDC Proxy implementation UID: 0x%08x"), fdcUid2.iUid); |
|
279 TInt fdcVersion2 = iImplInfoArray[kk]->Version(); |
|
280 LOGTEXT2(_L8("\t\tFDC Proxy version UID: %d"), fdcVersion2); |
|
281 } |
|
282 #endif |
|
283 |
|
284 // See if any relevant FDCs (or upgrades) have been installed or uninstalled: |
|
285 |
|
286 // For each FD in the proxy list compare the uid and version with each FD returned by ECom looking |
|
287 // for the removal, upgrade or downgrade of an existing FD |
|
288 TSglQueIter<CFdcProxy> proxiesIter(iFunctionDrivers); |
|
289 proxiesIter.SetToFirst(); |
|
290 CFdcProxy* fdc = NULL; |
|
291 while ( ( fdc = proxiesIter++ ) != NULL ) |
|
292 { |
|
293 TBool fdcRemoved = ETrue; |
|
294 for (TInt ii = 0; ii < implementationsCount; ++ii) |
|
295 { |
|
296 if (fdc->ImplUid() == iImplInfoArray[ii]->ImplementationUid()) |
|
297 { |
|
298 // We have found an upgrade, downgrade, or duplicate (a duplicate could occur in the situation |
|
299 // where an FD has been installed, then a device attached, then the FD uninstalled and re-installed *while* |
|
300 // the device is still attached (meaning the FD's proxy is still in the proxy list but will have been marked |
|
301 // for deletion when the uninstallation was detected). |
|
302 fdcRemoved = EFalse; |
|
303 if (fdc->Version() != iImplInfoArray[ii]->Version()) |
|
304 { |
|
305 // We've found an upgrade or a downgrade. Note that the upgrade FD proxy needs adding to the |
|
306 // proxy list, however that isn't done here it is done later in the loop that is searching for |
|
307 // new FDs. This is to prevent its possible duplicate addition [consider the situation where |
|
308 // there is FDv1 and a device is attached, then while still attached FDv2 gets installed (while will |
|
309 // result in FDv1 getting marked for deletion), then another device is attached which will use FDv2. |
|
310 // Now if FDv3 is installed before any of the devices were detached there will be two proxies in the |
|
311 // proxy list with the same UID but differing version numbers. If FDv3 is added here it will therefore |
|
312 // be added twice]. |
|
313 if (fdc->DeviceCount()) |
|
314 { |
|
315 // The device using the FD is still attached |
|
316 fdc->MarkForDeletion(); |
|
317 } |
|
318 else |
|
319 { |
|
320 iFunctionDrivers.Remove(*fdc); |
|
321 delete fdc; |
|
322 } |
|
323 } |
|
324 else |
|
325 { |
|
326 // we've found an FD being installed which is still currently |
|
327 // active in the proxy list |
|
328 fdc->UnmarkForDeletion(); |
|
329 } |
|
330 // Since we found the plugin with the same implementationUid |
|
331 // we could simply bail out to stop the looping; |
|
332 break; |
|
333 } |
|
334 } |
|
335 if (fdcRemoved) |
|
336 { |
|
337 // An FDC has been uninstalled - if the FDC isn't in use remove it |
|
338 // otherwise mark it for deletion |
|
339 if (fdc->DeviceCount()) |
|
340 fdc->MarkForDeletion(); |
|
341 else |
|
342 { |
|
343 iFunctionDrivers.Remove(*fdc); |
|
344 delete fdc; |
|
345 } |
|
346 } |
|
347 } |
|
348 |
|
349 |
|
350 // For each FD returned by ECom, search and compare with the FD proxy list |
|
351 // looking for new FDs |
|
352 for (TInt ii = 0; ii < implementationsCount; ++ii) |
|
353 { |
|
354 TBool newFdcFound = ETrue; |
|
355 proxiesIter.SetToFirst(); |
|
356 while ( ( fdc = proxiesIter++ ) != NULL ) |
|
357 { |
|
358 if (fdc->ImplUid() == iImplInfoArray[ii]->ImplementationUid() && fdc->Version() == iImplInfoArray[ii]->Version()) |
|
359 { |
|
360 // No need to create a new proxy if there is one with a matching UID and version. |
|
361 newFdcFound = EFalse; |
|
362 |
|
363 // We break out this loop for efficiency. |
|
364 break; |
|
365 } |
|
366 } |
|
367 |
|
368 if (newFdcFound) |
|
369 { |
|
370 // A new or upgrade FDC has been installed onto the device |
|
371 CFdcProxy* proxy = CFdcProxy::NewL(*this, *iImplInfoArray[ii]); |
|
372 |
|
373 // If this proxy is rom based then put it in the first place |
|
374 // this will save time when trying to load the FDC with the rule that |
|
375 // ROM-based ones have higher priority than installed ones. |
|
376 if (proxy->RomBased()) |
|
377 iFunctionDrivers.AddFirst(*proxy); |
|
378 else |
|
379 iFunctionDrivers.AddLast(*proxy); |
|
380 } |
|
381 } |
|
382 } |
|
383 |
|
384 // A bus event has occurred. |
|
385 void CFdf::MbeoBusEvent() |
|
386 { |
|
387 LOG_FUNC |
|
388 LOGTEXT2(_L8("\tiBusEvent.iEventType = %d"), iBusEvent.iEventType); |
|
389 LOGTEXT2(_L8("\tiBusEvent.iError = %d"), iBusEvent.iError); |
|
390 LOGTEXT2(_L8("\tiBusEvent.iDeviceHandle = %d"), iBusEvent.iDeviceHandle); |
|
391 |
|
392 switch ( iBusEvent.iEventType ) |
|
393 { |
|
394 case RUsbHubDriver::TBusEvent::EDeviceAttached: |
|
395 if ( !iBusEvent.iError ) |
|
396 { |
|
397 // So far, a successful attachment. |
|
398 HandleDeviceAttachment(iBusEvent.iDeviceHandle); |
|
399 } |
|
400 else |
|
401 { |
|
402 // It was an attachment failure. Simply tell the event queue. |
|
403 ASSERT_DEBUG(iEventQueue); |
|
404 iEventQueue->AttachmentFailure(iBusEvent.iError); |
|
405 } |
|
406 break; |
|
407 |
|
408 case RUsbHubDriver::TBusEvent::EDeviceRemoved: |
|
409 // Device detachments are always 'KErrNone'. If the device was |
|
410 // pseudo-detached due to an overcurrent condition (for instance) then |
|
411 // the overcurrent condition is indicated through the devmon API (i.e. |
|
412 // EDevMonEvent) and the detachment is still 'KErrNone'. |
|
413 ASSERT_DEBUG(iBusEvent.iError == KErrNone); |
|
414 HandleDeviceDetachment(iBusEvent.iDeviceHandle); |
|
415 break; |
|
416 |
|
417 case RUsbHubDriver::TBusEvent::EDevMonEvent: |
|
418 HandleDevmonEvent(iBusEvent.iError); |
|
419 break; |
|
420 |
|
421 case RUsbHubDriver::TBusEvent::ENoEvent: |
|
422 default: |
|
423 break; |
|
424 } |
|
425 |
|
426 // Only re-post the notification when we've finished examining the |
|
427 // TBusEvent from the previous completion. (Otherwise it might get |
|
428 // overwritten.) |
|
429 iActiveWaitForBusEvent->Wait(); |
|
430 } |
|
431 |
|
432 // This is the central handler for device attachment. |
|
433 // We deal with device attachments in two phases. |
|
434 // The first phase is confusingly called device attachment. |
|
435 // The second phase is driver loading. |
|
436 void CFdf::HandleDeviceAttachment(TUint aDeviceId) |
|
437 { |
|
438 LOG_FUNC |
|
439 // This is filled in by HandleDeviceAttachmentL on success. |
|
440 CDeviceProxy* device; |
|
441 TRAPD(err, HandleDeviceAttachmentL(aDeviceId, device)); |
|
442 if ( err ) |
|
443 { |
|
444 LOGTEXT2(_L8("\terr = %d"), err); |
|
445 // There was an attachment failure, so we just increment the count of |
|
446 // attachment failures. |
|
447 ASSERT_DEBUG(iEventQueue); |
|
448 iEventQueue->AttachmentFailure(err); |
|
449 // If we failed the attachment phase, we can't try to load drivers for |
|
450 // the device. |
|
451 |
|
452 } |
|
453 else |
|
454 { |
|
455 // This function always moves the 'driver loading' event from the |
|
456 // device proxy created by HandleDeviceAttachmentL to the event queue. |
|
457 // This event object is always populated with the correct status and |
|
458 // error. |
|
459 ASSERT_DEBUG(device); |
|
460 DoDriverLoading(*device); |
|
461 } |
|
462 |
|
463 // Finally, clean up the collection of information on the device's |
|
464 // interfaces which was populated (maybe only partly) in |
|
465 // HandleDeviceAttachmentL. |
|
466 iCurrentDevice = NULL; |
|
467 iInterfaces.ResetAndDestroy(); |
|
468 } |
|
469 |
|
470 // This does the 'device attachment' phase of the new device attachment only. |
|
471 void CFdf::HandleDeviceAttachmentL(TUint aDeviceId, CDeviceProxy*& aDevice) |
|
472 { |
|
473 LOG_FUNC |
|
474 |
|
475 // Create the device proxy |
|
476 aDevice = CDeviceProxy::NewL(iHubDriver, aDeviceId); |
|
477 CleanupStack::PushL(aDevice); |
|
478 iCurrentDevice = aDevice; |
|
479 // Get necessary descriptors (for this phase) |
|
480 LEAVEIFERRORL(aDevice->GetDeviceDescriptor(iDD)); |
|
481 LOGTEXT2(_L8("\tiDD.USBBcd = 0x%04x"), iDD.USBBcd()); |
|
482 LOGTEXT2(_L8("\tiDD.DeviceClass = 0x%02x"), iDD.DeviceClass()); |
|
483 LOGTEXT2(_L8("\tiDD.DeviceSubClass = 0x%02x"), iDD.DeviceSubClass()); |
|
484 LOGTEXT2(_L8("\tiDD.DeviceProtocol = 0x%02x"), iDD.DeviceProtocol()); |
|
485 LOGTEXT2(_L8("\tiDD.MaxPacketSize0 = %d"), iDD.MaxPacketSize0()); |
|
486 LOGTEXT2(_L8("\tiDD.VendorId = 0x%04x"), iDD.VendorId()); |
|
487 LOGTEXT2(_L8("\tiDD.ProductId = 0x%04x"), iDD.ProductId()); |
|
488 LOGTEXT2(_L8("\tiDD.DeviceBcd = 0x%04x"), iDD.DeviceBcd()); |
|
489 LOGTEXT2(_L8("\tiDD.ManufacturerIndex = %d"), iDD.ManufacturerIndex()); |
|
490 LOGTEXT2(_L8("\tiDD.ProductIndex = %d"), iDD.ProductIndex()); |
|
491 LOGTEXT2(_L8("\tiDD.SerialNumberIndex = %d"), iDD.SerialNumberIndex()); |
|
492 LOGTEXT2(_L8("\tiDD.NumConfigurations = %d"), iDD.NumConfigurations()); |
|
493 LEAVEIFERRORL(aDevice->GetConfigurationDescriptor(iCD)); |
|
494 LOGTEXT2(_L8("\tiCD.TotalLength = %d"), iCD.TotalLength()); |
|
495 LOGTEXT2(_L8("\tiCD.NumInterfaces = %d"), iCD.NumInterfaces()); |
|
496 LOGTEXT2(_L8("\tiCD.ConfigurationValue = %d"), iCD.ConfigurationValue()); |
|
497 LOGTEXT2(_L8("\tiCD.ConfigurationIndex = %d"), iCD.ConfigurationIndex()); |
|
498 LOGTEXT2(_L8("\tiCD.Attributes = %d"), iCD.Attributes()); |
|
499 LOGTEXT2(_L8("\tiCD.MaxPower = %d"), iCD.MaxPower()); |
|
500 |
|
501 const TUint8 numberOfInterfaces = iCD.NumInterfaces(); |
|
502 LOGTEXT2(_L8("\tnumberOfInterfaces (field in config descriptor) = %d)"), numberOfInterfaces); |
|
503 if ( numberOfInterfaces == 0 ) |
|
504 { |
|
505 LEAVEL(KErrUsbConfigurationHasNoInterfaces); |
|
506 } |
|
507 |
|
508 // Walk the configuration bundle. Collect information on each interface |
|
509 // (its number, class, subclass and protocol). This populates iInterfaces. |
|
510 ASSERT_DEBUG(iInterfaces.Count() == 0); |
|
511 ASSERT_ALWAYS(iCurrentDevice); |
|
512 ParseL(iCD); |
|
513 |
|
514 // Log iInterfaces. |
|
515 const TUint interfaceCount = iInterfaces.Count(); |
|
516 LOGTEXT2(_L8("\tinterfaceCount (parsed from bundle) = %d"), interfaceCount); |
|
517 #ifdef __FLOG_ACTIVE |
|
518 LOGTEXT(_L8("\tLogging iInterfaces:")); |
|
519 for ( TUint ii = 0 ; ii < interfaceCount ; ++ii ) |
|
520 { |
|
521 const TInterfaceInfo* ifInfo = iInterfaces[ii]; |
|
522 ASSERT_DEBUG(ifInfo); |
|
523 LOGTEXT6(_L8("\t\tiInterfaces[%d]: number %d, interface class 0x%02x subclass 0x%02x protocol 0x%02x"), |
|
524 ii, |
|
525 ifInfo->iNumber, |
|
526 ifInfo->iClass, |
|
527 ifInfo->iSubclass, |
|
528 ifInfo->iProtocol |
|
529 ); |
|
530 } |
|
531 #endif |
|
532 |
|
533 // Check that the config's NumInterfaces is the same as the actual number |
|
534 // of interface descriptors we found. We rely on this later on. |
|
535 if ( numberOfInterfaces != interfaceCount ) |
|
536 { |
|
537 LEAVEL(KErrUsbInterfaceCountMismatch); |
|
538 } |
|
539 |
|
540 // Check that each interface number in iInterfaces is unique. |
|
541 if ( interfaceCount > 1 ) |
|
542 { |
|
543 for ( TUint ii = 0 ; ii < interfaceCount ; ++ii ) |
|
544 { |
|
545 const TInterfaceInfo* lhs = iInterfaces[ii]; |
|
546 ASSERT_DEBUG(lhs); |
|
547 for ( TUint jj = ii+1 ; jj < interfaceCount ; ++jj ) |
|
548 { |
|
549 const TInterfaceInfo* rhs = iInterfaces[jj]; |
|
550 ASSERT_DEBUG(rhs); |
|
551 if ( lhs->iNumber == rhs->iNumber ) |
|
552 { |
|
553 LEAVEL(KErrUsbDuplicateInterfaceNumbers); |
|
554 } |
|
555 } |
|
556 } |
|
557 } |
|
558 |
|
559 #ifndef __OVER_DUMMYUSBDI__ |
|
560 // If we're using the DummyUSBDI we don't need the real USBDI. |
|
561 // Load USBDI when attached devices goes from 0 to 1 |
|
562 if (iDevices.IsEmpty()) |
|
563 { |
|
564 TInt err = User::LoadLogicalDevice(KDriverUsbdiLddFileName); |
|
565 if ( err != KErrAlreadyExists ) |
|
566 { |
|
567 LEAVEIFERRORL(err); |
|
568 } |
|
569 } |
|
570 #endif // __OVER_DUMMYUSBDI__ |
|
571 |
|
572 // Now we know we've succeeded with a device attachment, remove the device |
|
573 // proxy from the cleanup stack and put it on the TSglQue. |
|
574 CLEANUPSTACK_POP1(aDevice); |
|
575 iDevices.AddLast(*aDevice); |
|
576 // Also put an event on the event queue. |
|
577 TDeviceEvent* const attachmentEvent = aDevice->GetAttachmentEventObject(); |
|
578 ASSERT_DEBUG(attachmentEvent); |
|
579 attachmentEvent->iInfo.iVid = iDD.VendorId(); |
|
580 attachmentEvent->iInfo.iPid = iDD.ProductId(); |
|
581 attachmentEvent->iInfo.iError = KErrNone; |
|
582 ASSERT_DEBUG(iEventQueue); |
|
583 iEventQueue->AddDeviceEvent(*attachmentEvent); |
|
584 LOGTEXT2(_L8("***USB HOST STACK: SUCCESSFUL ATTACHMENT OF DEVICE (id %d)"), aDeviceId); |
|
585 } |
|
586 |
|
587 void CFdf::DoDriverLoading(CDeviceProxy& aDevice) |
|
588 { |
|
589 LOG_FUNC |
|
590 |
|
591 // Leaving or returning from DoDriverLoadingL is the trigger to put the |
|
592 // 'driver loading' event object on the event queue. It must already have |
|
593 // been populated correctly (the actual error code it left with doesn't |
|
594 // feed into the driver loading event). |
|
595 TRAP_IGNORE(DoDriverLoadingL(aDevice)); |
|
596 |
|
597 TDeviceEvent* const driverLoadingEvent = aDevice.GetDriverLoadingEventObject(); |
|
598 ASSERT_DEBUG(driverLoadingEvent); |
|
599 // The driver loading event object says whether driver loading succeeded |
|
600 // (all interfaces were claimed without error), partly succeeded (not all |
|
601 // interfaces were claimed without error), or failed (no interfaces were |
|
602 // claimed without error). This information is intended for USBMAN so it |
|
603 // can tell the user, but we also use it now to suspend the device if |
|
604 // driver loading failed completely. |
|
605 if ( driverLoadingEvent->iInfo.iDriverLoadStatus == EDriverLoadFailure ) |
|
606 { |
|
607 // We can't do anything with error here. Suspending the device is for |
|
608 // power-saving reasons and is not critical. |
|
609 (void)aDevice.Suspend(); |
|
610 } |
|
611 ASSERT_DEBUG(iEventQueue); |
|
612 iEventQueue->AddDeviceEvent(*driverLoadingEvent); |
|
613 } |
|
614 |
|
615 |
|
616 void CFdf::DoDriverLoadingL(CDeviceProxy& aDevice) |
|
617 { |
|
618 LOG_FUNC |
|
619 |
|
620 // Check whether driver loading is enabled. |
|
621 if ( !iDriverLoadingEnabled ) |
|
622 { |
|
623 // Complete driver load failure scenario. |
|
624 aDevice.SetDriverLoadingEventData(EDriverLoadFailure, KErrUsbDriverLoadingDisabled); |
|
625 LEAVEL(KErrGeneral); |
|
626 } |
|
627 |
|
628 |
|
629 // Set this member up so that when the FDC calls TokenForInterface we call |
|
630 // the right proxy object. |
|
631 |
|
632 TInt collectedErr = KErrNone; |
|
633 TBool anySuccess = EFalse; |
|
634 |
|
635 |
|
636 // Now actually try to load the drivers. |
|
637 // Device drivers are located based upon descriptor information from the USB device. The first search is |
|
638 // based on information from the device descriptor and looks for a driver that matches the whole device; |
|
639 // the second search is based upon locating a driver for each interface within a configuration. |
|
640 // The particular keys used in the driver search are defined in the Universal Serial Bus Common Class |
|
641 // Specification version 1.0. They are represented by TDeviceSearchKeys and TInterfaceSearchKeys. |
|
642 // |
|
643 // First perform a device search by iterating through the keys in TDeviceSearchKeys looking for a matching driver. |
|
644 TBool functionDriverFound = SearchForADeviceFunctionDriverL(aDevice, anySuccess, collectedErr); |
|
645 |
|
646 // When do the parsing against the CD bundle, we already know if there is IAD(Interface Association Descriptor) |
|
647 // in the new attached device. Once we finished the device level searching of FDC and we couldn't find any, we |
|
648 // break down the loading process |
|
649 if (aDevice.HasIADFlag() && !functionDriverFound) |
|
650 { |
|
651 aDevice.SetDriverLoadingEventData(EDriverLoadFailure, KErrUsbUnsupportedDevice); |
|
652 LEAVEL(KErrGeneral); |
|
653 } |
|
654 // If a device FD is found then it is supposed to claim all the interfaces, if it didn't then report |
|
655 // a partial success but don't offer unclaimed interfaces to any other FD. |
|
656 const TUint interfaceCount = iInterfaces.Count(); |
|
657 |
|
658 |
|
659 |
|
660 // If no device driver was found then next perform an Interface search |
|
661 if (!functionDriverFound) |
|
662 SearchForInterfaceFunctionDriversL(aDevice, anySuccess, collectedErr); |
|
663 |
|
664 // Now worry about the following: |
|
665 // (a) are there any unclaimed interfaces remaining? |
|
666 // (b) what's in collectedErr? |
|
667 // Whether all interfaces were taken, some, or none, collectedErr may have |
|
668 // an error in it or KErrNone. We use specific error codes in some cases. |
|
669 TUint unclaimedInterfaces = UnclaimedInterfaceCount(); |
|
670 LOGTEXT2(_L8("\tunclaimedInterfaces = %d"), unclaimedInterfaces); |
|
671 LOGTEXT2(_L8("\tanySuccess = %d"), anySuccess); |
|
672 LOGTEXT2(_L8("\tcollectedErr = %d"), collectedErr); |
|
673 ASSERT_DEBUG(unclaimedInterfaces <= interfaceCount); |
|
674 |
|
675 if(iDeviceDetachedTooEarly) |
|
676 { |
|
677 LOGTEXT(_L8("\tDevice has been detached too early!")); |
|
678 iDeviceDetachedTooEarly = EFalse; |
|
679 // the choice of having the status to be EDriverLoadPartialSuccess |
|
680 // was not to clash with trying to suspend the device because |
|
681 // of a total failure to load the FD.(because device is detached) |
|
682 // even though that a FDC has been created |
|
683 // see the : |
|
684 // if ( driverLoadingEvent->iInfo.iDriverLoadStatus == EDriverLoadFailure ) |
|
685 // in function above => void CFdf::DoDriverLoadingL(etc...) |
|
686 aDevice.SetDriverLoadingEventData(EDriverLoadPartialSuccess, KErrUsbDeviceDetachedDuringDriverLoading); |
|
687 } |
|
688 else |
|
689 { |
|
690 SetFailureStatus(unclaimedInterfaces, interfaceCount, anySuccess, collectedErr, aDevice); |
|
691 }// iDeviceDetachedTooEarly |
|
692 |
|
693 } |
|
694 |
|
695 // Recursive function, originally called with the configuration descriptor. |
|
696 // Builds up information on the interface descriptors in the configuration |
|
697 // bundle. |
|
698 void CFdf::ParseL(TUsbGenericDescriptor& aDesc) |
|
699 { |
|
700 LOG_FUNC |
|
701 LOGTEXT2(_L8("\t&aDesc = 0x%08x"), &aDesc); |
|
702 LOGTEXT2(_L8("\taDesc.ibDescriptorType = %d"), aDesc.ibDescriptorType); |
|
703 LOGTEXT2(_L8("\taDesc.iFirstChild = 0x%08x"), aDesc.iFirstChild); |
|
704 LOGTEXT2(_L8("\taDesc.iNextPeer = 0x%08x"), aDesc.iNextPeer); |
|
705 |
|
706 if ( aDesc.ibDescriptorType == EInterface ) |
|
707 { |
|
708 // Add interface information to collection, but only if it's alternate |
|
709 // setting 0. |
|
710 const TUsbInterfaceDescriptor& ifDesc = static_cast<TUsbInterfaceDescriptor&>(aDesc); |
|
711 if ( ifDesc.AlternateSetting() == 0 ) // hard-coded '0' means the default (initial configuration) setting |
|
712 { |
|
713 LOGTEXT2(_L8("\tifDesc.InterfaceNumber = %d"), ifDesc.InterfaceNumber()); |
|
714 LOGTEXT2(_L8("\tifDesc.NumEndpoints = %d"), ifDesc.NumEndpoints()); |
|
715 LOGTEXT2(_L8("\tifDesc.InterfaceClass = 0x%02x"), ifDesc.InterfaceClass()); |
|
716 LOGTEXT2(_L8("\tifDesc.InterfaceSubClass = 0x%02x"), ifDesc.InterfaceSubClass()); |
|
717 LOGTEXT2(_L8("\tifDesc.InterfaceProtocol = 0x%02x"), ifDesc.InterfaceProtocol()); |
|
718 LOGTEXT2(_L8("\tifDesc.Interface = %d"), ifDesc.Interface()); |
|
719 |
|
720 TInterfaceInfo* ifInfo = TInterfaceInfo::NewL(iInterfaces); |
|
721 ifInfo->iNumber = ifDesc.InterfaceNumber(); |
|
722 ifInfo->iClass = ifDesc.InterfaceClass(); |
|
723 ifInfo->iSubclass = ifDesc.InterfaceSubClass(); |
|
724 ifInfo->iProtocol = ifDesc.InterfaceProtocol(); |
|
725 ifInfo->iClaimed = EFalse; |
|
726 } |
|
727 } |
|
728 else if (!iCurrentDevice->HasIADFlag() && aDesc.ibDescriptorType == EInterfaceAssociation) |
|
729 { |
|
730 // When found a Interface association descriptor, set this flag to ETrue, |
|
731 // it is checked later after the device level driverloading. |
|
732 iCurrentDevice->SetHasIADFlag(); |
|
733 } |
|
734 else if (aDesc.ibDescriptorType == EOTG) |
|
735 { |
|
736 // OTG descriptor found |
|
737 const TUsbOTGDescriptor& otgDesc = static_cast<TUsbOTGDescriptor&>(aDesc); |
|
738 |
|
739 LOGTEXT2(_L8("\totgDesc.Attributes = %b"), otgDesc.Attributes()); |
|
740 LOGTEXT2(_L8("\totgDesc.HNPSupported = %d"), otgDesc.HNPSupported()); |
|
741 LOGTEXT2(_L8("\totgDesc.SRPSupported = %d"), otgDesc.SRPSupported()); |
|
742 |
|
743 iCurrentDevice->SetOtgDescriptorL(otgDesc); |
|
744 } |
|
745 |
|
746 TUsbGenericDescriptor* const firstChild = aDesc.iFirstChild; |
|
747 if ( firstChild ) |
|
748 { |
|
749 ParseL(*firstChild); |
|
750 } |
|
751 |
|
752 TUsbGenericDescriptor* const nextPeer = aDesc.iNextPeer; |
|
753 if ( nextPeer ) |
|
754 { |
|
755 ParseL(*nextPeer); |
|
756 } |
|
757 } |
|
758 |
|
759 // Method that uses only one array to hold the unclaimed interface numbers. |
|
760 void CFdf::FindDriversForInterfacesUsingSpecificKeyL(CDeviceProxy& aDevice, |
|
761 TInt& aCollectedErr, |
|
762 TBool& aAnySuccess, |
|
763 RArray<TUint>& aInterfacesNumberArray, |
|
764 TInterfaceSearchKeys aKey) |
|
765 { |
|
766 LOG_FUNC |
|
767 |
|
768 const TUint interfaceCount = iInterfaces.Count(); |
|
769 for ( TUint ii = 0 ; ii < interfaceCount ; ++ii ) |
|
770 { |
|
771 TInterfaceInfo* ifInfo = iInterfaces[ii]; |
|
772 ASSERT_DEBUG(ifInfo); |
|
773 |
|
774 if ((ifInfo->iClaimed) || |
|
775 (aKey == EVendorInterfacesubclassInterfaceprotocol && ifInfo->iClass != KVendorSpecificInterfaceClassValue)|| |
|
776 (aKey == EVendorInterfacesubclass && ifInfo->iClass != KVendorSpecificInterfaceClassValue) || |
|
777 (aKey == EInterfaceclassInterfacesubclassInterfaceprotocol && ifInfo->iClass == KVendorSpecificInterfaceClassValue) || |
|
778 (aKey == EInterfaceclassInterfacesubclass && ifInfo->iClass == KVendorSpecificInterfaceClassValue)) |
|
779 { |
|
780 continue; |
|
781 } |
|
782 |
|
783 |
|
784 TBuf8<KMaxSearchKeyLength> searchKey; |
|
785 FormatInterfaceSearchKey(searchKey, aKey, *ifInfo); |
|
786 |
|
787 LOGTEXT2(_L8("\tsearchKey = \"%S\""), &searchKey); |
|
788 // RArray<TUint>* array = &aInterfacesNumberArray; |
|
789 |
|
790 FindDriverForInterfaceUsingSpecificKey(aDevice, aCollectedErr, aAnySuccess, aInterfacesNumberArray, searchKey); |
|
791 |
|
792 // Putting ii+1 as the starting offset is to remove the interface on which |
|
793 // the searching have been done. |
|
794 RebuildUnClaimedInterfacesArrayL(aDevice, aInterfacesNumberArray, ii+1); |
|
795 } |
|
796 } |
|
797 |
|
798 |
|
799 |
|
800 // Called for one interface, to find a Function Driver on the basis of a |
|
801 |
|
802 // specific search key. |
|
803 void CFdf::FindDriverForInterfaceUsingSpecificKey(CDeviceProxy& aDevice, |
|
804 TInt& aCollectedErr, |
|
805 TBool& aAnySuccess, |
|
806 RArray<TUint>& aInterfacesGivenToFdc, |
|
807 const TDesC8& aSearchKey) |
|
808 { |
|
809 |
|
810 LOG_FUNC |
|
811 LOGTEXT2(_L8("\taSearchKey = \"%S\""), &aSearchKey); |
|
812 |
|
813 // Find an FDC matching this search key. |
|
814 TSglQueIter<CFdcProxy> iter(iFunctionDrivers); |
|
815 iter.SetToFirst(); |
|
816 CFdcProxy* fdc; |
|
817 |
|
818 while ( ( fdc = iter++ ) != NULL ) |
|
819 { |
|
820 LOGTEXT2(_L8("\tFDC's default_data field = \"%S\""), &fdc->DefaultDataField()); |
|
821 #ifdef _DEBUG |
|
822 // having these two together in the debug window is helpful for interactive debugging |
|
823 TBuf8<KMaxSearchKeyLength > fd_key; |
|
824 fd_key.Append(fdc->DefaultDataField().Ptr(), fdc->DefaultDataField().Length() > KMaxSearchKeyLength ? KMaxSearchKeyLength : fdc->DefaultDataField().Length()); |
|
825 TBuf8<KMaxSearchKeyLength > searchKey; |
|
826 searchKey.Append(aSearchKey.Ptr(), aSearchKey.Length() > KMaxSearchKeyLength ? KMaxSearchKeyLength : aSearchKey.Length()); |
|
827 TInt version = fdc->Version(); |
|
828 #endif // _DEBUG |
|
829 if (aSearchKey.CompareF(fdc->DefaultDataField()) == 0 && !fdc->MarkedForDeletion()) |
|
830 { |
|
831 // If there is more than one matching FD then if all of them are in RAM we simply choose the first one we find. |
|
832 // (Similarly if they are all in ROM we choose the first one although this situation should not arise as a device |
|
833 // manufacturer should not put two matching FDs into ROM). |
|
834 // However if there are matching FDs in ROM and RAM then the one in ROM should be selected in preference to |
|
835 // any in RAM. Hence at this point if the matching FD we have found is in RAM then we need to scan the list |
|
836 // of FDs to see if there is also a matching one in ROM and if so we'll skip this iteration of the loop. |
|
837 |
|
838 // Edwin comment |
|
839 // Put the searching key and the iterator as the parameter of |
|
840 // searching if more FDCs have the same default_data. The iterator |
|
841 // helps to searching from the current FDC since this is the very first |
|
842 // suitable FDC we found so fa. |
|
843 if (!aDevice.MultipleDriversFlag() && FindMultipleFDs(aSearchKey, iter)) |
|
844 { |
|
845 aDevice.SetMultipleDriversFlag(); |
|
846 } |
|
847 |
|
848 LOGTEXT2(_L8("\tfound matching FDC (0x%08x)"), fdc); |
|
849 #ifdef __FLOG_ACTIVE |
|
850 const TUint count = aInterfacesGivenToFdc.Count(); |
|
851 LOGTEXT2(_L8("\tlogging aInterfacesGivenToFdc (interfaces being offered to the FDC): count = %d"), count); |
|
852 for ( TUint ii = 0 ; ii < count ; ++ii ) |
|
853 { |
|
854 LOGTEXT3(_L8("\t\tindex %d: interface number %d"), ii, aInterfacesGivenToFdc[ii]); |
|
855 } |
|
856 #endif |
|
857 TInt err = fdc->NewFunction(aDevice.DeviceId(), aInterfacesGivenToFdc, iDD, iCD); |
|
858 LOGTEXT2(_L8("\tNewFunction returned %d"), err); |
|
859 // To correctly determine whether the driver load for the whole |
|
860 // configuration was a complete failure, a partial success or a |
|
861 // complete success, we need to collect any non-KErrNone error |
|
862 // from this, and whether any handovers worked at all. |
|
863 if ( err == KErrNone ) |
|
864 { |
|
865 #ifdef __FLOG_ACTIVE |
|
866 LOGTEXT3(_L8("***USB HOST STACK: THE FOLLOWING INTERFACES OF DEVICE %d WERE SUCCESSFULLY PASSED TO FUNCTION DRIVER WITH IMPL UID 0x%08x"), |
|
867 aDevice.DeviceId(), fdc->ImplUid()); |
|
868 // We want to log each interface that's in |
|
869 // aInterfacesGivenToFdc AND is marked claimed in iInterfaces. |
|
870 for ( TUint ii = 0 ; ii < aInterfacesGivenToFdc.Count() ; ++ii ) |
|
871 { |
|
872 const TUint ifNum = aInterfacesGivenToFdc[ii]; |
|
873 for ( TUint jj = 0 ; jj < iInterfaces.Count() ; ++jj ) |
|
874 { |
|
875 const TInterfaceInfo* ifInfo = iInterfaces[jj]; |
|
876 ASSERT_DEBUG(ifInfo); |
|
877 if ( ifNum == ifInfo->iNumber |
|
878 && ifInfo->iClaimed |
|
879 ) |
|
880 { |
|
881 LOGTEXT2(_L8("***USB HOST STACK: bInterfaceNumber %d"), ifNum); |
|
882 } |
|
883 } |
|
884 } |
|
885 #endif |
|
886 aAnySuccess = ETrue; |
|
887 } |
|
888 else |
|
889 { |
|
890 aCollectedErr = err; |
|
891 } |
|
892 // We found a matching FDC for this interface- no need to look for more. |
|
893 break; |
|
894 } |
|
895 } |
|
896 } |
|
897 |
|
898 void CFdf::HandleDeviceDetachment(TUint aDeviceId) |
|
899 { |
|
900 LOG_FUNC |
|
901 LOGTEXT2(_L8("\taDeviceId = %d"), aDeviceId); |
|
902 |
|
903 |
|
904 #ifdef _DEBUG |
|
905 TBool found = EFalse; |
|
906 #endif |
|
907 // Find the relevant device proxy. If there isn't one, just drop the |
|
908 // notification, assuming that the corresponding attachment failed at the |
|
909 // FDF level. |
|
910 TSglQueIter<CDeviceProxy> iter(iDevices); |
|
911 iter.SetToFirst(); |
|
912 CDeviceProxy* device; |
|
913 while ( ( device = iter++ ) != NULL ) |
|
914 { |
|
915 if ( device->DeviceId() == aDeviceId ) |
|
916 { |
|
917 #ifdef _DEBUG |
|
918 found = ETrue; |
|
919 #endif |
|
920 LOGTEXT(_L8("\tfound matching device proxy")); |
|
921 |
|
922 iDevices.Remove(*device); |
|
923 // Before destroying the device proxy, take the detachment event |
|
924 // stored in it for the event queue. |
|
925 TDeviceEvent* const detachmentEvent = device->GetDetachmentEventObject(); |
|
926 ASSERT_DEBUG(detachmentEvent); |
|
927 ASSERT_DEBUG(iEventQueue); |
|
928 iEventQueue->AddDeviceEvent(*detachmentEvent); |
|
929 LOGTEXT2(_L8("***USB HOST STACK: DETACHMENT OF DEVICE (id %d)"), aDeviceId); |
|
930 delete device; |
|
931 |
|
932 TellFdcsOfDeviceDetachment(aDeviceId); |
|
933 |
|
934 #ifndef __OVER_DUMMYUSBDI__ |
|
935 // If we're using the DummyUSBDI the real USBDI isn't loaded. |
|
936 // Unload USBDI when attached devices goes from 1 to 0 |
|
937 if (iDevices.IsEmpty()) |
|
938 { |
|
939 TInt err = User::FreeLogicalDevice(KDriverUsbdiLddFileName); |
|
940 LOGTEXT2(_L8("\tFreeLogicalDevice( usbdi ) returned %d"), err); |
|
941 } |
|
942 #endif // __OVER_DUMMYUSBDI__ |
|
943 |
|
944 break; |
|
945 } |
|
946 } |
|
947 |
|
948 #ifdef _DEBUG |
|
949 if ( !found ) |
|
950 { |
|
951 LOGTEXT(_L8("\tno matching device proxy found")); |
|
952 } |
|
953 #endif |
|
954 } |
|
955 |
|
956 void CFdf::HandleDevmonEvent(TInt aEvent) |
|
957 { |
|
958 LOG_FUNC |
|
959 LOGTEXT2(_L8("\taEvent = %d"), aEvent); |
|
960 |
|
961 ASSERT_DEBUG(iEventQueue); |
|
962 iEventQueue->AddDevmonEvent(aEvent); |
|
963 } |
|
964 |
|
965 void CFdf::TellFdcsOfDeviceDetachment(TUint aDeviceId) |
|
966 { |
|
967 LOG_FUNC |
|
968 LOGTEXT2(_L8("\taDeviceId = %d"), aDeviceId); |
|
969 |
|
970 TSglQueIter<CFdcProxy> iter(iFunctionDrivers); |
|
971 iter.SetToFirst(); |
|
972 CFdcProxy* fdc; |
|
973 while ( ( fdc = iter++ ) != NULL ) |
|
974 { |
|
975 fdc->DeviceDetached(aDeviceId); |
|
976 if (fdc->DeviceCount() == 0 && fdc->MarkedForDeletion()) |
|
977 { // If the FDC was uninstalled while it was in use then it couldn't be deleted at that point so delete it now |
|
978 iFunctionDrivers.Remove(*fdc); |
|
979 delete fdc; |
|
980 } |
|
981 } |
|
982 |
|
983 } |
|
984 |
|
985 TUint32 CFdf::TokenForInterface(TUint8 aInterface) |
|
986 { |
|
987 LOG_FUNC |
|
988 LOGTEXT2(_L8("\taInterface = %d"), aInterface); |
|
989 TUint32 token = 0; |
|
990 |
|
991 // Check that the interface was in the array given to the FD and mark it |
|
992 // as claimed. |
|
993 TBool found = EFalse; |
|
994 const TUint interfaceCount = iInterfaces.Count(); |
|
995 for ( TUint ii = 0 ; ii < interfaceCount ; ++ii ) |
|
996 { |
|
997 TInterfaceInfo* ifInfo = iInterfaces[ii]; |
|
998 ASSERT_DEBUG(ifInfo); |
|
999 if ( ifInfo->iNumber == aInterface ) |
|
1000 { |
|
1001 found = ETrue; |
|
1002 // The FDC tried to claim an interface that was already claimed. |
|
1003 ASSERT_ALWAYS(!ifInfo->iClaimed); |
|
1004 ifInfo->iClaimed = ETrue; |
|
1005 break; |
|
1006 } |
|
1007 } |
|
1008 // Could not find interface in the interface array- the FDC tried to claim |
|
1009 // an interface it had not been offered. |
|
1010 ASSERT_ALWAYS(found); |
|
1011 |
|
1012 ASSERT_DEBUG(iCurrentDevice); |
|
1013 |
|
1014 // GetTokenForInterface will return error in the following cases: |
|
1015 // 1/ KErrBadHandle: invalid device handle (the CDeviceProxy asserts that |
|
1016 // the handle is valid) because the device has been detached while processing |
|
1017 // may be due to too much current or cable has been removed |
|
1018 // so FDF will still return a token of 0 and FDF will handle the proper |
|
1019 // device detachment when it will be able to process the detachment notification |
|
1020 // |
|
1021 // 2/ KErrNotFound: interface not found (if this happens, the FDC has |
|
1022 // misbehaved, and the correct thing to do is to panic) |
|
1023 // 3/ KErrInUse: we've already requested a token for that interface |
|
1024 // (ditto) |
|
1025 // 4/ KErrOverflow: when 0xFFFFFFFF tokens have been requested (this is a |
|
1026 // realistic built-in limitation of USBD) |
|
1027 |
|
1028 |
|
1029 TInt err = iCurrentDevice->GetTokenForInterface(aInterface, token); |
|
1030 switch(err) |
|
1031 { |
|
1032 case KErrBadHandle: |
|
1033 token = 0; |
|
1034 iDeviceDetachedTooEarly = ETrue; |
|
1035 |
|
1036 case KErrNone: // Fall through and do nothing |
|
1037 break; |
|
1038 |
|
1039 default: |
|
1040 LOGTEXT3(_L8("\tUnexpected error %d when requesting token for aInterface %d"),err,aInterface); |
|
1041 ASSERT_ALWAYS(0); |
|
1042 break; |
|
1043 } |
|
1044 |
|
1045 LOGTEXT3(_L8("\tToken for interface %d is = %d"),aInterface, token); |
|
1046 |
|
1047 return token; |
|
1048 } |
|
1049 |
|
1050 CDeviceProxy* CFdf::DeviceProxyL(TUint aDeviceId) const |
|
1051 { |
|
1052 LOG_FUNC |
|
1053 LOGTEXT2(_L8("\taDeviceId = %d"), aDeviceId); |
|
1054 |
|
1055 TSglQueIter<CDeviceProxy> iter(const_cast<CFdf*>(this)->iDevices); |
|
1056 iter.SetToFirst(); |
|
1057 CDeviceProxy* device = NULL; |
|
1058 while ( ( device = iter++ ) != NULL ) |
|
1059 { |
|
1060 if ( device->DeviceId() == aDeviceId ) |
|
1061 { |
|
1062 LOGTEXT2(_L8("\tdevice = 0x%08x"), device); |
|
1063 return device; |
|
1064 } |
|
1065 } |
|
1066 LEAVEL(KErrNotFound); |
|
1067 return NULL; // avoid warning |
|
1068 } |
|
1069 |
|
1070 const RArray<TUint>& CFdf::GetSupportedLanguagesL(TUint aDeviceId) const |
|
1071 { |
|
1072 LOG_FUNC |
|
1073 LOGTEXT2(_L8("\taDeviceId = %d"), aDeviceId); |
|
1074 |
|
1075 CDeviceProxy* deviceProxy = DeviceProxyL(aDeviceId); |
|
1076 return deviceProxy->GetSupportedLanguages(); |
|
1077 } |
|
1078 |
|
1079 void CFdf::GetManufacturerStringDescriptorL(TUint aDeviceId, TUint32 aLangId, TName& aString) const |
|
1080 { |
|
1081 LOG_FUNC |
|
1082 LOGTEXT3(_L8("\taDeviceId = %d, aLangId = 0x%04x"), aDeviceId, aLangId); |
|
1083 |
|
1084 CDeviceProxy* deviceProxy = DeviceProxyL(aDeviceId); |
|
1085 deviceProxy->GetManufacturerStringDescriptorL(aLangId, aString); |
|
1086 LOGTEXT2(_L("\taString = \"%S\""), &aString); |
|
1087 } |
|
1088 |
|
1089 void CFdf::GetProductStringDescriptorL(TUint aDeviceId, TUint32 aLangId, TName& aString) const |
|
1090 { |
|
1091 LOG_FUNC |
|
1092 LOGTEXT3(_L8("\taDeviceId = %d, aLangId = 0x%04x"), aDeviceId, aLangId); |
|
1093 |
|
1094 CDeviceProxy* deviceProxy = DeviceProxyL(aDeviceId); |
|
1095 deviceProxy->GetProductStringDescriptorL(aLangId, aString); |
|
1096 LOGTEXT2(_L("\taString = \"%S\""), &aString); |
|
1097 } |
|
1098 |
|
1099 void CFdf::GetOtgDeviceDescriptorL(TInt aDeviceId, TOtgDescriptor& aDescriptor) const |
|
1100 { |
|
1101 LOG_FUNC |
|
1102 |
|
1103 DeviceProxyL(aDeviceId)->GetOtgDescriptorL(aDescriptor); |
|
1104 } |
|
1105 |
|
1106 void CFdf::GetSerialNumberStringDescriptorL(TUint aDeviceId, TUint32 aLangId, TName& aString) const |
|
1107 { |
|
1108 LOG_FUNC |
|
1109 LOGTEXT3(_L8("\taDeviceId = %d, aLangId = 0x%04x"), aDeviceId, aLangId); |
|
1110 |
|
1111 CDeviceProxy* deviceProxy = DeviceProxyL(aDeviceId); |
|
1112 deviceProxy->GetSerialNumberStringDescriptorL(aLangId, aString); |
|
1113 LOGTEXT2(_L("\taString = \"%S\""), &aString); |
|
1114 } |
|
1115 |
|
1116 void CFdf::SearchForInterfaceFunctionDriversL(CDeviceProxy& aDevice, TBool& aAnySuccess, TInt& aCollectedErr) |
|
1117 { |
|
1118 RArray<TUint> interfacesNumberArray; |
|
1119 CleanupClosePushL(interfacesNumberArray); |
|
1120 |
|
1121 |
|
1122 |
|
1123 for ( TUint ii = 0 ; ii < iInterfaces.Count() ; ++ii ) |
|
1124 { |
|
1125 // At this point we have NOT done any interface level searching yet, |
|
1126 // and all interfaces should in the Unclaimed status, |
|
1127 // just simply put them all into the interfacesNumberArray. |
|
1128 TUint interfaceNumber = iInterfaces[ii]->iNumber; |
|
1129 AppendInterfaceNumberToArrayL(aDevice, interfacesNumberArray, interfaceNumber); |
|
1130 } |
|
1131 |
|
1132 |
|
1133 for ( TUint key = EVendorProductDeviceConfigurationvalueInterfacenumber ; key < EMaxInterfaceSearchKey ; ++key ) |
|
1134 { |
|
1135 // Searching for proper FDCs based on different criteria. |
|
1136 FindDriversForInterfacesUsingSpecificKeyL(aDevice, |
|
1137 aCollectedErr, |
|
1138 aAnySuccess, |
|
1139 interfacesNumberArray, |
|
1140 (TInterfaceSearchKeys) key); |
|
1141 |
|
1142 // If all the interfaces have been claimed by an FD then there is no point searching for other FDs |
|
1143 if (UnclaimedInterfaceCount() == 0) |
|
1144 { |
|
1145 break; |
|
1146 } |
|
1147 else |
|
1148 { |
|
1149 // Put all the unclaimed interface numbers into the array again. |
|
1150 RebuildUnClaimedInterfacesArrayL(aDevice, interfacesNumberArray); |
|
1151 } |
|
1152 } |
|
1153 CleanupStack::PopAndDestroy(&interfacesNumberArray); |
|
1154 } |
|
1155 void CFdf::RebuildUnClaimedInterfacesArrayL(CDeviceProxy& aDevice, RArray<TUint>& aArray, TUint aOffset) |
|
1156 { |
|
1157 aArray.Reset(); |
|
1158 for ( TUint ii = aOffset ; ii < iInterfaces.Count() ; ++ii ) |
|
1159 { |
|
1160 if (!iInterfaces[ii]->iClaimed) |
|
1161 { |
|
1162 TUint interfaceNumber = iInterfaces[ii]->iNumber; |
|
1163 AppendInterfaceNumberToArrayL(aDevice, aArray, interfaceNumber); |
|
1164 } |
|
1165 } |
|
1166 } |
|
1167 |
|
1168 void CFdf::AppendInterfaceNumberToArrayL(CDeviceProxy& aDevice, RArray<TUint>& aArray, TUint aInterfaceNo) const |
|
1169 { |
|
1170 TInt err = aArray.Append(aInterfaceNo); |
|
1171 if ( err ) |
|
1172 { |
|
1173 aDevice.SetDriverLoadingEventData(EDriverLoadFailure, err); |
|
1174 LEAVEL(err); |
|
1175 } |
|
1176 } |
|
1177 |
|
1178 |
|
1179 |
|
1180 TBool CFdf::SearchForADeviceFunctionDriverL(CDeviceProxy& aDevice, TBool& aAnySuccess, TInt& aCollectedErr) |
|
1181 { |
|
1182 |
|
1183 RArray<TUint> interfaces; |
|
1184 CleanupClosePushL(interfaces); |
|
1185 |
|
1186 for (TUint ii = 0; ii < iInterfaces.Count(); ++ii) |
|
1187 { |
|
1188 TUint interfaceNumber = iInterfaces[ii]->iNumber; |
|
1189 AppendInterfaceNumberToArrayL(aDevice, interfaces, interfaceNumber); |
|
1190 } |
|
1191 |
|
1192 TBool foundFdc = EFalse; |
|
1193 for (TUint key = EVendorProductDevice; key < EMaxDeviceSearchKey; ++key) |
|
1194 { |
|
1195 |
|
1196 if (key == EVendorDevicesubclassDeviceprotocol && iDD.DeviceClass() != KVendorSpecificDeviceClassValue) |
|
1197 continue; |
|
1198 if (key == EVendorDevicesubclass && iDD.DeviceClass() != KVendorSpecificDeviceClassValue) |
|
1199 continue; |
|
1200 if (key == EDeviceclassDevicesubclassDeviceprotocol && iDD.DeviceClass() == KVendorSpecificDeviceClassValue) |
|
1201 continue; |
|
1202 if (key == EDeviceclassDevicesubclass && iDD.DeviceClass() == KVendorSpecificDeviceClassValue) |
|
1203 continue; |
|
1204 |
|
1205 TBuf8<KMaxSearchKeyLength> searchKeyString; |
|
1206 FormatDeviceSearchKey(searchKeyString, (TDeviceSearchKeys)key); |
|
1207 |
|
1208 // Find an FDC matching this search key. |
|
1209 TSglQueIter<CFdcProxy> iter(iFunctionDrivers); |
|
1210 iter.SetToFirst(); |
|
1211 CFdcProxy* fdc; |
|
1212 while ( ( fdc = iter++ ) != NULL) |
|
1213 { |
|
1214 if (fdc->MarkedForDeletion()) |
|
1215 continue; |
|
1216 LOGTEXT2(_L8("\tFDC's default_data field = \"%S\""), &fdc->DefaultDataField()); |
|
1217 #ifdef _DEBUG |
|
1218 // having these two together in the debug window is helpful for interactive debugging |
|
1219 TBuf8<KMaxSearchKeyLength> fd_key; |
|
1220 fd_key.Append(fdc->DefaultDataField().Ptr(), fdc->DefaultDataField().Length() > KMaxSearchKeyLength ? KMaxSearchKeyLength : fdc->DefaultDataField().Length()); |
|
1221 TBuf8<KMaxSearchKeyLength> search_key; |
|
1222 search_key.Append(searchKeyString.Ptr(), searchKeyString.Length() > KMaxSearchKeyLength ? KMaxSearchKeyLength : searchKeyString.Length()); |
|
1223 TInt version = fdc->Version(); |
|
1224 #endif |
|
1225 if (searchKeyString.CompareF(fdc->DefaultDataField()) == 0) |
|
1226 { |
|
1227 |
|
1228 // If there is more than one matching FD then if all of them are in RAM we simply choose the first one we find. |
|
1229 // (Similarly if they are all in ROM we choose the first one although this situation should not arise as a device |
|
1230 // manufacturer should not put two matching FDs into ROM). |
|
1231 // However if there are matching FDs in ROM and RAM then the one in ROM should be selected in preference to |
|
1232 // any in RAM. Hence at this point if the matching FD we have found is in RAM then we need to scan the list |
|
1233 // of FDs to see if there is also a matching one in ROM and if so we'll skip this iteration of the loop. |
|
1234 //if (!fdc->RomBased() && FindMatchingRomBasedFD(searchKeyString)) |
|
1235 // continue; |
|
1236 if (FindMultipleFDs(searchKeyString, iter)) |
|
1237 { |
|
1238 aDevice.SetMultipleDriversFlag(); |
|
1239 } |
|
1240 |
|
1241 foundFdc = ETrue; |
|
1242 LOGTEXT2(_L8("\tfound matching FDC (0x%08x)"), fdc); |
|
1243 TInt err = fdc->NewFunction(aDevice.DeviceId(), interfaces, iDD, iCD); |
|
1244 LOGTEXT2(_L8("\tNewFunction returned %d"), err); |
|
1245 // To correctly determine whether the driver load for the whole |
|
1246 // configuration was a complete failure, a partial success or a |
|
1247 // complete success, we need to collect any non-KErrNone error |
|
1248 // from this, and whether any handovers worked at all. |
|
1249 if ( err == KErrNone ) |
|
1250 { |
|
1251 aAnySuccess = ETrue; |
|
1252 } |
|
1253 else |
|
1254 { |
|
1255 aCollectedErr = err; |
|
1256 } |
|
1257 break; // We found a matching FDC so no need to look for more. |
|
1258 } |
|
1259 } |
|
1260 if (foundFdc) |
|
1261 break; |
|
1262 } // end of for |
|
1263 CleanupStack::PopAndDestroy(&interfaces); |
|
1264 return foundFdc; |
|
1265 |
|
1266 } // end of function |
|
1267 |
|
1268 |
|
1269 |
|
1270 |
|
1271 // |
|
1272 // Search the list of FDs looking for which matches with aSearchKey and is rom based and return true if found. |
|
1273 // |
|
1274 // added for Multiple FDs |
|
1275 TBool CFdf::FindMultipleFDs(const TDesC8& aSearchKey,TSglQueIter<CFdcProxy>& aFdcIter) |
|
1276 { |
|
1277 CFdcProxy* fdc; |
|
1278 while ( ( fdc = aFdcIter++ ) != NULL) |
|
1279 { |
|
1280 if (!fdc->MarkedForDeletion() && (aSearchKey.CompareF(fdc->DefaultDataField()) == 0)) |
|
1281 return ETrue; |
|
1282 } |
|
1283 |
|
1284 return EFalse; |
|
1285 } |
|
1286 |
|
1287 // |
|
1288 // Format the string aSearchKey according to aSearchKeys to search for Device Functions drivers |
|
1289 // |
|
1290 void CFdf::FormatDeviceSearchKey(TDes8& aSearchKey, TDeviceSearchKeys aDeviceSearchKeys) |
|
1291 { |
|
1292 LOG_FUNC |
|
1293 switch (aDeviceSearchKeys) |
|
1294 { |
|
1295 case EVendorProductDevice: |
|
1296 { |
|
1297 _LIT8(KTemplateV_P_D, "V0x%04xP0x%04xD0x%04x"); |
|
1298 aSearchKey.Format(KTemplateV_P_D(), iDD.VendorId(), iDD.ProductId(), iDD.DeviceBcd()); |
|
1299 break; |
|
1300 } |
|
1301 case EVendorProduct: |
|
1302 { |
|
1303 _LIT8(KTemplateV_P, "V0x%04xP0x%04x"); |
|
1304 aSearchKey.Format(KTemplateV_P(), iDD.VendorId(), iDD.ProductId()); |
|
1305 break; |
|
1306 } |
|
1307 case EVendorDevicesubclassDeviceprotocol: |
|
1308 { |
|
1309 _LIT8(KTemplateV_DSC_DP, "V0x%04xDSC0x%02xDP0x%02x"); |
|
1310 aSearchKey.Format(KTemplateV_DSC_DP(), iDD.VendorId(), iDD.DeviceSubClass(), iDD.DeviceProtocol()); |
|
1311 break; |
|
1312 } |
|
1313 case EVendorDevicesubclass: |
|
1314 { |
|
1315 _LIT8(KTemplateV_DSC, "V0x%04xDSC0x%02x"); |
|
1316 aSearchKey.Format(KTemplateV_DSC(), iDD.VendorId(), iDD.DeviceSubClass()); |
|
1317 break; |
|
1318 } |
|
1319 case EDeviceclassDevicesubclassDeviceprotocol: |
|
1320 { |
|
1321 _LIT8(KTemplateDC_DSC_DP, "DC0x%02xDSC0x%02xDP0x%02x"); |
|
1322 aSearchKey.Format(KTemplateDC_DSC_DP(), iDD.DeviceClass(), iDD.DeviceSubClass(), iDD.DeviceProtocol()); |
|
1323 break; |
|
1324 } |
|
1325 case EDeviceclassDevicesubclass: |
|
1326 { |
|
1327 _LIT8(KTemplateDC_DSC, "DC0x%02xDSC0x%02x"); |
|
1328 aSearchKey.Format(KTemplateDC_DSC(), iDD.DeviceClass(), iDD.DeviceSubClass()); |
|
1329 break; |
|
1330 } |
|
1331 default: |
|
1332 { |
|
1333 ASSERT_DEBUG(EFalse); |
|
1334 } |
|
1335 } |
|
1336 |
|
1337 LOGTEXT2(_L8("\taSearchKey = \"%S\""), &aSearchKey); |
|
1338 } |
|
1339 |
|
1340 |
|
1341 |
|
1342 |
|
1343 |
|
1344 // |
|
1345 // Format the string aSearchKey according to aSearchKeys to search for Interface Functions drivers |
|
1346 // |
|
1347 void CFdf::FormatInterfaceSearchKey(TDes8& aSearchKey, TInterfaceSearchKeys aSearchKeys, const TInterfaceInfo& aIfInfo) |
|
1348 { |
|
1349 LOG_FUNC |
|
1350 switch (aSearchKeys) |
|
1351 { |
|
1352 case EVendorProductDeviceConfigurationvalueInterfacenumber: |
|
1353 { |
|
1354 _LIT8(KTemplateV_P_D_CV_IN, "V0x%04xP0x%04xD0x%04xCV0x%02xIN0x%02x"); |
|
1355 aSearchKey.Format(KTemplateV_P_D_CV_IN(), iDD.VendorId(), iDD.ProductId(), iDD.DeviceBcd(), iCD.ConfigurationValue(), aIfInfo.iNumber); |
|
1356 break; |
|
1357 } |
|
1358 case EVendorProductConfigurationValueInterfacenumber: |
|
1359 { |
|
1360 _LIT8(KTemplateV_P_CV_IN, "V0x%04xP0x%04xCV0x%02xIN0x%02x"); |
|
1361 aSearchKey.Format(KTemplateV_P_CV_IN(), iDD.VendorId(), iDD.ProductId(), iCD.ConfigurationValue(), aIfInfo.iNumber); |
|
1362 break; |
|
1363 } |
|
1364 case EVendorInterfacesubclassInterfaceprotocol: |
|
1365 { |
|
1366 _LIT8(KTemplateV_ISC_IP, "V0x%04xISC0x%02xIP0x%02x"); |
|
1367 aSearchKey.Format(KTemplateV_ISC_IP(), iDD.VendorId(), aIfInfo.iSubclass, aIfInfo.iProtocol); |
|
1368 break; |
|
1369 } |
|
1370 case EVendorInterfacesubclass: |
|
1371 { |
|
1372 _LIT8(KTemplateV_ISC, "V0x%04xISC0x%02x"); |
|
1373 aSearchKey.Format(KTemplateV_ISC(), iDD.VendorId(), aIfInfo.iSubclass); |
|
1374 break; |
|
1375 } |
|
1376 case EInterfaceclassInterfacesubclassInterfaceprotocol: |
|
1377 { |
|
1378 _LIT8(KTemplateIC_ISC_IP, "IC0x%02xISC0x%02xIP0x%02x"); |
|
1379 aSearchKey.Format(KTemplateIC_ISC_IP(), aIfInfo.iClass, aIfInfo.iSubclass, aIfInfo.iProtocol); |
|
1380 break; |
|
1381 } |
|
1382 case EInterfaceclassInterfacesubclass: |
|
1383 { |
|
1384 _LIT8(KTemplateIC_ISC, "IC0x%02xISC0x%02x"); |
|
1385 aSearchKey.Format(KTemplateIC_ISC(), aIfInfo.iClass, aIfInfo.iSubclass); |
|
1386 break; |
|
1387 } |
|
1388 default: |
|
1389 { |
|
1390 ASSERT_DEBUG(EFalse); |
|
1391 } |
|
1392 } |
|
1393 LOGTEXT2(_L8("\taSearchKey = \"%S\""), &aSearchKey); |
|
1394 } |
|
1395 |
|
1396 |
|
1397 TUint CFdf::UnclaimedInterfaceCount() const |
|
1398 { |
|
1399 LOG_FUNC |
|
1400 TUint unclaimedInterfaces = 0; |
|
1401 for ( TUint ii = 0 ; ii < iInterfaces.Count() ; ++ii ) |
|
1402 { |
|
1403 TInterfaceInfo* ifInfo = iInterfaces[ii]; |
|
1404 ASSERT_DEBUG(ifInfo); |
|
1405 if ( !ifInfo->iClaimed ) |
|
1406 { |
|
1407 LOGTEXT2(_L8("\tunclaimed interface: ifInfo->iNumber = %d"), ifInfo->iNumber); |
|
1408 ++unclaimedInterfaces; |
|
1409 } |
|
1410 } |
|
1411 LOGTEXT2(_L("\tunclaimedInterfaces = \"%d\""), unclaimedInterfaces); |
|
1412 return unclaimedInterfaces; |
|
1413 } |
|
1414 |
|
1415 |
|
1416 void CFdf::SetFailureStatus(TInt aUnclaimedInterfaces, TInt aInterfaceCount, TBool aAnySuccess, TBool aCollectedErr, CDeviceProxy& aDevice) |
|
1417 { |
|
1418 const TUint KMultipleDriverFound = aDevice.MultipleDriversFlag()?KMultipleDriversFound : 0; |
|
1419 |
|
1420 if (aUnclaimedInterfaces) |
|
1421 { |
|
1422 if(aUnclaimedInterfaces == aInterfaceCount) |
|
1423 { |
|
1424 // complete failure |
|
1425 aDevice.SetDriverLoadingEventData((TDriverLoadStatus)(EDriverLoadFailure|KMultipleDriverFound), KErrUsbFunctionDriverNotFound); |
|
1426 } |
|
1427 else |
|
1428 {// at that stage because we have unclaimed interfaces it means that |
|
1429 // depending on anySuccess we have a failure or a partial success |
|
1430 TDriverLoadStatus status = (aAnySuccess)? EDriverLoadPartialSuccess:EDriverLoadFailure; |
|
1431 aDevice.SetDriverLoadingEventData((TDriverLoadStatus)(status|KMultipleDriverFound), KErrUsbFunctionDriverNotFound); |
|
1432 } |
|
1433 } |
|
1434 else |
|
1435 { |
|
1436 if (aCollectedErr) |
|
1437 { |
|
1438 // There were no unclaimed interfaces, but an error was expressed. |
|
1439 // This is either a partial success or a complete failure scenario. |
|
1440 TDriverLoadStatus status = aAnySuccess ? EDriverLoadPartialSuccess : EDriverLoadFailure; |
|
1441 aDevice.SetDriverLoadingEventData((TDriverLoadStatus)(status|KMultipleDriverFound), aCollectedErr); |
|
1442 } |
|
1443 else |
|
1444 { |
|
1445 // There were no unclaimed interfaces, and no error reported. |
|
1446 aDevice.SetDriverLoadingEventData((TDriverLoadStatus)(EDriverLoadSuccess|KMultipleDriverFound)); |
|
1447 } |
|
1448 } |
|
1449 } |
|
1450 |