|
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 * Description: |
|
15 * Implements a Session of a Symbian OS server for the RUsb API |
|
16 * |
|
17 */ |
|
18 |
|
19 /** |
|
20 @file |
|
21 */ |
|
22 |
|
23 #include <usb/usblogger.h> |
|
24 #include "CUsbSession.h" |
|
25 #include "CUsbDevice.h" |
|
26 #include "CUsbServer.h" |
|
27 |
|
28 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
29 #include "CUsbOtg.h" |
|
30 #include "cusbhost.h" |
|
31 #endif // SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
32 |
|
33 #include <usbstates.h> |
|
34 #include <usberrors.h> |
|
35 |
|
36 #include <usb/usbshared.h> |
|
37 #include "CPersonality.h" |
|
38 #include "rusb.h" |
|
39 #include "UsbSettings.h" |
|
40 |
|
41 #ifdef __FLOG_ACTIVE |
|
42 _LIT8(KLogComponent, "USBSVR"); |
|
43 #endif |
|
44 |
|
45 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
46 CUsbSession* CUsbSession::iCtlSession = NULL; |
|
47 #endif // SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
48 |
|
49 /** |
|
50 * Construct a Symbian OS session object. |
|
51 * |
|
52 * @internalComponent |
|
53 * @param aServer Service the session will be a member of |
|
54 * |
|
55 * @return A new CUsbSession object |
|
56 */ |
|
57 CUsbSession* CUsbSession::NewL(CUsbServer* aServer) |
|
58 { |
|
59 LOG_STATIC_FUNC_ENTRY |
|
60 |
|
61 //this class has moved away from standard NewL() semantics |
|
62 //and now uses the virtual CSession2::CreateL() function |
|
63 //[instead of ConstructL()] which is called by CServer2 |
|
64 //and finalises the construction of the session |
|
65 return (new (ELeave) CUsbSession(aServer)); |
|
66 } |
|
67 |
|
68 |
|
69 /** |
|
70 * Constructor. |
|
71 * |
|
72 * @internalComponent |
|
73 * @param aServer Service the session will be a member of |
|
74 */ |
|
75 CUsbSession::CUsbSession(CUsbServer* aServer) |
|
76 : iUsbServer(aServer) |
|
77 { |
|
78 LOG_FUNC |
|
79 |
|
80 iUsbServer->IncrementSessionCount(); |
|
81 } |
|
82 |
|
83 |
|
84 /** |
|
85 * Destructor. |
|
86 */ |
|
87 CUsbSession::~CUsbSession() |
|
88 { |
|
89 LOG_FUNC |
|
90 |
|
91 LOGTEXT2(_L8("About to Device().DeRegisterObserver(%08x"),this); |
|
92 iUsbServer->Device().DeRegisterObserver(*this); |
|
93 |
|
94 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
95 #ifndef __OVER_DUMMYUSBDI__ |
|
96 LOGTEXT2(_L8("About to Otg().DeRegisterObserver(%08x"),this); |
|
97 iUsbServer->Otg().DeRegisterObserver(*this); |
|
98 #endif |
|
99 |
|
100 LOGTEXT2(_L8("About to Host().DeRegisterObserver(%08x"),this); |
|
101 iUsbServer->Host().DeregisterObserver(*this); |
|
102 |
|
103 if ( iCtlSession && (iCtlSession == this) ) |
|
104 { |
|
105 iCtlSession = NULL; |
|
106 } |
|
107 #endif // SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
108 |
|
109 LOGTEXT(_L8("About to iUsbServer->DecrementSessionCount()")); |
|
110 iUsbServer->DecrementSessionCount(); |
|
111 } |
|
112 |
|
113 |
|
114 /** |
|
115 * Called when a message is received from the client. |
|
116 * |
|
117 * @param aMessage Message received from the client |
|
118 */ |
|
119 void CUsbSession::ServiceL(const RMessage2& aMessage) |
|
120 { |
|
121 LOG_FUNC |
|
122 |
|
123 DispatchMessageL(aMessage); |
|
124 } |
|
125 |
|
126 /** |
|
127 * Handles 2nd Phase Construction. Implementation of the virtual method defined in CSession2 and called from |
|
128 * CServer2::DoConnectL() which executes when the client makes a connection request through CServer2::Connect(). If |
|
129 * a Leave occurs at any point the CUsbSession object is cleaned up in CServer2::DoConnect(). |
|
130 */ |
|
131 void CUsbSession::CreateL() |
|
132 { |
|
133 LOG_FUNC |
|
134 |
|
135 // This code originally existed in the typical non-virtual ConstructL() method. |
|
136 // However it was moved to this method for minor optimisation reasons [three less |
|
137 // function calls and several lines less code in the NewL() method]. |
|
138 |
|
139 iPersonalityCfged = iUsbServer->Device().isPersonalityCfged(); |
|
140 |
|
141 LOGTEXT(_L8("Registering Device Observer\n")); |
|
142 iUsbServer->Device().RegisterObserverL(*this); |
|
143 |
|
144 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
145 #ifndef __OVER_DUMMYUSBDI__ |
|
146 LOGTEXT(_L8("Registering OTG Observer\n")); |
|
147 iUsbServer->Otg().RegisterObserverL(*this); |
|
148 #endif |
|
149 |
|
150 LOGTEXT(_L8("Registering HOST Observer\n")); |
|
151 iUsbServer->Host().RegisterObserverL(*this); |
|
152 #endif // SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
153 } |
|
154 |
|
155 /** |
|
156 * Called by CUsbDevice when the service state changes. |
|
157 * CUsbSession is an observer of the device. |
|
158 * |
|
159 * @param aLastError The last error happened |
|
160 * @param aOldState The device's service state just before it changed |
|
161 * @param aNewState The device's new and current service state |
|
162 */ |
|
163 void CUsbSession::UsbServiceStateChange(TInt aLastError, TUsbServiceState aOldState, |
|
164 TUsbServiceState aNewState) |
|
165 { |
|
166 LOG_FUNC |
|
167 LOGTEXT3(_L8(" aOldState=0x%X, aNewState=0x%X"), aOldState, aNewState); |
|
168 (void) aOldState; // a-void build warning in UREL |
|
169 |
|
170 // Note that it's possible to have both a start and a stop outstanding! |
|
171 |
|
172 if (iStartOutstanding) |
|
173 { |
|
174 HandleServiceStateChangeWhileStarting(aLastError, aNewState); |
|
175 } |
|
176 |
|
177 if (iStopOutstanding) |
|
178 { |
|
179 HandleServiceStateChangeWhileStopping(aLastError, aNewState); |
|
180 } |
|
181 |
|
182 // Check whether we have an observer of the service state. |
|
183 |
|
184 if (iServiceObserverOutstanding) |
|
185 { |
|
186 TPckg<TUint32> pckg(aNewState); |
|
187 iServiceObserverOutstanding = EFalse; |
|
188 const TInt err = iServiceObserverMessage.Write(0, pckg); |
|
189 iServiceObserverMessage.Complete(err); |
|
190 } |
|
191 } |
|
192 |
|
193 /** |
|
194 * Handles a state change while a start request is currently outstanding. |
|
195 * |
|
196 * @param aLastError The last error happened |
|
197 * @param aNewState The state we've moved to |
|
198 */ |
|
199 void CUsbSession::HandleServiceStateChangeWhileStarting(TInt aLastError, |
|
200 TUsbServiceState aNewState) |
|
201 { |
|
202 LOG_FUNC |
|
203 |
|
204 switch (aNewState) |
|
205 { |
|
206 case EUsbServiceStarted: |
|
207 LOGTEXT(_L8(" Completing Start successfully")); |
|
208 |
|
209 // If the user has tried to cancel the start, they're too late! |
|
210 if (iCancelOutstanding) |
|
211 { |
|
212 LOGTEXT(_L8(" Completing cancel request with KErrNone")); |
|
213 iCancelOutstanding = EFalse; |
|
214 iCancelMessage.Complete(KErrNone); |
|
215 } |
|
216 |
|
217 iStartMessage.Complete(KErrNone); |
|
218 iStartOutstanding = EFalse; |
|
219 break; |
|
220 |
|
221 case EUsbServiceIdle: |
|
222 LOGTEXT2(_L8(" Completing Start with error=%d"), aLastError); |
|
223 |
|
224 // If there hasn't actually been an error, but we're in an unexpected |
|
225 // state now, that means that this client cancelled the request, or |
|
226 // another client stopped the service. |
|
227 if (aLastError == KErrNone) |
|
228 { |
|
229 // If there's a cancel outstanding, then that message succeeded, but |
|
230 // the start message should be completed with KErrCancel. |
|
231 if (iCancelOutstanding) |
|
232 { |
|
233 LOGTEXT(_L8(" Completing original message with KErrCancel")); |
|
234 iCancelOutstanding = EFalse; |
|
235 iCancelMessage.Complete(KErrNone); |
|
236 iStartMessage.Complete(KErrCancel); |
|
237 } |
|
238 else |
|
239 { |
|
240 iStartMessage.Complete(KErrUsbServiceStopped); |
|
241 } |
|
242 } |
|
243 else |
|
244 { |
|
245 // There's been some kind of error, so complete the original message |
|
246 // with the right error code. |
|
247 if (iCancelOutstanding) |
|
248 { |
|
249 iCancelOutstanding = EFalse; |
|
250 iCancelMessage.Complete(KErrNone); |
|
251 } |
|
252 iStartMessage.Complete(aLastError); |
|
253 } |
|
254 |
|
255 iStartOutstanding = EFalse; |
|
256 break; |
|
257 |
|
258 default: |
|
259 break; |
|
260 } |
|
261 } |
|
262 |
|
263 /** |
|
264 * Handles a state change while a stop request is currently outstanding. |
|
265 * |
|
266 * @param aLastError The last error happened |
|
267 * @param aNewState The state we've moved to |
|
268 */ |
|
269 void CUsbSession::HandleServiceStateChangeWhileStopping(TInt aLastError, |
|
270 TUsbServiceState aNewState) |
|
271 { |
|
272 LOG_FUNC |
|
273 |
|
274 switch (aNewState) |
|
275 { |
|
276 case EUsbServiceStarted: |
|
277 LOGTEXT2(_L8(" Completing Stop with error=%d"), aLastError); |
|
278 |
|
279 // If there hasn't actually been an error, but we're in an unexpected |
|
280 // state now, that means that this client cancelled the request, or |
|
281 // another client has started the service. |
|
282 if (aLastError == KErrNone) |
|
283 { |
|
284 // If there's a cancel outstanding, then that message succeeded, but |
|
285 // the stop message should be completed with KErrCancel. |
|
286 if (iCancelOutstanding) |
|
287 { |
|
288 LOGTEXT(_L8(" Completing original message with KErrCancel")); |
|
289 iCancelOutstanding = EFalse; |
|
290 iCancelMessage.Complete(KErrNone); |
|
291 iStopMessage.Complete(KErrCancel); |
|
292 } |
|
293 else |
|
294 { |
|
295 iStopMessage.Complete(KErrUsbServiceStarted); |
|
296 } |
|
297 } |
|
298 else |
|
299 { |
|
300 // There's been some kind of error, so complete the original message |
|
301 // with the right error code. |
|
302 if (iCancelOutstanding) |
|
303 { |
|
304 iCancelOutstanding = EFalse; |
|
305 iCancelMessage.Complete(KErrNone); |
|
306 } |
|
307 iStopMessage.Complete(aLastError); |
|
308 } |
|
309 |
|
310 iStopOutstanding = EFalse; |
|
311 break; |
|
312 |
|
313 case EUsbServiceIdle: |
|
314 LOGTEXT(_L8(" Completing Stop with KErrNone")); |
|
315 |
|
316 // If the user has tried to cancel the stop, they're too late! |
|
317 if (iCancelOutstanding) |
|
318 { |
|
319 LOGTEXT(_L8(" Completing cancel request with KErrNone")); |
|
320 iCancelOutstanding = EFalse; |
|
321 iCancelMessage.Complete(KErrNone); |
|
322 } |
|
323 |
|
324 iStopMessage.Complete(KErrNone); |
|
325 iStopOutstanding = EFalse; |
|
326 break; |
|
327 |
|
328 default: |
|
329 break; |
|
330 } |
|
331 } |
|
332 |
|
333 /** |
|
334 * Called by CUsbDevice when it state change. CUsbSession is an observer of |
|
335 * the device. If the client has an Observer outstanding then complete it, |
|
336 * otherwise put it in a circular queue. |
|
337 * |
|
338 * @internalComponent |
|
339 * @param aLastError The last error happened |
|
340 * @param aOldState The device's state just before it changed |
|
341 * @param aNewState The device's new and current state |
|
342 */ |
|
343 void CUsbSession::UsbDeviceStateChange(TInt /*aLastError*/, TUsbDeviceState /*aOldState*/, |
|
344 TUsbDeviceState aNewState) |
|
345 { |
|
346 LOG_FUNC |
|
347 |
|
348 // can we bypass the queue? |
|
349 if ((iDeviceObserverOutstanding) && (iDevStateQueueHead == iDevStateQueueTail)) |
|
350 { |
|
351 if ((iDeviceObserverMessage.Int0() & aNewState) || |
|
352 (aNewState == EUsbDeviceStateUndefined)) |
|
353 { |
|
354 TPckg<TUint32> pckg(aNewState); |
|
355 |
|
356 iNotifiedDevState = aNewState; |
|
357 |
|
358 iDeviceObserverOutstanding = EFalse; |
|
359 const TInt err = iDeviceObserverMessage.Write(1, pckg); |
|
360 iDeviceObserverMessage.Complete(err); |
|
361 } |
|
362 } |
|
363 else if (iObserverQueueEvents) |
|
364 { |
|
365 TBool addToQueue = ETrue; |
|
366 |
|
367 // Search queue for similar event, truncate event queue if found |
|
368 if (aNewState == EUsbDeviceStateUndefined) |
|
369 { |
|
370 // erase Event queue, just want this event - not interested in how we got here |
|
371 iDevStateQueueTail = iDevStateQueueHead; |
|
372 |
|
373 // if this is also the event mostly recently notified then don't bother to queue it |
|
374 if(aNewState == iNotifiedDevState) |
|
375 addToQueue = EFalse; |
|
376 } |
|
377 else |
|
378 { |
|
379 TInt queuePtr = iDevStateQueueTail; |
|
380 |
|
381 // search forward from tail to head |
|
382 while (queuePtr != iDevStateQueueHead) |
|
383 { |
|
384 if (aNewState == iDeviceStateQueue[queuePtr]) |
|
385 { |
|
386 // Event is already queued; discard the duplicate and in-between events |
|
387 LOGTEXT3(_L8("--- collapsing queue head (%d, %d)"), |
|
388 iDevStateQueueHead, |
|
389 (queuePtr + 1) % KDeviceStatesQueueSize); |
|
390 |
|
391 // queue head moved to position following the match |
|
392 iDevStateQueueHead = (queuePtr + 1) % KDeviceStatesQueueSize; |
|
393 addToQueue = EFalse; |
|
394 break; |
|
395 } |
|
396 |
|
397 // work our way through queue |
|
398 queuePtr = (queuePtr + 1) % KDeviceStatesQueueSize; |
|
399 } |
|
400 } |
|
401 |
|
402 // still want to add to queue? |
|
403 if (addToQueue) |
|
404 { |
|
405 // add event to head of queue |
|
406 iDeviceStateQueue[iDevStateQueueHead] = aNewState; |
|
407 iDevStateQueueHead = (iDevStateQueueHead + 1) % KDeviceStatesQueueSize; |
|
408 LOGTEXT3(_L8("+++ addqueue (%d, %d)"), iDevStateQueueHead, |
|
409 iDevStateQueueTail); |
|
410 } |
|
411 |
|
412 // UsbDeviceDequeueEvent() will read from queue when RegisterObserver() |
|
413 // is next called. |
|
414 } |
|
415 } |
|
416 |
|
417 /** |
|
418 * Dequeues an event and completes the observer's request with it. |
|
419 */ |
|
420 void CUsbSession::UsbDeviceDequeueEvent() |
|
421 { |
|
422 LOG_FUNC |
|
423 |
|
424 // Work our way through the queue, until we reach the end |
|
425 // OR we find an event the current observer wants. |
|
426 while ((iDeviceObserverOutstanding) && (iDevStateQueueHead != iDevStateQueueTail)) |
|
427 { |
|
428 // inform the observer of state changes they are interested in AND |
|
429 // if the cable is pulled out (EUsbDeviceStateUndefined) |
|
430 TUsbDeviceState newState = iDeviceStateQueue[iDevStateQueueTail]; |
|
431 |
|
432 // advance tail towards the head |
|
433 iDevStateQueueTail = (iDevStateQueueTail + 1) % KDeviceStatesQueueSize; |
|
434 |
|
435 // is this state one the Observer wants? |
|
436 if ((iDeviceObserverMessage.Int0() & newState) || |
|
437 (newState == EUsbDeviceStateUndefined)) |
|
438 { |
|
439 TPckg<TUint32> pckg(newState); |
|
440 |
|
441 iNotifiedDevState = newState; |
|
442 |
|
443 LOGTEXT3(_L8(">>> dequeued event #%d (0x%x)"), iDevStateQueueTail, newState); |
|
444 |
|
445 iDeviceObserverOutstanding = EFalse; |
|
446 const TInt err = iDeviceObserverMessage.Write(1, pckg); |
|
447 iDeviceObserverMessage.Complete(err); |
|
448 break; |
|
449 } |
|
450 } |
|
451 } |
|
452 |
|
453 /** |
|
454 * Handles the request (in the form of a the message) received from the client |
|
455 * |
|
456 * @internalComponent |
|
457 * @param aMessage The received message |
|
458 */ |
|
459 void CUsbSession::DispatchMessageL(const RMessage2& aMessage) |
|
460 { |
|
461 LOG_FUNC |
|
462 |
|
463 TBool complete = ETrue; |
|
464 TInt ret = KErrNone; |
|
465 |
|
466 LOGTEXT2(_L8("CUsbSession::DispatchMessageL(): func# %d"), aMessage.Function()); |
|
467 |
|
468 switch (aMessage.Function()) |
|
469 { |
|
470 case EUsbStart: |
|
471 ret = StartDeviceL(aMessage, complete); |
|
472 break; |
|
473 case EUsbStop: |
|
474 ret = StopDeviceL(aMessage, complete); |
|
475 break; |
|
476 case EUsbGetCurrentState: |
|
477 ret = GetCurrentServiceState(aMessage); |
|
478 break; |
|
479 case EUsbGetCurrentDeviceState: |
|
480 ret = GetCurrentDeviceState(aMessage); |
|
481 break; |
|
482 case EUsbRegisterServiceObserver: |
|
483 ret = RegisterServiceObserver(aMessage, complete); |
|
484 break; |
|
485 case EUsbRegisterObserver: |
|
486 ret = RegisterDeviceObserver(aMessage, complete); |
|
487 break; |
|
488 case EUsbStartCancel: |
|
489 ret = StartCancel(aMessage, complete); |
|
490 break; |
|
491 case EUsbStopCancel: |
|
492 ret = StopCancel(aMessage, complete); |
|
493 break; |
|
494 case EUsbCancelServiceObserver: |
|
495 ret = DeRegisterServiceObserver(); |
|
496 break; |
|
497 case EUsbCancelObserver: |
|
498 ret = DeRegisterDeviceObserver(); |
|
499 break; |
|
500 case EUsbTryStart: |
|
501 ret = TryStartDeviceL(aMessage, complete); |
|
502 break; |
|
503 case EUsbTryStop: |
|
504 ret = TryStopDeviceL(aMessage, complete); |
|
505 break; |
|
506 case EUsbCancelInterest: |
|
507 ret = CancelInterest(aMessage); |
|
508 break; |
|
509 case EUsbGetCurrentPersonalityId: |
|
510 ret = GetCurrentPersonalityId(aMessage); |
|
511 break; |
|
512 case EUsbGetSupportedClasses: |
|
513 ret = GetSupportedClasses(aMessage); |
|
514 break; |
|
515 case EUsbGetPersonalityIds: |
|
516 ret = GetPersonalityIds(aMessage); |
|
517 break; |
|
518 case EUsbGetDescription: |
|
519 ret = GetDescription(aMessage); |
|
520 break; |
|
521 case EUsbGetDetailedDescription: |
|
522 ret = GetDetailedDescription(aMessage); |
|
523 break; |
|
524 case EUsbGetPersonalityProperty: |
|
525 ret = GetPersonalityProperty(aMessage); |
|
526 break; |
|
527 case EUsbClassSupported: |
|
528 ret = ClassSupported(aMessage); |
|
529 break; |
|
530 |
|
531 #ifdef _DEBUG |
|
532 // Heap failure debug APIs. |
|
533 |
|
534 case EUsbDbgMarkHeap: |
|
535 LOGTEXT(_L8("Marking heap")); |
|
536 __UHEAP_MARK; |
|
537 break; |
|
538 case EUsbDbgCheckHeap: |
|
539 LOGTEXT2(_L8("Checking heap (expecting %d cells)"), aMessage.Int0()); |
|
540 __UHEAP_CHECK(aMessage.Int0()); |
|
541 break; |
|
542 case EUsbDbgMarkEnd: |
|
543 LOGTEXT2(_L8("End of marking heap (expecting %d cells)"), aMessage.Int0()); |
|
544 __UHEAP_MARKENDC(aMessage.Int0()); |
|
545 break; |
|
546 case EUsbDbgFailNext: |
|
547 { |
|
548 LOGTEXT2(_L8("Simulating failure after %d allocation(s)"), aMessage.Int0()); |
|
549 if (aMessage.Int0() == 0) |
|
550 __UHEAP_RESET; |
|
551 else |
|
552 __UHEAP_FAILNEXT(aMessage.Int0()); |
|
553 } |
|
554 break; |
|
555 case EUsbDbgAlloc: |
|
556 { |
|
557 ret = KErrNone; |
|
558 #ifdef _DEBUG |
|
559 LOGTEXT(_L8("\tallocate on the heap")); |
|
560 TInt* x = NULL; |
|
561 TRAP(ret, x = new(ELeave) TInt); |
|
562 delete x; |
|
563 #endif // _DEBUG |
|
564 } |
|
565 break; |
|
566 |
|
567 #endif |
|
568 |
|
569 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
570 case EUsbSetCtlSessionMode: |
|
571 ret = SetCtlSessionMode(aMessage); |
|
572 break; |
|
573 case EUsbRegisterMessageObserver: |
|
574 ret = RegisterMsgObserver(aMessage, complete); |
|
575 break; |
|
576 case EUsbCancelMessageObserver: |
|
577 ret = DeRegisterMsgObserver(); |
|
578 break; |
|
579 #ifndef __OVER_DUMMYUSBDI__ |
|
580 case EUsbBusRequest: |
|
581 ret = BusRequest(); |
|
582 break; |
|
583 case EUsbBusRespondSrp: |
|
584 ret = BusRespondSrp(); |
|
585 break; |
|
586 case EUsbBusClearError: |
|
587 ret = BusClearError(); |
|
588 break; |
|
589 case EUsbBusDrop: |
|
590 ret = BusDrop(); |
|
591 break; |
|
592 #else |
|
593 case EUsbBusRequest: |
|
594 case EUsbBusRespondSrp: |
|
595 case EUsbBusClearError: |
|
596 case EUsbBusDrop: |
|
597 ret = KErrNone; |
|
598 break; |
|
599 #endif |
|
600 case EUsbRegisterHostObserver: |
|
601 ret = RegisterHostObserver(aMessage, complete); |
|
602 break; |
|
603 case EUsbCancelHostObserver: |
|
604 ret = DeRegisterHostObserver(); |
|
605 break; |
|
606 case EUsbEnableFunctionDriverLoading: |
|
607 ret = EnableFunctionDriverLoading(); |
|
608 break; |
|
609 case EUsbDisableFunctionDriverLoading: |
|
610 ret = DisableFunctionDriverLoading(); |
|
611 break; |
|
612 case EUsbGetSupportedLanguages: |
|
613 ret = GetSupportedLanguages(aMessage); |
|
614 break; |
|
615 case EUsbGetManufacturerStringDescriptor: |
|
616 ret = GetManufacturerStringDescriptor(aMessage); |
|
617 break; |
|
618 case EUsbGetProductStringDescriptor: |
|
619 ret = GetProductStringDescriptor(aMessage); |
|
620 break; |
|
621 case EUsbGetOtgDescriptor: |
|
622 ret = GetOtgDescriptor(aMessage); |
|
623 break; |
|
624 case EUsbRequestSession: |
|
625 ret = RequestSession(); |
|
626 break; |
|
627 #else // !SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
628 case EUsbSetCtlSessionMode: |
|
629 case EUsbRegisterMessageObserver: |
|
630 case EUsbCancelMessageObserver: |
|
631 case EUsbBusRequest: |
|
632 case EUsbBusRespondSrp: |
|
633 case EUsbBusClearError: |
|
634 case EUsbBusDrop: |
|
635 case EUsbRegisterHostObserver: |
|
636 case EUsbCancelHostObserver: |
|
637 case EUsbEnableFunctionDriverLoading: |
|
638 case EUsbDisableFunctionDriverLoading: |
|
639 case EUsbGetSupportedLanguages: |
|
640 case EUsbGetManufacturerStringDescriptor: |
|
641 case EUsbGetProductStringDescriptor: |
|
642 case EUsbGetOtgDescriptor: |
|
643 case EUsbRequestSession: |
|
644 ret = KErrNotSupported; |
|
645 break; |
|
646 #endif // SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
647 |
|
648 default: |
|
649 LOGTEXT2(_L8("Illegal IPC argument(%d) - Panicking Client..."), aMessage.Function()); |
|
650 aMessage.Panic(KUsbCliPncCat, EUsbPanicIllegalIPC); |
|
651 complete = EFalse; |
|
652 break; |
|
653 } |
|
654 |
|
655 if (complete) |
|
656 aMessage.Complete(ret); |
|
657 } |
|
658 |
|
659 |
|
660 /** |
|
661 * Client request to start the device. |
|
662 * |
|
663 * @param aMessage Message received from the client |
|
664 * @param aComplete Whether the request is complete or not |
|
665 * @return Any error that occurred or KErrNone |
|
666 */ |
|
667 TInt CUsbSession::StartDeviceL(const RMessage2& aMessage, TBool& aComplete) |
|
668 { |
|
669 LOG_FUNC |
|
670 |
|
671 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
672 // Only 'control' session is allowed to start USB support |
|
673 if ( !iSessionCtlMode ) |
|
674 { |
|
675 return KErrAccessDenied; |
|
676 } |
|
677 #endif |
|
678 |
|
679 if (iStartOutstanding) |
|
680 return KErrInUse; |
|
681 |
|
682 #ifndef __OVER_DUMMYUSBDI__ |
|
683 |
|
684 // If the service is idle or stopping, then we just need to start it. |
|
685 // If it's starting (ie. by another client), then we need to perform nothing |
|
686 // but wait for the start to complete. |
|
687 // If it's already started, we just return immediately. |
|
688 TUsbServiceState state = iUsbServer->Device().ServiceState(); |
|
689 |
|
690 if ((state == EUsbServiceIdle) || (state == EUsbServiceStopping)) |
|
691 { |
|
692 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
693 iUsbServer->Host().StartL(); |
|
694 #endif |
|
695 iUsbServer->Device().StartL(); |
|
696 |
|
697 aComplete = EFalse; |
|
698 iStartMessage = aMessage; |
|
699 iStartOutstanding = ETrue; |
|
700 } |
|
701 else if (state == EUsbServiceStarting) |
|
702 { |
|
703 aComplete = EFalse; |
|
704 iStartMessage = aMessage; |
|
705 iStartOutstanding = ETrue; |
|
706 } |
|
707 |
|
708 return KErrNone; |
|
709 |
|
710 #else |
|
711 // pretend that the server is in Started state |
|
712 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
713 iUsbServer->Host().StartL(); |
|
714 #endif |
|
715 iStartOutstanding = EFalse; |
|
716 aMessage.IsNull(); |
|
717 aComplete = ETrue; |
|
718 return KErrNone; |
|
719 |
|
720 #endif |
|
721 } |
|
722 |
|
723 /** |
|
724 * Client request to stop the device. |
|
725 * |
|
726 * @param aMessage Message received from the client |
|
727 * @param aComplete Whether the request is complete or not |
|
728 * @return Any error that occurred or KErrNone |
|
729 */ |
|
730 TInt CUsbSession::StopDeviceL(const RMessage2& aMessage, TBool& aComplete) |
|
731 { |
|
732 LOG_FUNC |
|
733 |
|
734 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
735 // Only 'control' session is allowed to stop USB support |
|
736 if ( !iSessionCtlMode ) |
|
737 { |
|
738 return KErrAccessDenied; |
|
739 } |
|
740 #endif |
|
741 |
|
742 if (iStopOutstanding) |
|
743 { |
|
744 return KErrInUse; |
|
745 } |
|
746 |
|
747 #ifndef __OVER_DUMMYUSBDI__ |
|
748 |
|
749 // Only do anything if the service isn't currently idle. If it is, we just |
|
750 // need to complete the user's request immediately. |
|
751 if (iUsbServer->Device().ServiceState() != EUsbServiceIdle) |
|
752 { |
|
753 iUsbServer->Device().Stop(); |
|
754 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
755 iUsbServer->Host().Stop(); |
|
756 #endif |
|
757 |
|
758 aComplete = EFalse; |
|
759 iStopMessage = aMessage; |
|
760 iStopOutstanding = ETrue; |
|
761 } |
|
762 |
|
763 return KErrNone; |
|
764 |
|
765 #else |
|
766 // pretend that the server is in Started state |
|
767 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
768 iUsbServer->Host().Stop(); |
|
769 #endif |
|
770 aComplete = ETrue; |
|
771 aMessage.IsNull(); |
|
772 iStopOutstanding = EFalse; |
|
773 return KErrNone; |
|
774 |
|
775 #endif |
|
776 } |
|
777 |
|
778 /** |
|
779 * Cancel the pending start operation. Note that this can just be implemented |
|
780 * as a synchronous stop, if the start operation is pending. However, we have to |
|
781 * retain the cancel message, so we can complete it when the stop completes. |
|
782 * |
|
783 * @param aMessage The message from the client |
|
784 * @param aComplete Whether the message is complete or not |
|
785 * @return Always KErrNone |
|
786 */ |
|
787 TInt CUsbSession::StartCancel(const RMessage2& aMessage, TBool& aComplete) |
|
788 { |
|
789 LOG_FUNC |
|
790 |
|
791 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
792 // Only 'control' session is allowed to cancel outstaning start request |
|
793 if ( !iSessionCtlMode ) |
|
794 { |
|
795 return KErrAccessDenied; |
|
796 } |
|
797 #endif |
|
798 |
|
799 if (!iStartOutstanding) |
|
800 return KErrNone; |
|
801 |
|
802 aComplete = EFalse; |
|
803 iCancelMessage = aMessage; |
|
804 iCancelOutstanding = ETrue; |
|
805 |
|
806 if (iUsbServer->Device().ServiceState() != EUsbServiceIdle) |
|
807 { |
|
808 iUsbServer->Device().Stop(); |
|
809 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
810 iUsbServer->Host().Stop(); |
|
811 #endif |
|
812 } |
|
813 |
|
814 return KErrNone; |
|
815 } |
|
816 |
|
817 /** |
|
818 * Cancel the pending stop operation. Note that this can just be implemented as |
|
819 * a synchronous start, if the stop operation is pending. However, we have to |
|
820 * retain the cancel message, so we can complete it when the start completes. |
|
821 * |
|
822 * @param aMessage The message from the client |
|
823 * @param aComplete Whether the message is complete or not |
|
824 * @return KErrNone on success, otherwise standard error codes |
|
825 */ |
|
826 TInt CUsbSession::StopCancel(const RMessage2& aMessage, TBool& aComplete) |
|
827 { |
|
828 LOG_FUNC |
|
829 |
|
830 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
831 // Only 'control' session is allowed to cancel outstaning stop request |
|
832 if ( !iSessionCtlMode ) |
|
833 { |
|
834 return KErrAccessDenied; |
|
835 } |
|
836 #endif |
|
837 |
|
838 if (!iStopOutstanding) |
|
839 { |
|
840 return KErrNone; |
|
841 } |
|
842 |
|
843 aComplete = EFalse; |
|
844 iCancelMessage = aMessage; |
|
845 iCancelOutstanding = ETrue; |
|
846 |
|
847 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
848 TRAPD(errHost,iUsbServer->Host().StartL()); |
|
849 if (errHost != KErrNone) |
|
850 return errHost; |
|
851 #endif |
|
852 TRAPD(err, iUsbServer->Device().StartL()); |
|
853 return err; |
|
854 } |
|
855 |
|
856 /** |
|
857 * Client request to observe the device (for state changes). |
|
858 * Asks the device to register the session as an observer. |
|
859 * Assures initialisation/dequeueing of Event queue. |
|
860 * |
|
861 * @param aMessage Message received from the client |
|
862 * @param aComplete set to true to complete the request |
|
863 * |
|
864 * @return Any error that occurred or KErrNone |
|
865 */ |
|
866 TInt CUsbSession::RegisterDeviceObserver(const RMessage2& aMessage, TBool& aComplete) |
|
867 { |
|
868 LOG_FUNC |
|
869 |
|
870 if (iDeviceObserverOutstanding) |
|
871 { |
|
872 return KErrInUse; |
|
873 } |
|
874 |
|
875 iDeviceObserverMessage = aMessage; |
|
876 iDeviceObserverOutstanding = ETrue; |
|
877 aComplete = EFalse; |
|
878 |
|
879 if (iObserverQueueEvents == EFalse) |
|
880 { |
|
881 // This is the first observer after c'tor or DeregisterObserver(), |
|
882 // so zap the device event queue. |
|
883 LOGTEXT(_L8(" Reset Device Event Queue")); |
|
884 iDevStateQueueHead = 0; |
|
885 iDevStateQueueTail = 0; |
|
886 iObserverQueueEvents = ETrue; |
|
887 } |
|
888 else if (iDevStateQueueHead != iDevStateQueueTail) |
|
889 { |
|
890 // event(s) queued, we can de-queue one now |
|
891 UsbDeviceDequeueEvent(); |
|
892 } |
|
893 |
|
894 return KErrNone; |
|
895 } |
|
896 |
|
897 /** |
|
898 * Client request to observe the service (for state changes) |
|
899 * Asks the device to register the session as an observer |
|
900 * |
|
901 * @internalComponent |
|
902 * @param aMessage Message received from the client |
|
903 * @param aComplete set to true to complete the request |
|
904 * |
|
905 * @return Any error that occurred or KErrNone |
|
906 */ |
|
907 TInt CUsbSession::RegisterServiceObserver(const RMessage2& aMessage, TBool& aComplete) |
|
908 { |
|
909 LOG_FUNC |
|
910 |
|
911 if (iServiceObserverOutstanding) |
|
912 { |
|
913 return KErrInUse; |
|
914 } |
|
915 |
|
916 iServiceObserverMessage = aMessage; |
|
917 iServiceObserverOutstanding = ETrue; |
|
918 aComplete = EFalse; |
|
919 return KErrNone; |
|
920 } |
|
921 |
|
922 |
|
923 /** |
|
924 * Client request to fetch the current service state of the device |
|
925 * Asks the device for its current service state |
|
926 * |
|
927 * @internalComponent |
|
928 * @param aMessage Message received from the client |
|
929 * |
|
930 * @return Any errors that occurred or KErrNone |
|
931 */ |
|
932 TInt CUsbSession::GetCurrentServiceState(const RMessage2& aMessage) |
|
933 { |
|
934 LOG_FUNC |
|
935 |
|
936 TUsbServiceState state = iUsbServer->Device().ServiceState(); |
|
937 LOGTEXT2(_L8("\tstate = %d"), state); |
|
938 TPckg<TUint32> pckg(state); |
|
939 return aMessage.Write(0, pckg); |
|
940 } |
|
941 |
|
942 /** |
|
943 * Client request to fetch the current device state of the device |
|
944 * Asks the device for its current device state |
|
945 * |
|
946 * @internalComponent |
|
947 * @param aMessage Message received from the client |
|
948 * |
|
949 * @return Any errors that occurred or KErrNone |
|
950 */ |
|
951 TInt CUsbSession::GetCurrentDeviceState(const RMessage2& aMessage) |
|
952 { |
|
953 LOG_FUNC |
|
954 |
|
955 TUsbDeviceState state = iUsbServer->Device().DeviceState(); |
|
956 LOGTEXT2(_L8("\tstate = %d"), state); |
|
957 TPckg<TUint32> pckg(state); |
|
958 return aMessage.Write(0, pckg); |
|
959 } |
|
960 |
|
961 |
|
962 /** |
|
963 * Deregister the client as an observer of device state changes. Note that we don't |
|
964 * deregister ourselves as an observer, because we need to be notified when the |
|
965 * device state changes, so we can complete Start and Stop requests. |
|
966 * |
|
967 * @return Always KErrNone |
|
968 */ |
|
969 TInt CUsbSession::DeRegisterDeviceObserver() |
|
970 { |
|
971 LOG_FUNC |
|
972 |
|
973 if (!iDeviceObserverOutstanding) |
|
974 { |
|
975 return KErrNone; |
|
976 } |
|
977 |
|
978 iDeviceObserverOutstanding = EFalse; |
|
979 iDeviceObserverMessage.Complete(KErrCancel); |
|
980 |
|
981 // client doesn't need events queuing any more |
|
982 iObserverQueueEvents = EFalse; |
|
983 |
|
984 return KErrNone; |
|
985 } |
|
986 |
|
987 /** |
|
988 * Deregister the client as an observer of service state changes. Note that we don't |
|
989 * deregister ourselves as an observer, because we need to be notified when the |
|
990 * service state changes, so we can complete Start and Stop requests. |
|
991 * |
|
992 * @return Always KErrNone |
|
993 */ |
|
994 TInt CUsbSession::DeRegisterServiceObserver() |
|
995 { |
|
996 LOG_FUNC |
|
997 |
|
998 if (!iServiceObserverOutstanding) |
|
999 { |
|
1000 return KErrNone; |
|
1001 } |
|
1002 |
|
1003 iServiceObserverOutstanding = EFalse; |
|
1004 iServiceObserverMessage.Complete(KErrCancel); |
|
1005 return KErrNone; |
|
1006 } |
|
1007 |
|
1008 /** |
|
1009 * Try starting the USB device. |
|
1010 * |
|
1011 * @internalComponent |
|
1012 * @param aMessage Message received from the client |
|
1013 * @param aComplete set to true to complete the request |
|
1014 * @return Any error that occurred or KErrNone |
|
1015 */ |
|
1016 TInt CUsbSession::TryStartDeviceL(const RMessage2& aMessage, TBool& aComplete) |
|
1017 { |
|
1018 LOG_FUNC |
|
1019 |
|
1020 #ifndef __OVER_DUMMYUSBDI__ |
|
1021 |
|
1022 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
1023 // Only 'control' session is allowed to start USB support |
|
1024 if ( !iSessionCtlMode ) |
|
1025 { |
|
1026 return KErrAccessDenied; |
|
1027 } |
|
1028 #endif |
|
1029 |
|
1030 if (!iPersonalityCfged) |
|
1031 { |
|
1032 return KErrNotSupported; |
|
1033 } |
|
1034 |
|
1035 if (iStartOutstanding || iStopOutstanding) |
|
1036 { |
|
1037 return KErrServerBusy; |
|
1038 } |
|
1039 |
|
1040 // Obtains the curent service state |
|
1041 TUsbServiceState state = iUsbServer->Device().ServiceState(); |
|
1042 |
|
1043 |
|
1044 // USB Peripheral Stack Starting sequence: |
|
1045 // if the server is in the idle state |
|
1046 // start it; |
|
1047 // if the server is in the started state |
|
1048 // return KErrNone immediately; |
|
1049 // if the server is in the stopping state |
|
1050 // return KErrServerBusy immediately; |
|
1051 // if the server is in the starting state |
|
1052 // (was already called by this very session in OTG/Host configuration and/or |
|
1053 // by another session for Client Only configuration) |
|
1054 // if requested personality is not equal to the current one |
|
1055 // return KErrAbort; |
|
1056 // else |
|
1057 // mark this request as outstanding and let the caller to wait |
|
1058 // for start operation to complete; |
|
1059 if (state == EUsbServiceIdle) |
|
1060 { |
|
1061 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
1062 iUsbServer->Host().StartL(); |
|
1063 #endif |
|
1064 iUsbServer->Device().TryStartL(aMessage.Int0()); |
|
1065 aComplete = EFalse; |
|
1066 iStartMessage = aMessage; |
|
1067 iStartOutstanding = ETrue; |
|
1068 } |
|
1069 else if (state == EUsbServiceStarting || state == EUsbServiceStarted) |
|
1070 { |
|
1071 if (aMessage.Int0() != iUsbServer->Device().CurrentPersonalityId()) |
|
1072 { |
|
1073 return KErrAbort; |
|
1074 } |
|
1075 |
|
1076 if (state == EUsbServiceStarting) |
|
1077 { |
|
1078 aComplete = EFalse; |
|
1079 iStartMessage = aMessage; |
|
1080 iStartOutstanding = ETrue; |
|
1081 } |
|
1082 } |
|
1083 else if (state == EUsbServiceStopping) |
|
1084 { |
|
1085 return KErrServerBusy; |
|
1086 } |
|
1087 |
|
1088 return KErrNone; |
|
1089 |
|
1090 #else |
|
1091 // pretend that the server is in Started state |
|
1092 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
1093 iUsbServer->Host().StartL(); |
|
1094 #endif |
|
1095 iStartOutstanding = EFalse; |
|
1096 aMessage.IsNull(); |
|
1097 aComplete = ETrue; |
|
1098 return KErrNone; |
|
1099 #endif |
|
1100 } |
|
1101 |
|
1102 /** |
|
1103 * Try stopping the USB device. |
|
1104 * |
|
1105 * @internalComponent |
|
1106 * @param aMessage Message received from the client |
|
1107 * @param aComplete Whether the request is complete or not |
|
1108 * @return Any error that occurred or KErrNone |
|
1109 */ |
|
1110 TInt CUsbSession::TryStopDeviceL(const RMessage2& aMessage, TBool& aComplete) |
|
1111 { |
|
1112 LOG_FUNC |
|
1113 |
|
1114 #ifndef __OVER_DUMMYUSBDI__ |
|
1115 |
|
1116 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
1117 // Only 'control' session is allowed to stop USB support |
|
1118 if ( !iSessionCtlMode ) |
|
1119 { |
|
1120 return KErrAccessDenied; |
|
1121 } |
|
1122 #endif |
|
1123 |
|
1124 if (!iPersonalityCfged) |
|
1125 { |
|
1126 return KErrNotSupported; |
|
1127 } |
|
1128 |
|
1129 if (iStartOutstanding || iStopOutstanding) |
|
1130 { |
|
1131 return KErrServerBusy; |
|
1132 } |
|
1133 |
|
1134 // Obtains the curent service state |
|
1135 TUsbServiceState state = iUsbServer->Device().ServiceState(); |
|
1136 |
|
1137 // USB Peripheral Stack Stopping sequence: |
|
1138 // if the server is in the started state |
|
1139 // stop it; |
|
1140 // if the server is in the starting state |
|
1141 // return KErrServerBusy immediately; |
|
1142 // if the server is in the idle state |
|
1143 // return KErrNone immediately; |
|
1144 // if the server is in the stopping state (must by another client) |
|
1145 // mark this request as outstanding and let the caller to wait |
|
1146 // for stop operation to complete; |
|
1147 if (state == EUsbServiceStarted) |
|
1148 { |
|
1149 iUsbServer->Device().Stop(); |
|
1150 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
1151 iUsbServer->Host().Stop(); |
|
1152 #endif |
|
1153 |
|
1154 aComplete = EFalse; |
|
1155 iStopMessage = aMessage; |
|
1156 iStopOutstanding = ETrue; |
|
1157 } |
|
1158 else if (state == EUsbServiceStarting) |
|
1159 { |
|
1160 return KErrServerBusy; |
|
1161 } |
|
1162 else if (state == EUsbServiceStopping) |
|
1163 { |
|
1164 aComplete = EFalse; |
|
1165 iStopMessage = aMessage; |
|
1166 iStopOutstanding = ETrue; |
|
1167 } |
|
1168 |
|
1169 return KErrNone; |
|
1170 |
|
1171 #else |
|
1172 // pretend that the server is in Started state |
|
1173 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
1174 iUsbServer->Host().Stop(); |
|
1175 #endif |
|
1176 aMessage.IsNull(); |
|
1177 aComplete = ETrue; |
|
1178 iStopOutstanding = EFalse; |
|
1179 return KErrNone; |
|
1180 #endif |
|
1181 } |
|
1182 |
|
1183 /** |
|
1184 * Cancels the interest to the outstanding request. The acutal request itself |
|
1185 * is not cancelled. |
|
1186 * |
|
1187 * @internalComponent |
|
1188 * @param aMessage Message received from the client |
|
1189 * @return KErrCancel |
|
1190 */ |
|
1191 TInt CUsbSession::CancelInterest(const RMessage2& aMessage) |
|
1192 { |
|
1193 LOG_FUNC |
|
1194 |
|
1195 if (!iPersonalityCfged) |
|
1196 { |
|
1197 return KErrNotSupported; |
|
1198 } |
|
1199 |
|
1200 TUsbMessages toBeCancelledMsg = static_cast<TUsbMessages>(aMessage.Int0()); |
|
1201 if (toBeCancelledMsg == EUsbStart || toBeCancelledMsg == EUsbTryStart) |
|
1202 { |
|
1203 if (iStartOutstanding) |
|
1204 { |
|
1205 iStartMessage.Complete(KErrNone); |
|
1206 iStartOutstanding = EFalse; |
|
1207 } |
|
1208 } |
|
1209 else if (toBeCancelledMsg == EUsbStop || toBeCancelledMsg == EUsbTryStop) |
|
1210 { |
|
1211 if (iStopOutstanding) |
|
1212 { |
|
1213 iStopMessage.Complete(KErrNone); |
|
1214 iStopOutstanding = EFalse; |
|
1215 } |
|
1216 } |
|
1217 |
|
1218 return KErrCancel; |
|
1219 } |
|
1220 |
|
1221 /** |
|
1222 * Gets the current personality id. |
|
1223 * |
|
1224 * @internalComponent |
|
1225 * @param aMessage Message received from the client |
|
1226 * @return Any error that occurred or KErrNone |
|
1227 */ |
|
1228 TInt CUsbSession::GetCurrentPersonalityId(const RMessage2& aMessage) |
|
1229 { |
|
1230 LOG_FUNC |
|
1231 |
|
1232 if (!iPersonalityCfged) |
|
1233 { |
|
1234 return KErrNotSupported; |
|
1235 } |
|
1236 |
|
1237 TInt currentPersonalityId = iUsbServer->Device().CurrentPersonalityId(); |
|
1238 LOGTEXT2(_L8("\tcurrentPersonalityId = %d"), currentPersonalityId); |
|
1239 TPckgC<TInt> pckg(currentPersonalityId); |
|
1240 return aMessage.Write(0, pckg); |
|
1241 } |
|
1242 |
|
1243 /** |
|
1244 * Gets supported classes. |
|
1245 * |
|
1246 * @internalComponent |
|
1247 * @param aMessage Message received from the client |
|
1248 * @return KerrTooBig if supported class > KUsbMaxSupportedClasses; |
|
1249 * KErrNotSupported if personality is not configured |
|
1250 * return code from RMessage2.Write() |
|
1251 */ |
|
1252 TInt CUsbSession::GetSupportedClasses(const RMessage2& aMessage) |
|
1253 { |
|
1254 LOG_FUNC |
|
1255 |
|
1256 if (!iPersonalityCfged) |
|
1257 { |
|
1258 return KErrNotSupported; |
|
1259 } |
|
1260 |
|
1261 // +1 for the size of actual class uid count |
|
1262 TInt32 classUids[KUsbMaxSupportedClasses + 1]; |
|
1263 classUids[0] = 0; // initializes class uids count to zero |
|
1264 // Gets all class uids for the given personality |
|
1265 const RPointerArray<CPersonality>& personalities = iUsbServer->Device().Personalities(); |
|
1266 TInt personalityCount = personalities.Count(); |
|
1267 for (TInt i = 0; i < personalityCount; i++) |
|
1268 { |
|
1269 __ASSERT_ALWAYS(personalities[i] != NULL, _USB_PANIC(KUsbSvrPncCat, ENullPersonalityPointer)); |
|
1270 if (aMessage.Int0() == personalities[i]->PersonalityId()) |
|
1271 { |
|
1272 classUids[0] = personalities[i]->SupportedClasses().Count(); |
|
1273 for (TInt j = 1; j <= classUids[0]; j++) |
|
1274 { |
|
1275 if (j < KUsbMaxSupportedClasses + 1) |
|
1276 { |
|
1277 classUids[j] = personalities[i]->SupportedClasses()[j - 1].iUid; |
|
1278 LOGTEXT3(_L8("\tclassUids[%d] = %d"), j, classUids[j]); |
|
1279 } |
|
1280 else |
|
1281 { |
|
1282 return KErrTooBig; |
|
1283 } |
|
1284 } |
|
1285 break; |
|
1286 } |
|
1287 } |
|
1288 |
|
1289 if (classUids[0] == 0) |
|
1290 { |
|
1291 // No supported classes are found |
|
1292 return KErrNotSupported; |
|
1293 } |
|
1294 |
|
1295 TInt ret; |
|
1296 HBufC8* buf = NULL; |
|
1297 TRAP(ret, buf = HBufC8::NewL((classUids[0] + 1)*sizeof(TInt32))); |
|
1298 if (ret == KErrNone) |
|
1299 { |
|
1300 TPtr8 ptr8 = buf->Des(); |
|
1301 ptr8.Copy(reinterpret_cast<TUint8*>(classUids), (classUids[0] + 1)*sizeof(TInt32)); |
|
1302 ret = aMessage.Write(1, ptr8); |
|
1303 } |
|
1304 |
|
1305 delete buf; |
|
1306 return ret; |
|
1307 } |
|
1308 |
|
1309 /** |
|
1310 * Gets all personality ids. |
|
1311 * |
|
1312 * @internalComponent |
|
1313 * @param aMessage Message received from the client |
|
1314 * @return Any error that occurred or KErrNone |
|
1315 */ |
|
1316 TInt CUsbSession::GetPersonalityIds(const RMessage2& aMessage) |
|
1317 { |
|
1318 LOG_FUNC |
|
1319 |
|
1320 if (!iPersonalityCfged) |
|
1321 { |
|
1322 return KErrNotSupported; |
|
1323 } |
|
1324 |
|
1325 // +1 for the size of actual personality id count |
|
1326 TInt personalityIds[KUsbMaxSupportedPersonalities + 1]; |
|
1327 |
|
1328 const RPointerArray<CPersonality>& personalities = iUsbServer->Device().Personalities(); |
|
1329 TInt personalityCount = personalities.Count(); |
|
1330 for (TInt i = 0; i < personalityCount; ++i) |
|
1331 { |
|
1332 __ASSERT_ALWAYS(personalities[i] != NULL, _USB_PANIC(KUsbSvrPncCat, ENullPersonalityPointer)); |
|
1333 personalityIds[i + 1] = personalities[i]->PersonalityId(); |
|
1334 } |
|
1335 personalityIds[0] = personalityCount; |
|
1336 |
|
1337 TInt ret; |
|
1338 HBufC8* buf = NULL; |
|
1339 TRAP(ret, buf = HBufC8::NewL((personalityCount + 1)*sizeof(TInt))); |
|
1340 if (ret == KErrNone) |
|
1341 { |
|
1342 TPtr8 ptr8 = buf->Des(); |
|
1343 ptr8.Copy(reinterpret_cast<TUint8*>(personalityIds), (personalityCount + 1)*sizeof(TInt)); |
|
1344 ret = aMessage.Write(0, ptr8); |
|
1345 } |
|
1346 |
|
1347 delete buf; |
|
1348 return ret; |
|
1349 } |
|
1350 |
|
1351 /** |
|
1352 * Gets personality description |
|
1353 * |
|
1354 * @internalComponent |
|
1355 * @param aMessage Message received from the client |
|
1356 * @return Any error that occurred or KErrNone |
|
1357 */ |
|
1358 TInt CUsbSession::GetDescription(const RMessage2& aMessage) |
|
1359 { |
|
1360 LOG_FUNC |
|
1361 |
|
1362 if (!iPersonalityCfged) |
|
1363 { |
|
1364 return KErrNotSupported; |
|
1365 } |
|
1366 |
|
1367 TInt personalityId = aMessage.Int0(); |
|
1368 const CPersonality* personality = iUsbServer->Device().GetPersonality(personalityId); |
|
1369 if (personality) |
|
1370 { |
|
1371 return aMessage.Write(1, *(personality->Description())); |
|
1372 } |
|
1373 |
|
1374 // We should never reach here |
|
1375 return KErrNotSupported; |
|
1376 } |
|
1377 |
|
1378 /** |
|
1379 * Gets personality detailed description |
|
1380 * |
|
1381 * @internalComponent |
|
1382 * @param aMessage Message received from the client |
|
1383 * @return Any error that occurred or KErrNone |
|
1384 */ |
|
1385 TInt CUsbSession::GetDetailedDescription(const RMessage2& aMessage) |
|
1386 { |
|
1387 LOG_FUNC |
|
1388 |
|
1389 if (!iPersonalityCfged) |
|
1390 { |
|
1391 return KErrNotSupported; |
|
1392 } |
|
1393 |
|
1394 TInt personalityId = aMessage.Int0(); |
|
1395 const CPersonality* personality = iUsbServer->Device().GetPersonality(personalityId); |
|
1396 if (personality) |
|
1397 { |
|
1398 if(personality->Version() < EUsbManagerResourceVersionTwo) |
|
1399 { |
|
1400 return KErrNotFound; |
|
1401 } |
|
1402 return aMessage.Write(1, *(personality->DetailedDescription())); |
|
1403 } |
|
1404 |
|
1405 // We should never reach here |
|
1406 return KErrNotSupported; |
|
1407 } |
|
1408 |
|
1409 /** |
|
1410 * Gets personality property |
|
1411 * |
|
1412 * @internalComponent |
|
1413 * @param aMessage Message received from the client |
|
1414 * @return Any error that occurred or KErrNone |
|
1415 */ |
|
1416 TInt CUsbSession::GetPersonalityProperty(const RMessage2& aMessage) |
|
1417 { |
|
1418 LOG_FUNC |
|
1419 |
|
1420 if (!iPersonalityCfged) |
|
1421 { |
|
1422 return KErrNotSupported; |
|
1423 } |
|
1424 |
|
1425 TInt personalityId = aMessage.Int0(); |
|
1426 const CPersonality* personality = iUsbServer->Device().GetPersonality(personalityId); |
|
1427 if (personality) |
|
1428 { |
|
1429 if(personality->Version() < EUsbManagerResourceVersionThree) |
|
1430 { |
|
1431 return KErrNotFound; |
|
1432 } |
|
1433 TPckg<TUint32> pckg(personality->Property()); |
|
1434 return aMessage.Write(1, pckg); |
|
1435 } |
|
1436 |
|
1437 return KErrNotSupported; |
|
1438 } |
|
1439 |
|
1440 /** |
|
1441 * Checks if a given class is supported by a personality. |
|
1442 * |
|
1443 * @internalComponent |
|
1444 * @param aMessage Message received from the client |
|
1445 * @return Any error that occurred or KErrNone |
|
1446 */ |
|
1447 TInt CUsbSession::ClassSupported(const RMessage2& aMessage) |
|
1448 { |
|
1449 LOG_FUNC |
|
1450 |
|
1451 if (!iPersonalityCfged) |
|
1452 { |
|
1453 return KErrNotSupported; |
|
1454 } |
|
1455 |
|
1456 TBool isSupported = EFalse; |
|
1457 TInt personalityId = aMessage.Int0(); |
|
1458 TUid classUid = TUid::Uid(aMessage.Int1()); |
|
1459 const CPersonality* personality = iUsbServer->Device().GetPersonality(personalityId); |
|
1460 if (personality) |
|
1461 { |
|
1462 isSupported = (personality->ClassSupported(classUid) != KErrNotFound); |
|
1463 TPckg<TBool> pkg2(isSupported); |
|
1464 return aMessage.Write(2, pkg2); |
|
1465 } |
|
1466 |
|
1467 // We should never reach here |
|
1468 return KErrNotSupported; |
|
1469 } |
|
1470 |
|
1471 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
1472 /** |
|
1473 * Sets or resets the control mode flag for this session. |
|
1474 * |
|
1475 * @internalComponent |
|
1476 * @param aMessage Message received from the client |
|
1477 * @return Any error that occurred or KErrNone |
|
1478 */ |
|
1479 TInt CUsbSession::SetCtlSessionMode(const RMessage2& aMessage) |
|
1480 { |
|
1481 LOG_FUNC |
|
1482 |
|
1483 TInt ret = KErrNone; |
|
1484 |
|
1485 TBool value = (TBool)aMessage.Int0(); |
|
1486 LOGTEXT2(_L8("\tSetting = %d"), static_cast<TInt>(value)); |
|
1487 |
|
1488 // Verify if this is the same session which set the value before |
|
1489 if ( iCtlSession && (iCtlSession != this) ) |
|
1490 { |
|
1491 ret = KErrAccessDenied; |
|
1492 } |
|
1493 else |
|
1494 { |
|
1495 iSessionCtlMode = value; |
|
1496 |
|
1497 // Set control session pointer if the flag is set |
|
1498 if ( iSessionCtlMode ) |
|
1499 { |
|
1500 iCtlSession = this; |
|
1501 } |
|
1502 else |
|
1503 { |
|
1504 iCtlSession = NULL; |
|
1505 } |
|
1506 } |
|
1507 |
|
1508 return ret; |
|
1509 } |
|
1510 |
|
1511 /** |
|
1512 * Asserts a request to drive VBus. |
|
1513 * |
|
1514 * @internalComponent |
|
1515 * @return If control mode flag is not set returns KErrAccessDenied |
|
1516 * An error code for all other cases |
|
1517 */ |
|
1518 TInt CUsbSession::BusRequest() |
|
1519 { |
|
1520 LOG_FUNC |
|
1521 |
|
1522 TInt ret = KErrNone; |
|
1523 if ( iSessionCtlMode ) |
|
1524 { |
|
1525 ret = iUsbServer->Otg().BusRequest(); |
|
1526 } |
|
1527 else |
|
1528 { |
|
1529 ret = KErrAccessDenied; |
|
1530 } |
|
1531 |
|
1532 return ret; |
|
1533 } |
|
1534 |
|
1535 /** |
|
1536 * Asserts a request to raise VBUS but assumes this is after B-Device |
|
1537 * has used SRP to make a request to become session Host, so may be able |
|
1538 * to take some short cuts when enumerating the B-Device. |
|
1539 * |
|
1540 * @internalComponent |
|
1541 * @return If control mode flag is not set returns KErrAccessDenied |
|
1542 * Any error that occurred or KErrNone for all other cases |
|
1543 */ |
|
1544 TInt CUsbSession::BusRespondSrp() |
|
1545 { |
|
1546 LOG_FUNC |
|
1547 |
|
1548 TInt ret = KErrNone; |
|
1549 if ( iSessionCtlMode ) |
|
1550 { |
|
1551 ret = iUsbServer->Otg().BusRespondSrp(); |
|
1552 } |
|
1553 else |
|
1554 { |
|
1555 ret = KErrAccessDenied; |
|
1556 } |
|
1557 |
|
1558 return ret; |
|
1559 } |
|
1560 |
|
1561 /** |
|
1562 * Clears a possible VBUS error condition (VBUS inexplicably low after |
|
1563 * having been driven) |
|
1564 * |
|
1565 * @internalComponent |
|
1566 * @return If control mode flag is not set returns KErrAccessDenied |
|
1567 * Any error that occurred or KErrNone for all other cases |
|
1568 */ |
|
1569 TInt CUsbSession::BusClearError() |
|
1570 { |
|
1571 LOG_FUNC |
|
1572 |
|
1573 TInt ret = KErrNone; |
|
1574 if ( iSessionCtlMode ) |
|
1575 { |
|
1576 ret = iUsbServer->Otg().BusClearError(); |
|
1577 } |
|
1578 else |
|
1579 { |
|
1580 ret = KErrAccessDenied; |
|
1581 } |
|
1582 |
|
1583 return ret; |
|
1584 } |
|
1585 |
|
1586 /** |
|
1587 * Drops VBus. |
|
1588 * |
|
1589 * @internalComponent |
|
1590 * @return If control mode flag is not set returns KErrAccessDenied |
|
1591 * Any error that occurred or KErrNone for all other cases |
|
1592 */ |
|
1593 TInt CUsbSession::BusDrop() |
|
1594 { |
|
1595 LOG_FUNC |
|
1596 |
|
1597 TInt ret = KErrNone; |
|
1598 if ( iSessionCtlMode ) |
|
1599 { |
|
1600 ret = iUsbServer->Otg().BusDrop(); |
|
1601 } |
|
1602 else |
|
1603 { |
|
1604 ret = KErrAccessDenied; |
|
1605 } |
|
1606 |
|
1607 return ret; |
|
1608 } |
|
1609 |
|
1610 /** |
|
1611 * Enables loading of Function Drivers. |
|
1612 * |
|
1613 * @internalComponent |
|
1614 * @return If control mode flag is not set returns KErrAccessDenied |
|
1615 * Any error that occurred or KErrNone for all other cases |
|
1616 */ |
|
1617 TInt CUsbSession::EnableFunctionDriverLoading() |
|
1618 { |
|
1619 LOG_FUNC |
|
1620 |
|
1621 TInt ret = KErrNone; |
|
1622 if ( iSessionCtlMode ) |
|
1623 { |
|
1624 ret = iUsbServer->Host().EnableDriverLoading(); |
|
1625 } |
|
1626 else |
|
1627 { |
|
1628 ret = KErrAccessDenied; |
|
1629 } |
|
1630 |
|
1631 return ret; |
|
1632 } |
|
1633 |
|
1634 /** |
|
1635 * Disables loading of Function Drivers. |
|
1636 * |
|
1637 * @internalComponent |
|
1638 * @return If control mode flag is not set returns KErrAccessDenied |
|
1639 * KErrNone for all other cases |
|
1640 */ |
|
1641 TInt CUsbSession::DisableFunctionDriverLoading() |
|
1642 { |
|
1643 LOG_FUNC |
|
1644 |
|
1645 TInt ret = KErrNone; |
|
1646 if ( iSessionCtlMode ) |
|
1647 { |
|
1648 iUsbServer->Host().DisableDriverLoading(); |
|
1649 } |
|
1650 else |
|
1651 { |
|
1652 ret = KErrAccessDenied; |
|
1653 } |
|
1654 |
|
1655 return ret; |
|
1656 } |
|
1657 |
|
1658 /** |
|
1659 * Requests an array of language identifiers supported by connected device. |
|
1660 * |
|
1661 * @internalComponent |
|
1662 * @param aMessage Message received from the client |
|
1663 * @return Any error that occurred or KErrNone |
|
1664 */ |
|
1665 TInt CUsbSession::GetSupportedLanguages(const RMessage2& aMessage) |
|
1666 { |
|
1667 LOG_FUNC |
|
1668 TRAPD(err, GetSupportedLanguagesL(aMessage)); |
|
1669 return err; |
|
1670 } |
|
1671 |
|
1672 /** |
|
1673 * Requests an array of language identifiers supported by connected device. |
|
1674 * |
|
1675 * @internalComponent |
|
1676 * @param aMessage Message received from the client |
|
1677 * @return Any error that occurred or KErrNone |
|
1678 */ |
|
1679 TInt CUsbSession::GetSupportedLanguagesL(const RMessage2& aMessage) |
|
1680 { |
|
1681 LOG_FUNC |
|
1682 |
|
1683 |
|
1684 const TUint deviceId = aMessage.Int0(); |
|
1685 LOGTEXT2(_L8("\tdeviceId = %d"), deviceId); |
|
1686 |
|
1687 RArray<TUint> langIds; |
|
1688 CleanupClosePushL(langIds); |
|
1689 TInt ret = iUsbServer->Host().GetSupportedLanguages(deviceId,langIds); |
|
1690 |
|
1691 if (ret == KErrNone) |
|
1692 { |
|
1693 const TUint count = langIds.Count(); |
|
1694 LOGTEXT2(_L8("\tcount = %d"), count); |
|
1695 |
|
1696 // Set error code if there is no languages or there are too many |
|
1697 if ( count == 0 ) |
|
1698 { |
|
1699 ret = KErrNotSupported; |
|
1700 } |
|
1701 else if ( count > KUsbMaxSupportedLanguageIds ) |
|
1702 { |
|
1703 ret = KErrTooBig; |
|
1704 } |
|
1705 |
|
1706 if ( ret == KErrNone ) |
|
1707 { |
|
1708 // Create a buffer to keep an array size and all received language Ids |
|
1709 RBuf8 buf; |
|
1710 buf.CreateL((count + 1) * sizeof(TUint)); |
|
1711 CleanupClosePushL(buf); |
|
1712 |
|
1713 // Save the length of the array |
|
1714 buf.Append((TUint8*)&count, sizeof(TUint)); |
|
1715 |
|
1716 // Save all received language Ids |
|
1717 for ( TUint ii = 0 ; ii < count; ++ii ) |
|
1718 { |
|
1719 buf.Append((TUint8*)&(langIds[ii]), sizeof(TUint)); |
|
1720 LOGTEXT3(_L8("Append langID[%d] = %d"),ii,langIds[ii]); |
|
1721 } |
|
1722 |
|
1723 // Write back to the client. |
|
1724 ret = aMessage.Write(1, buf); |
|
1725 CleanupStack::PopAndDestroy(&buf); |
|
1726 } |
|
1727 } |
|
1728 |
|
1729 CleanupStack::PopAndDestroy(); |
|
1730 |
|
1731 return ret; |
|
1732 } |
|
1733 |
|
1734 /** |
|
1735 * Requests a manufacturer string descriptor of connected device. |
|
1736 * |
|
1737 * @internalComponent |
|
1738 * @param aMessage Message received from the client |
|
1739 * @return Any error that occurred or KErrNone |
|
1740 */ |
|
1741 TInt CUsbSession::GetManufacturerStringDescriptor(const RMessage2& aMessage) |
|
1742 { |
|
1743 LOG_FUNC |
|
1744 |
|
1745 const TUint deviceId = aMessage.Int0(); |
|
1746 const TUint langId = aMessage.Int1(); |
|
1747 LOGTEXT3(_L8("\tdeviceId = %d, langId = %d"), deviceId, langId); |
|
1748 |
|
1749 TName string; |
|
1750 TInt ret = iUsbServer->Host().GetManufacturerStringDescriptor(deviceId,langId,string); |
|
1751 if (ret == KErrNone) |
|
1752 { |
|
1753 LOGTEXT2(_L("\tstring = \"%S\""), &string); |
|
1754 ret = aMessage.Write(2, string); |
|
1755 } |
|
1756 |
|
1757 return ret; |
|
1758 } |
|
1759 |
|
1760 /** |
|
1761 * Requests a product string descriptor of connected device. |
|
1762 * |
|
1763 * @internalComponent |
|
1764 * @param aMessage Message received from the client |
|
1765 * @return Any error that occurred or KErrNone |
|
1766 */ |
|
1767 TInt CUsbSession::GetProductStringDescriptor(const RMessage2& aMessage) |
|
1768 { |
|
1769 LOG_FUNC |
|
1770 |
|
1771 const TUint deviceId = aMessage.Int0(); |
|
1772 const TUint langId = aMessage.Int1(); |
|
1773 LOGTEXT3(_L8("\tdeviceId = %d, langId = %d"), deviceId, langId); |
|
1774 |
|
1775 TName string; |
|
1776 TInt ret = iUsbServer->Host().GetProductStringDescriptor(deviceId,langId,string); |
|
1777 if (ret == KErrNone) |
|
1778 { |
|
1779 LOGTEXT2(_L("\tstring = \"%S\""), &string); |
|
1780 ret = aMessage.Write(2, string); |
|
1781 } |
|
1782 |
|
1783 return ret; |
|
1784 } |
|
1785 |
|
1786 /** |
|
1787 * Requests a OTG descriptor of connected device. |
|
1788 * |
|
1789 * @internalComponent |
|
1790 * @param aMessage Message received from the client |
|
1791 * @return Any error that occurred or KErrNone |
|
1792 */ |
|
1793 TInt CUsbSession::GetOtgDescriptor(const RMessage2& aMessage) |
|
1794 { |
|
1795 LOG_FUNC |
|
1796 |
|
1797 const TUint deviceId = aMessage.Int0(); |
|
1798 LOGTEXT2(_L8("\tdeviceId = %d"), deviceId); |
|
1799 |
|
1800 TOtgDescriptor otgDescriptor; |
|
1801 TInt ret = iUsbServer->Host().GetOtgDescriptor(deviceId, otgDescriptor); |
|
1802 if (ret == KErrNone) |
|
1803 { |
|
1804 TPckg<TOtgDescriptor> buf(otgDescriptor); |
|
1805 ret = aMessage.Write(1, buf); |
|
1806 } |
|
1807 |
|
1808 return ret; |
|
1809 } |
|
1810 |
|
1811 /** |
|
1812 * Client request to observe the host (for state changes). |
|
1813 * Asks the host to register the session as an observer. |
|
1814 * Assures initialisation/dequeueing of Event queue. |
|
1815 * No events are queued until the first observer is registered |
|
1816 * |
|
1817 * @internalComponent |
|
1818 * @param aMessage Message received from the client |
|
1819 * @param aComplete set to true to complete the request |
|
1820 * |
|
1821 * @return Any error that occurred or KErrNone |
|
1822 */ |
|
1823 TInt CUsbSession::RegisterHostObserver(const RMessage2& aMessage, TBool& aComplete) |
|
1824 { |
|
1825 LOG_FUNC |
|
1826 |
|
1827 if (iHostEventObserverOutstanding) |
|
1828 { |
|
1829 return KErrInUse; |
|
1830 } |
|
1831 |
|
1832 iHostEventObserverMessage = aMessage; |
|
1833 iHostEventObserverOutstanding = ETrue; |
|
1834 aComplete = EFalse; |
|
1835 |
|
1836 if (iHostEventObserverQueueEvents == EFalse) |
|
1837 { |
|
1838 // This is the first observer after c'tor or DeregisterObserver(), |
|
1839 // so zap the device event queue. |
|
1840 LOGTEXT(_L8(" Reset OTG Host State Queue")); |
|
1841 iHostEventQueueHead = 0; |
|
1842 iHostEventQueueTail = 0; |
|
1843 iHostEventObserverQueueEvents = ETrue; |
|
1844 } |
|
1845 else if (iHostEventQueueHead != iHostEventQueueTail) |
|
1846 { |
|
1847 // event(s) queued, we can de-queue one now |
|
1848 UsbHostEventDequeue(); |
|
1849 } |
|
1850 |
|
1851 return KErrNone; |
|
1852 } |
|
1853 |
|
1854 /** |
|
1855 * Deregister the client as an observer of host state changes. |
|
1856 * |
|
1857 * @internalComponent |
|
1858 * @return Always KErrNone |
|
1859 */ |
|
1860 TInt CUsbSession::DeRegisterHostObserver() |
|
1861 { |
|
1862 LOG_FUNC |
|
1863 |
|
1864 |
|
1865 if (!iHostEventObserverOutstanding) |
|
1866 { |
|
1867 return KErrNone; |
|
1868 } |
|
1869 |
|
1870 iHostEventObserverOutstanding = EFalse; |
|
1871 iHostEventObserverMessage.Complete(KErrCancel); |
|
1872 |
|
1873 // client doesn't need events queuing any more |
|
1874 iHostEventObserverQueueEvents = EFalse; |
|
1875 |
|
1876 return KErrNone; |
|
1877 } |
|
1878 |
|
1879 /** |
|
1880 * Client request to observe both OTG and HOST (for events and errors). |
|
1881 * Asks HOST and OTGDI components to register the session as an observer. |
|
1882 * Assures initialisation/dequeueing of Event queue. |
|
1883 * No events are queued until the first observer is registered |
|
1884 * |
|
1885 * @internalComponent |
|
1886 * @param aMessage Message received from the client |
|
1887 * @param aComplete set to true to complete the request |
|
1888 * |
|
1889 * @return Any error that occurred or KErrNone |
|
1890 */ |
|
1891 TInt CUsbSession::RegisterMsgObserver(const RMessage2& aMessage, TBool& aComplete) |
|
1892 { |
|
1893 LOG_FUNC |
|
1894 |
|
1895 if (iMsgObserverOutstanding) |
|
1896 { |
|
1897 return KErrInUse; |
|
1898 } |
|
1899 |
|
1900 iMsgObserverMessage = aMessage; |
|
1901 iMsgObserverOutstanding = ETrue; |
|
1902 aComplete = EFalse; |
|
1903 |
|
1904 if (iMsgObserverQueueEvents == EFalse) |
|
1905 { |
|
1906 // This is the first observer after c'tor or DeregisterObserver(), |
|
1907 // so zap the device event queue. |
|
1908 LOGTEXT(_L8(" Reset OTG Message Queue")); |
|
1909 iMsgQueueHead = 0; |
|
1910 iMsgQueueTail = 0; |
|
1911 iMsgObserverQueueEvents = ETrue; |
|
1912 } |
|
1913 else if (iMsgQueueHead != iMsgQueueTail) |
|
1914 { |
|
1915 // event(s) queued, we can de-queue one now |
|
1916 UsbMsgDequeue(); |
|
1917 } |
|
1918 |
|
1919 return KErrNone; |
|
1920 } |
|
1921 |
|
1922 /** |
|
1923 * Deregister the client as an observer of OTG/HOST events and errors. |
|
1924 * |
|
1925 * @internalComponent |
|
1926 * @return Always KErrNone |
|
1927 */ |
|
1928 TInt CUsbSession::DeRegisterMsgObserver() |
|
1929 { |
|
1930 LOG_FUNC |
|
1931 |
|
1932 if (!iMsgObserverOutstanding) |
|
1933 { |
|
1934 return KErrNone; |
|
1935 } |
|
1936 |
|
1937 iMsgObserverOutstanding = EFalse; |
|
1938 iMsgObserverMessage.Complete(KErrCancel); |
|
1939 |
|
1940 // client doesn't need events queuing any more |
|
1941 iMsgObserverQueueEvents = EFalse; |
|
1942 |
|
1943 return KErrNone; |
|
1944 } |
|
1945 |
|
1946 |
|
1947 |
|
1948 /** |
|
1949 * Called by CUsbOtg or CUsbHost when the USB OTG/HOST message has arrived |
|
1950 * |
|
1951 * @internalComponent |
|
1952 * @param aMessage The new OTG Message |
|
1953 */ |
|
1954 void CUsbSession::UsbOtgHostMessage(TInt aMessage) |
|
1955 { |
|
1956 LOG_FUNC |
|
1957 |
|
1958 // can we bypass the queue? |
|
1959 if ((iMsgObserverOutstanding) && (iMsgQueueHead == iMsgQueueTail)) |
|
1960 { |
|
1961 TPckg<TInt> pckg(aMessage); |
|
1962 |
|
1963 iNotifiedMsg = aMessage; |
|
1964 |
|
1965 iMsgObserverOutstanding = EFalse; |
|
1966 const TInt err = iMsgObserverMessage.Write(0, pckg); |
|
1967 iMsgObserverMessage.Complete(err); |
|
1968 } |
|
1969 else if (iMsgObserverQueueEvents) |
|
1970 { |
|
1971 // add event to head of queue |
|
1972 iMsgQueue[iMsgQueueHead] = aMessage; |
|
1973 iMsgQueueHead = (iMsgQueueHead + 1) % KOtgHostMessageQueueSize; |
|
1974 LOGTEXT3(_L8("+++ CUsbSession::UsbOtgMessage() addqueue (%d, %d)"), iMsgQueueHead, |
|
1975 iMsgQueueTail); |
|
1976 |
|
1977 // UsbMsgDequeueEvent() will read from queue when RegisterMsgObserver() |
|
1978 // is next called. |
|
1979 } |
|
1980 } |
|
1981 |
|
1982 /** |
|
1983 * Called by CUsbHost when it state change. CUsbSession is an observer of |
|
1984 * the device. If the client has an Observer outstanding then complete it, |
|
1985 * otherwise put it in a circular queue. |
|
1986 * |
|
1987 * @internalComponent |
|
1988 * @param aDevInfo The information about the device being attached or detached |
|
1989 * along with the status of Function Driver loading |
|
1990 */ |
|
1991 void CUsbSession::UsbHostEvent(TDeviceEventInformation& aDevInfo) |
|
1992 { |
|
1993 LOG_FUNC |
|
1994 |
|
1995 // can we bypass the queue? |
|
1996 if ((iHostEventObserverOutstanding) && (iHostEventQueueHead == iHostEventQueueTail)) |
|
1997 { |
|
1998 iNotifiedHostState = aDevInfo; |
|
1999 iHostEventObserverOutstanding = EFalse; |
|
2000 |
|
2001 LOGTEXT(_L8("CUsbSession::UsbHostEvent() detected outstanding request")); |
|
2002 |
|
2003 TPckg<TDeviceEventInformation> info(aDevInfo); |
|
2004 const TInt err = iHostEventObserverMessage.Write(0, info); |
|
2005 iHostEventObserverMessage.Complete(err); |
|
2006 LOGTEXT2(_L8("CUsbSession::UsbHostEvent() detects outstanding request: request is compeleted with %d"), err); |
|
2007 } |
|
2008 else if (iHostEventObserverQueueEvents) |
|
2009 { |
|
2010 // add dev info to head of queue |
|
2011 iHostStateQueue[iHostEventQueueHead] = aDevInfo; |
|
2012 iHostEventQueueHead = (iHostEventQueueHead + 1) % KDeviceStatesQueueSize; |
|
2013 LOGTEXT3(_L8("+++ CUsbSession::UsbHostEvent() addqueue (%d, %d)"), iHostEventQueueHead, |
|
2014 iHostEventQueueTail); |
|
2015 |
|
2016 // UsbHostStateDequeueEvent() will read from queue when RegisterHostObserver() |
|
2017 // is next called. |
|
2018 } |
|
2019 } |
|
2020 |
|
2021 /** |
|
2022 * Dequeues an event and completes the observer's request with it. |
|
2023 */ |
|
2024 void CUsbSession::UsbMsgDequeue() |
|
2025 { |
|
2026 LOG_FUNC |
|
2027 |
|
2028 // Work our way through the queue, until we reach the end |
|
2029 // OR we find an event the current observer wants. |
|
2030 if ((iMsgObserverOutstanding) && (iMsgQueueHead != iMsgQueueTail)) |
|
2031 { |
|
2032 TInt newMsg = iMsgQueue[iMsgQueueTail]; |
|
2033 |
|
2034 // advance tail towards the head |
|
2035 iMsgQueueTail = (iMsgQueueTail + 1) % KOtgHostMessageQueueSize; |
|
2036 |
|
2037 TPckg<TUint32> pckg(newMsg); |
|
2038 iNotifiedMsg = newMsg; |
|
2039 |
|
2040 LOGTEXT3(_L8(">>> dequeued event #%d (0x%x)"), iMsgQueueTail, newMsg); |
|
2041 |
|
2042 iMsgObserverOutstanding = EFalse; |
|
2043 const TInt err = iMsgObserverMessage.Write(0, pckg); |
|
2044 iMsgObserverMessage.Complete(err); |
|
2045 } |
|
2046 } |
|
2047 |
|
2048 /** |
|
2049 * Dequeues an event and completes the observer's request with it. |
|
2050 */ |
|
2051 void CUsbSession::UsbHostEventDequeue() |
|
2052 { |
|
2053 LOG_FUNC |
|
2054 |
|
2055 // Work our way through the queue, until we reach the end |
|
2056 // OR we find an event the current observer wants. |
|
2057 if ((iHostEventObserverOutstanding) && (iHostEventQueueHead != iHostEventQueueTail)) |
|
2058 { |
|
2059 // inform the observer of state changes they are interested in AND |
|
2060 // if the cable is pulled out (EUsbDeviceStateUndefined) |
|
2061 TDeviceEventInformation newDevInfo = iHostStateQueue[iHostEventQueueTail]; |
|
2062 iNotifiedHostState = newDevInfo; |
|
2063 |
|
2064 // advance tail towards the head |
|
2065 iHostEventQueueTail = (iHostEventQueueTail + 1) % KDeviceStatesQueueSize; |
|
2066 |
|
2067 LOGTEXT3(_L8(">>> CUsbSession::UsbHostStateDequeueEvent() dequeued event #%d (0x%x)"), iHostEventQueueTail, newDevInfo.iEventType); |
|
2068 |
|
2069 TPckg<TDeviceEventInformation> info(newDevInfo); |
|
2070 iHostEventObserverOutstanding = EFalse; |
|
2071 const TInt err = iHostEventObserverMessage.Write(0, info); |
|
2072 iHostEventObserverMessage.Complete(err); |
|
2073 |
|
2074 LOGTEXT2(_L8("CUsbSession::UsbHostStateDequeueEvent() detects outstanding request: request is compeleted with %d"), err); |
|
2075 } |
|
2076 } |
|
2077 |
|
2078 TInt CUsbSession::RequestSession() |
|
2079 { |
|
2080 return DoRequestSession(); |
|
2081 } |
|
2082 |
|
2083 TInt CUsbSession::DoRequestSession() |
|
2084 { |
|
2085 if ( iCtlSession ) |
|
2086 { |
|
2087 if ( iCtlSession == this ) |
|
2088 { |
|
2089 if (iMsgObserverQueueEvents) |
|
2090 { |
|
2091 UsbOtgHostMessage(KUsbMessageRequestSession); |
|
2092 return KErrNone; |
|
2093 } |
|
2094 else |
|
2095 { |
|
2096 return KErrNotFound; |
|
2097 } |
|
2098 } |
|
2099 else |
|
2100 { |
|
2101 return iCtlSession->DoRequestSession(); |
|
2102 } |
|
2103 } |
|
2104 return KErrNotFound; |
|
2105 } |
|
2106 |
|
2107 #endif // SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
2108 |