|
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 // |
|
15 |
|
16 /** |
|
17 @file |
|
18 @internalComponent |
|
19 |
|
20 The driver's name |
|
21 |
|
22 @return The name of the driver |
|
23 |
|
24 @internalComponent |
|
25 */ |
|
26 inline const TDesC& RUsbHubDriver::Name() |
|
27 { |
|
28 _LIT(KDriverName,"USBHUBDRIVER"); |
|
29 return KDriverName; |
|
30 } |
|
31 |
|
32 /** |
|
33 The driver's version |
|
34 |
|
35 @return The version number of the driver |
|
36 */ |
|
37 inline TVersion RUsbHubDriver::VersionRequired() |
|
38 { |
|
39 const TInt KMajorVersionNumber=1; |
|
40 const TInt KMinorVersionNumber=0; |
|
41 const TInt KBuildVersionNumber=KE32BuildVersionNumber; |
|
42 return TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber); |
|
43 } |
|
44 |
|
45 |
|
46 #ifndef __KERNEL_MODE__ |
|
47 |
|
48 /** |
|
49 Open a handle to the host controller. |
|
50 @return System-wide error code giving status of connection attempt. |
|
51 */ |
|
52 TInt RUsbHubDriver::Open() |
|
53 { |
|
54 TInt rc = KErrNone; |
|
55 |
|
56 // Check to see if this object has already been opened - if it has, |
|
57 // there will be a handle set. |
|
58 |
|
59 if ( Handle() ) |
|
60 { |
|
61 User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverAlreadyOpened); |
|
62 } |
|
63 |
|
64 rc = DoCreate(Name(),VersionRequired(),KNullUnit,NULL,NULL,EOwnerThread); |
|
65 |
|
66 if ( rc != KErrNone ) |
|
67 { |
|
68 RDebug::Print(_L("********************************")); |
|
69 RDebug::Print(_L("* RUsbHubDriver::Open() Fault! *")); |
|
70 RDebug::Print(_L("********************************")); |
|
71 } |
|
72 |
|
73 return rc; |
|
74 } |
|
75 |
|
76 |
|
77 /** |
|
78 Start the host stack. |
|
79 */ |
|
80 TInt RUsbHubDriver::StartHost() |
|
81 { |
|
82 return DoControl(EStartHost); |
|
83 } |
|
84 |
|
85 |
|
86 /** |
|
87 Stop the host stack. |
|
88 */ |
|
89 void RUsbHubDriver::StopHost() |
|
90 { |
|
91 DoControl(EStopHost); |
|
92 } |
|
93 |
|
94 |
|
95 /** |
|
96 Wait for a bus event. These include device attachments and detachments. |
|
97 @see TBusEvent |
|
98 @param aEvent The details of the event that occured, filled in when the request completes. |
|
99 @param aStatus Completed when an event occurs |
|
100 */ |
|
101 void RUsbHubDriver::WaitForBusEvent(TBusEvent& aEvent, TRequestStatus& aStatus) |
|
102 { |
|
103 DoRequest(EWaitForBusEvent, aStatus, &aEvent); |
|
104 } |
|
105 |
|
106 |
|
107 /** |
|
108 Cancel a request to wait for bus events. |
|
109 */ |
|
110 void RUsbHubDriver::CancelWaitForBusEvent() |
|
111 { |
|
112 DoCancel(ECancelWaitForBusEvent); |
|
113 } |
|
114 |
|
115 |
|
116 RUsbDevice::RUsbDevice() |
|
117 : iHeadDeviceDescriptor(NULL) |
|
118 , iHeadConfDescriptor(NULL) |
|
119 , iConfigurationDescriptorData(NULL) |
|
120 , iHub(NULL) |
|
121 , iHandle(0) |
|
122 { |
|
123 } |
|
124 |
|
125 /** |
|
126 Open a handle to a device. |
|
127 */ |
|
128 TInt RUsbDevice::Open(RUsbHubDriver& aHub, TUint aHandle) |
|
129 { |
|
130 if(iHandle) |
|
131 { |
|
132 return KErrInUse; |
|
133 } |
|
134 |
|
135 TInt err; |
|
136 err = aHub.DoControl(EOpen, (TAny*)aHandle); |
|
137 |
|
138 |
|
139 if (err == KErrNone) |
|
140 { |
|
141 iHub = &aHub; |
|
142 iHandle = aHandle; |
|
143 } |
|
144 else |
|
145 { |
|
146 return err; |
|
147 } |
|
148 |
|
149 TRAP(err, GetLocalDescriptorsL()); |
|
150 // GetLocalDescriptorsL should roll back iHandle etc on error. |
|
151 __ASSERT_DEBUG(err == KErrNone || !iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverNoRollBackAfterFailedDeviceOpen)); |
|
152 |
|
153 return err; |
|
154 } |
|
155 |
|
156 void RUsbDevice::GetLocalDescriptorsL() |
|
157 { |
|
158 CleanupClosePushL(*this); // Ensure that we roll back to closed on error. |
|
159 |
|
160 // Get Device Descriptor Data. |
|
161 User::LeaveIfError(GetDeviceDescriptor(iDeviceDescriptorData)); |
|
162 |
|
163 // Get Configuration Descriptor Data |
|
164 TInt configSize = 0; |
|
165 User::LeaveIfError(GetConfigurationDescriptorSize(configSize)); |
|
166 |
|
167 iConfigurationDescriptorData = HBufC8::NewL(configSize); |
|
168 TPtr8 ptr = iConfigurationDescriptorData->Des(); |
|
169 User::LeaveIfError(GetConfigurationDescriptor(ptr)); |
|
170 |
|
171 |
|
172 TUsbGenericDescriptor* parsed = NULL; |
|
173 |
|
174 // Parse Device Descriptor |
|
175 User::LeaveIfError(UsbDescriptorParser::Parse(iDeviceDescriptorData, parsed)); |
|
176 iHeadDeviceDescriptor = TUsbDeviceDescriptor::Cast(parsed); |
|
177 if(!iHeadDeviceDescriptor) |
|
178 { |
|
179 User::Leave(KErrCorrupt); |
|
180 } |
|
181 |
|
182 // Parse Configuration Descriptor |
|
183 User::LeaveIfError(UsbDescriptorParser::Parse(*iConfigurationDescriptorData, parsed)); |
|
184 iHeadConfDescriptor = TUsbConfigurationDescriptor::Cast(parsed); |
|
185 if(!iHeadConfDescriptor) |
|
186 { |
|
187 User::Leave(KErrCorrupt); |
|
188 } |
|
189 |
|
190 CleanupStack::Pop(); // this |
|
191 } |
|
192 |
|
193 |
|
194 /** |
|
195 Close a handle to a device. |
|
196 */ |
|
197 void RUsbDevice::Close() |
|
198 { |
|
199 if(iHub) |
|
200 { |
|
201 iHub->DoControl(EClose, (TAny*)iHandle); |
|
202 } |
|
203 |
|
204 if(iHeadConfDescriptor) |
|
205 { |
|
206 iHeadConfDescriptor->DestroyTree(); |
|
207 delete iHeadConfDescriptor; |
|
208 iHeadConfDescriptor = NULL; |
|
209 } |
|
210 |
|
211 if(iHeadDeviceDescriptor) |
|
212 { |
|
213 iHeadDeviceDescriptor->DestroyTree(); |
|
214 delete iHeadDeviceDescriptor; |
|
215 iHeadDeviceDescriptor = NULL; |
|
216 } |
|
217 |
|
218 delete iConfigurationDescriptorData; |
|
219 iConfigurationDescriptorData = NULL; |
|
220 |
|
221 iHub = NULL; |
|
222 iHandle = 0; |
|
223 } |
|
224 |
|
225 |
|
226 /** |
|
227 Return the handle to a device |
|
228 */ |
|
229 TUint RUsbDevice::Handle() const |
|
230 { |
|
231 return iHandle; |
|
232 } |
|
233 |
|
234 |
|
235 /** |
|
236 Places the device into a suspended state. |
|
237 */ |
|
238 TInt RUsbDevice::Suspend() |
|
239 { |
|
240 __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); |
|
241 __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); |
|
242 return iHub->DoControl(ESuspend, (TAny*)iHandle); |
|
243 } |
|
244 |
|
245 |
|
246 /** |
|
247 Resumes the device from a suspended state. |
|
248 */ |
|
249 TInt RUsbDevice::Resume() |
|
250 { |
|
251 __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); |
|
252 __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); |
|
253 return iHub->DoControl(EResume, (TAny*)iHandle); |
|
254 } |
|
255 |
|
256 |
|
257 TInt RUsbDevice::GetStringDescriptor(TDes8& aStringDescriptor, TInt aIndex, TInt aLangId) |
|
258 { |
|
259 __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); |
|
260 __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); |
|
261 __ASSERT_ALWAYS(aStringDescriptor.MaxLength() >= 255, |
|
262 User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverInsufficientSizeToHoldStringDescriptor)); |
|
263 |
|
264 aStringDescriptor.Zero(); |
|
265 |
|
266 TStringDescParams stringDescParams; |
|
267 stringDescParams.iTarget = &aStringDescriptor; |
|
268 stringDescParams.iIndex = aIndex; |
|
269 stringDescParams.iLangId = aLangId; |
|
270 |
|
271 return iHub->DoControl(EGetStringDescriptor, (TAny*)iHandle, &stringDescParams); |
|
272 } |
|
273 |
|
274 |
|
275 /** |
|
276 Return a token which may be used to uniquely identify the supplied interface on this device. The returned |
|
277 token may then be passed to a function driver, to allow it to open the required interface. |
|
278 |
|
279 @param [in] aInterfaceNumber Interface to return a token for. |
|
280 @param [out] aToken The token assigned to the interface. |
|
281 @return System wide error code, for instance KErrNotFound if the supplied interface number is unknown. |
|
282 */ |
|
283 TInt RUsbDevice::GetTokenForInterface(TInt aInterfaceNumber, TUint32& aToken) |
|
284 { |
|
285 __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); |
|
286 __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); |
|
287 |
|
288 TInterfaceTokenParameters params; |
|
289 params.iInterfaceNumber = aInterfaceNumber; |
|
290 params.iToken = &aToken; |
|
291 |
|
292 return iHub->DoControl(EGetInterfaceToken, (TAny*)iHandle, ¶ms); |
|
293 } |
|
294 |
|
295 /** |
|
296 Queues an asynchronous request for changes in the state of the device represented by this handle. |
|
297 |
|
298 @param [out] aNewState The new state of the device |
|
299 @param [out] aRequest The request status completed when a state change has occured. |
|
300 */ |
|
301 void RUsbDevice::QueueDeviceStateChangeNotification(TDeviceState& aNewState, TRequestStatus& aRequest) |
|
302 { |
|
303 __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); |
|
304 __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); |
|
305 iHub->DoRequest(EDeviceStateChange, aRequest, (TAny*)iHandle, &aNewState); |
|
306 } |
|
307 |
|
308 |
|
309 /** |
|
310 Cancels an outstanding request for device state changes |
|
311 @see QueueDeviceStateChangeNotification |
|
312 */ |
|
313 void RUsbDevice::CancelDeviceStateChangeNotification() |
|
314 { |
|
315 __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); |
|
316 __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); |
|
317 iHub->DoControl(ECancelDeviceStateChange, (TAny*)iHandle); |
|
318 } |
|
319 |
|
320 |
|
321 /** |
|
322 Return the USB Device Descriptor for this device. |
|
323 |
|
324 Note: the supplied TUsbDeviceDescriptor is owned by the caller, but any descriptor objects linked to it |
|
325 remain the property of the RUsbDevice object. Memory leaks will result if the head pointer is not |
|
326 cleaned up, but the pointed to objects should not be destroyed. |
|
327 |
|
328 @param [out] aDescriptor The supplied TUsbDeviceDescriptor object will be populated from the data retrieved from the |
|
329 device. |
|
330 |
|
331 @return KErrNone on success, otherwise a system wide error code. |
|
332 */ |
|
333 TInt RUsbDevice::GetDeviceDescriptor(TUsbDeviceDescriptor& aDescriptor) |
|
334 { |
|
335 __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); |
|
336 __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); |
|
337 aDescriptor = *iHeadDeviceDescriptor; |
|
338 return KErrNone; |
|
339 } |
|
340 |
|
341 /** |
|
342 Return the USB Configuration Descriptor for this device. |
|
343 |
|
344 Note: the supplied TUsbConfigurationDescriptor is owned by the caller, but any descriptor objects linked to it |
|
345 remain the property of the RUsbDevice object. Memory leaks will result if the head pointer is not |
|
346 cleaned up, but the pointed to objects should not be destroyed. |
|
347 |
|
348 @param [out] aDescriptor The supplied TUsbConfigurationDescriptor object will be populated from the data retrieved from |
|
349 the device. Note that the caller owns the head of the list, but not any children or peers. |
|
350 |
|
351 @return KErrNone on success, otherwise a system wide error code. |
|
352 */ |
|
353 TInt RUsbDevice::GetConfigurationDescriptor(TUsbConfigurationDescriptor& aDescriptor) |
|
354 { |
|
355 __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); |
|
356 __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); |
|
357 aDescriptor = *iHeadConfDescriptor; |
|
358 return KErrNone; |
|
359 } |
|
360 |
|
361 TInt RUsbDevice::GetStringDescriptor(TUsbStringDescriptor*& aDescriptor, TDes8& aTarget, TInt aIndex) |
|
362 { |
|
363 __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); |
|
364 __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); |
|
365 |
|
366 aDescriptor = NULL; |
|
367 // aTarget will be Zero-ed in the GetStringDescriptor overload. |
|
368 |
|
369 TInt err = GetStringDescriptor(aTarget, aIndex); |
|
370 if(err != KErrNone) |
|
371 { |
|
372 return err; |
|
373 } |
|
374 return ParseStringDescriptor(aDescriptor, aTarget); |
|
375 } |
|
376 |
|
377 TInt RUsbDevice::GetStringDescriptor(TUsbStringDescriptor*& aDescriptor, TDes8& aTarget, TInt aIndex, TInt aLangId) |
|
378 { |
|
379 __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); |
|
380 __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); |
|
381 |
|
382 aDescriptor = NULL; |
|
383 // aTarget will be Zero-ed in the GetStringDescriptor overload. |
|
384 |
|
385 TInt err = GetStringDescriptor(aTarget, aIndex, aLangId); |
|
386 if(err != KErrNone) |
|
387 { |
|
388 return err; |
|
389 } |
|
390 |
|
391 return ParseStringDescriptor(aDescriptor, aTarget); |
|
392 } |
|
393 |
|
394 TInt RUsbDevice::ParseStringDescriptor(TUsbStringDescriptor*& aDescriptor, const TDesC8& aData) |
|
395 { |
|
396 TUsbGenericDescriptor* parsed = NULL; |
|
397 TInt err = UsbDescriptorParser::Parse(aData, parsed); |
|
398 if(err == KErrNone) |
|
399 { |
|
400 aDescriptor = TUsbStringDescriptor::Cast(parsed); |
|
401 if(aDescriptor) |
|
402 { |
|
403 return KErrNone; |
|
404 } |
|
405 } |
|
406 // If here then there has been an error when parsing the descriptor |
|
407 if(parsed) |
|
408 { |
|
409 parsed->DestroyTree(); |
|
410 delete parsed; |
|
411 } |
|
412 return (err != KErrNone) ? err : KErrCorrupt; |
|
413 } |
|
414 |
|
415 |
|
416 |
|
417 |
|
418 TInt RUsbDevice::GetDeviceDescriptor(TDes8& aDeviceDesc) |
|
419 { |
|
420 __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); |
|
421 __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); |
|
422 return iHub->DoControl(EGetDeviceDescriptor, (TAny*)iHandle, &aDeviceDesc); |
|
423 } |
|
424 |
|
425 |
|
426 TInt RUsbDevice::GetConfigurationDescriptorSize(TInt& aSize) |
|
427 { |
|
428 __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); |
|
429 __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); |
|
430 return iHub->DoControl(EGetConfigurationDescriptorSize, (TAny*)iHandle, &aSize); |
|
431 } |
|
432 |
|
433 |
|
434 TInt RUsbDevice::GetConfigurationDescriptor(TDes8& aConfigDesc) |
|
435 { |
|
436 __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); |
|
437 __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); |
|
438 return iHub->DoControl(EGetConfigurationDescriptor, (TAny*)iHandle, &aConfigDesc); |
|
439 } |
|
440 |
|
441 |
|
442 #endif // !__KERNEL_MODE__ |