|
1 // Copyright (c) 1997-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 "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 |
|
21 |
|
22 #include <obexusbtransportinfo.h> |
|
23 #include "usbconn.h" |
|
24 #include <obex/transport/obexconnector.h> |
|
25 #include "logger.h" |
|
26 #include "obexusbfaults.h" |
|
27 |
|
28 #ifdef __FLOG_ACTIVE |
|
29 _LIT8(KLogComponent, "USB"); |
|
30 #endif |
|
31 |
|
32 #ifdef _DEBUG |
|
33 _LIT(KPanicCat, "ObexUsbHandler"); |
|
34 #endif |
|
35 |
|
36 |
|
37 // |
|
38 |
|
39 /** |
|
40 CObexUsbActiveWriter factory function |
|
41 |
|
42 @param aTransport Reference to a CObexUsbTransportController object. Required for a call to the CObexUsbActiveReader |
|
43 @param aOwner Reference to a MObexTransportNotify object |
|
44 @param aUsb Reference to a RDevUsbcClient object |
|
45 @param aInfo Reference to a TObexConnectionInfo object |
|
46 @param aPacketSize The size of packets used on the underlying link, dependent on High Speed mode. |
|
47 @return Ownership of a new CObexUsbActiveWriter. |
|
48 */ |
|
49 CObexUsbActiveWriter* CObexUsbActiveWriter::NewL(MObexTransportNotify& aOwner, RDevUsbcClient& aUsb, |
|
50 TObexConnectionInfo& aInfo, TInt aPacketSize) |
|
51 { |
|
52 CObexUsbActiveWriter* self = new(ELeave) CObexUsbActiveWriter(aOwner, aUsb, aInfo, aPacketSize); |
|
53 CleanupStack::PushL(self); |
|
54 self->BaseConstructL(); |
|
55 CleanupStack::Pop(self); |
|
56 return self; |
|
57 } |
|
58 |
|
59 /** |
|
60 CObexUsbActiveWriter constructor |
|
61 |
|
62 @param aTransport Reference to a CObexUsbTransportController object. Required for a call to the CObexUsbActiveReader |
|
63 @param aOwner Reference to a MObexTransportNotify object |
|
64 @param aUsb Reference to a RDevUsbcClient object |
|
65 @param aInfo Reference to a TObexConnectionInfo object |
|
66 @param aPacketSize The size of packets used on the underlying link, dependent on High Speed mode. |
|
67 */ |
|
68 CObexUsbActiveWriter::CObexUsbActiveWriter(MObexTransportNotify& aOwner, RDevUsbcClient& aUsb, |
|
69 TObexConnectionInfo& aInfo, TInt aPacketSize) |
|
70 : CObexWriterBase(EPriorityHigh, aOwner, aInfo), |
|
71 iUsb(aUsb), iPacketSize(aPacketSize) |
|
72 { |
|
73 } |
|
74 |
|
75 |
|
76 /** |
|
77 CObexUsbActiveWriter destructor. |
|
78 */ |
|
79 CObexUsbActiveWriter::~CObexUsbActiveWriter() |
|
80 { |
|
81 LOG_FUNC |
|
82 |
|
83 Cancel(); |
|
84 } |
|
85 |
|
86 |
|
87 /** |
|
88 Start actual transfer. May be called several times by CObexActiveRW::RunL. |
|
89 Queues a write on USB endpoint. |
|
90 */ |
|
91 void CObexUsbActiveWriter::DoTransfer() |
|
92 { |
|
93 LOG_FUNC |
|
94 LOG1(_L("CObexUsbActiveWriter::DoTransfer [Length=%d]"),iLocation.Length()); |
|
95 |
|
96 iLocation.SetMax(); |
|
97 iUsb.Write(iStatus, KTransmitEndpoint, iLocation, iLocation.Length(), ETrue); |
|
98 SetActive(); |
|
99 } |
|
100 |
|
101 |
|
102 /** |
|
103 Cancels an outstanding write. |
|
104 */ |
|
105 void CObexUsbActiveWriter::DoCancel() |
|
106 { |
|
107 LOG_FUNC |
|
108 |
|
109 //Only cancel the write if there's more than 1 packet left to write. |
|
110 //This restriction is imposed to prevent the SUCCESS response being |
|
111 //cancelled when an ObexServer is handling a disconnect and bringing |
|
112 //the transport down. |
|
113 if(Remaining() > iPacketSize) |
|
114 { |
|
115 iUsb.WriteCancel(KTransmitEndpoint); |
|
116 } |
|
117 } |
|
118 |
|
119 |
|
120 // |
|
121 |
|
122 /** |
|
123 CObexUsbActiveReader factory function |
|
124 |
|
125 @param aOwner Reference to a MObexTransportNotify object |
|
126 @param aUsb Reference to a RDevUsbcClient object |
|
127 @param aInfo Reference to a TObexConnectionInfo object |
|
128 @return Ownership of a new CObexUsbActiveWriter. |
|
129 */ |
|
130 CObexUsbActiveReader* CObexUsbActiveReader::NewL(MObexTransportNotify& aOwner, RDevUsbcClient& aUsb, |
|
131 TObexConnectionInfo& aInfo) |
|
132 { |
|
133 CObexUsbActiveReader* self = new(ELeave) CObexUsbActiveReader(aOwner, aUsb, aInfo); |
|
134 CleanupStack::PushL(self); |
|
135 self->BaseConstructL(); |
|
136 CleanupStack::Pop(self); |
|
137 return self; |
|
138 } |
|
139 |
|
140 /** |
|
141 CObexUsbActiveReader constructor |
|
142 |
|
143 @param aOwner Reference to a MObexTransportNotify object |
|
144 @param aUsb Reference to a RDevUsbcClient object |
|
145 @param aInfo Reference to a TObexConnectionInfo object |
|
146 */ |
|
147 CObexUsbActiveReader::CObexUsbActiveReader(MObexTransportNotify& aOwner, RDevUsbcClient& aUsb, |
|
148 TObexConnectionInfo& aInfo) |
|
149 : CObexReaderBase(EPriorityStandard, aOwner, aInfo), iUsb(aUsb) |
|
150 { |
|
151 } |
|
152 |
|
153 |
|
154 /** |
|
155 CObexUsbActiveReader destructor. |
|
156 */ |
|
157 CObexUsbActiveReader::~CObexUsbActiveReader() |
|
158 { |
|
159 LOG_FUNC |
|
160 |
|
161 Cancel(); |
|
162 } |
|
163 |
|
164 |
|
165 /** |
|
166 Start actual transfer. May be called several times by CObexActiveRW::RunL. |
|
167 Queues a read on USB endpoint. |
|
168 */ |
|
169 void CObexUsbActiveReader::DoTransfer() |
|
170 { |
|
171 LOG_FUNC |
|
172 LOG1(_L("CObexUsbActiveReader::DoTransfer [maxLength=%d]"),iLocation.MaxLength()); |
|
173 |
|
174 iUsb.ReadUntilShort(iStatus, KReceiveEndpoint, iLocation); |
|
175 SetActive(); |
|
176 } |
|
177 |
|
178 |
|
179 /** |
|
180 Cancels an outstanding read, |
|
181 */ |
|
182 void CObexUsbActiveReader::DoCancel() |
|
183 { |
|
184 FLOG(_L("CObexUsbActiveReader::DoCancel")); |
|
185 |
|
186 iUsb.ReadCancel(KReceiveEndpoint); |
|
187 } |
|
188 |
|
189 |
|
190 /** |
|
191 Return the maximum packet size |
|
192 @return TInt the maximum packet size for this transport |
|
193 */ |
|
194 TInt CObexUsbActiveReader::GetMaxPacketSize() |
|
195 { |
|
196 LOG_FUNC |
|
197 |
|
198 return GetObexPacketDataLimit(); |
|
199 } |
|
200 |
|
201 |
|
202 /** |
|
203 Returns a initial packet size when the packet size of iPacket is not know. This is used |
|
204 when determining the remaining bytes to be read. |
|
205 @return TInt the initial packet size |
|
206 */ |
|
207 TInt CObexUsbActiveReader::GetInitialPacketSize () |
|
208 { |
|
209 LOG_FUNC |
|
210 |
|
211 return GetObexPacketBufferSize(); |
|
212 } |
|
213 // |
|
214 |
|
215 /** |
|
216 CObexUsbConnector constructor. |
|
217 */ |
|
218 CObexUsbConnector::CObexUsbConnector(MObexTransportNotify& aObserver, TObexUsbTransportInfo& aUsbTransportInfo) |
|
219 : CObexConnector(aObserver), |
|
220 iObexTransportInfo(aUsbTransportInfo), |
|
221 iMode(EDefaultClient) |
|
222 { |
|
223 LOG_FUNC |
|
224 // Note iObexTransportInfo reference is only kept so that it can be used in the ConstructL |
|
225 // It may not be safe to use this variables outside of the construction phases |
|
226 } |
|
227 |
|
228 |
|
229 /* |
|
230 Returns an instance of CObexUsbConnector |
|
231 |
|
232 @param aController Reference to a MObexTransportNotify object (the CObexUsbTransportController that owns this) |
|
233 @param aTransportInfo Reference to a TObexUsbTransportInfo object containing the transport information |
|
234 |
|
235 @return A pointer to a CObexUsbConnector object |
|
236 */ |
|
237 CObexUsbConnector* CObexUsbConnector::NewL(MObexTransportNotify& aController, TObexUsbTransportInfo& aTransportInfo) |
|
238 { |
|
239 CObexUsbConnector* self = new(ELeave) CObexUsbConnector(aController, aTransportInfo); |
|
240 CleanupStack::PushL(self); |
|
241 self->ConstructL(); |
|
242 CleanupStack::Pop(self); |
|
243 return(self); |
|
244 } |
|
245 |
|
246 |
|
247 /** |
|
248 Second phase construction. |
|
249 */ |
|
250 void CObexUsbConnector::ConstructL() |
|
251 { |
|
252 LOG_FUNC |
|
253 |
|
254 OpenUsbL(0); |
|
255 |
|
256 FLOG(_L("USB opened")); |
|
257 |
|
258 iHandler = CObexUsbHandler::NewL(iObexTransportInfo, *this, iUsb); |
|
259 iCallback = new(ELeave) CAsyncCallBack(EPriorityHigh); |
|
260 iStaller = CObexUsbStaller::NewL(iUsb, *this); |
|
261 iHandler->Start(); |
|
262 |
|
263 BaseConstructL(); |
|
264 } |
|
265 |
|
266 |
|
267 /** |
|
268 CObexUsbConnector destructor. Releases endpoint and closes USB object if we have an open connection. |
|
269 */ |
|
270 CObexUsbConnector::~CObexUsbConnector() |
|
271 { |
|
272 LOG_FUNC |
|
273 |
|
274 delete iCallback; |
|
275 delete iHandler; |
|
276 delete iStaller; |
|
277 |
|
278 if (iUsb.Handle()) |
|
279 { |
|
280 iUsb.Close(); |
|
281 } |
|
282 } |
|
283 |
|
284 |
|
285 /** |
|
286 Attempt to open a client-type connection. |
|
287 This will succeed if the USB host has already opened a connection to us |
|
288 */ |
|
289 void CObexUsbConnector::ConnectL() |
|
290 { |
|
291 LOG_FUNC |
|
292 |
|
293 if (iMode == EServer) |
|
294 { |
|
295 // Already performed a server-type connect, so can't act as a |
|
296 // client as well. |
|
297 FLOG(_L(" -- In server mode, give up")); |
|
298 LEAVEIFERRORL(KErrNotSupported); |
|
299 } |
|
300 |
|
301 |
|
302 FLOG(_L(" -- Not in server mode")); |
|
303 |
|
304 iMode = EClient; |
|
305 if (iTransportLinkAvailable) |
|
306 { |
|
307 FLOG(_L(" -- Link available, set a callback")); |
|
308 |
|
309 TCallBack callback(LinkUp, this); |
|
310 iCallback->Set(callback); |
|
311 iCallback->CallBack(); |
|
312 iConnectRequested = ETrue; |
|
313 } |
|
314 else |
|
315 { |
|
316 FLOG(_L(" -- No link available, set a callback")); |
|
317 |
|
318 TCallBack callback(NoDevice, this); |
|
319 iCallback->Set(callback); |
|
320 iCallback->CallBack(); |
|
321 } |
|
322 } |
|
323 |
|
324 |
|
325 /* |
|
326 @param aConn A pointer to a connector object. Will be cast to CObexUsbConnector |
|
327 |
|
328 @return KErrNone |
|
329 */ |
|
330 TInt CObexUsbConnector::LinkUp(TAny* aConn) |
|
331 { |
|
332 FLOG(_L("CObexUsbConnector::LinkUp")); |
|
333 |
|
334 reinterpret_cast<CObexUsbConnector*>(aConn)->SignalUp(); |
|
335 return KErrNone; |
|
336 } |
|
337 |
|
338 |
|
339 /* |
|
340 @param aConn A pointer to a connector object. Will be cast to CObexUsbConnector |
|
341 |
|
342 @return KErrNone |
|
343 */ |
|
344 TInt CObexUsbConnector::NoDevice(TAny* aConn) |
|
345 { |
|
346 FLOG(_L("CObexUsbConnector::NoDevice")); |
|
347 |
|
348 reinterpret_cast<CObexUsbConnector*>(aConn)->SignalDown(KErrIrObexClientPeerDoesNotHaveObex); |
|
349 return KErrNone; |
|
350 } |
|
351 |
|
352 |
|
353 /** |
|
354 Cancel an active connection attempt. This is unlikely to succeed, as a client |
|
355 connection over USB will complete almost immediately. |
|
356 */ |
|
357 void CObexUsbConnector::CancelConnect() |
|
358 { |
|
359 LOG_FUNC |
|
360 |
|
361 if (iMode == EClient) |
|
362 { |
|
363 iCallback->Cancel(); |
|
364 } |
|
365 |
|
366 iConnectRequested = EFalse; |
|
367 } |
|
368 |
|
369 |
|
370 /** |
|
371 Start listening for a connection to us. |
|
372 */ |
|
373 void CObexUsbConnector::AcceptL() |
|
374 { |
|
375 LOG_FUNC |
|
376 |
|
377 if (iMode == EClient) |
|
378 { |
|
379 // Already carried out a client side connection. Therefore we |
|
380 // can't be a server as well. |
|
381 FLOG(_L(" -- In client mode, give up")); |
|
382 |
|
383 LEAVEIFERRORL(KErrNotSupported); |
|
384 } |
|
385 |
|
386 FLOG(_L(" -- Not in client mode")); |
|
387 |
|
388 iMode = EServer; |
|
389 if (iTransportLinkAvailable) |
|
390 { |
|
391 FLOG(_L(" -- Transport link currently available, set a callback")); |
|
392 |
|
393 TCallBack callback(LinkUp, this); |
|
394 iCallback->Set(callback); |
|
395 iCallback->CallBack(); |
|
396 } |
|
397 else |
|
398 { |
|
399 FLOG(_L(" -- No link available, wait for one")); |
|
400 |
|
401 iWaitingForLink = ETrue; |
|
402 } |
|
403 } |
|
404 |
|
405 /** |
|
406 Stop listening for connections. |
|
407 */ |
|
408 void CObexUsbConnector::CancelAccept() |
|
409 { |
|
410 LOG_FUNC |
|
411 |
|
412 if (iMode == EServer) |
|
413 { |
|
414 iWaitingForLink = EFalse; |
|
415 iCallback->Cancel(); |
|
416 } |
|
417 } |
|
418 |
|
419 |
|
420 /** |
|
421 Called to indicate transport layer has come up. |
|
422 */ |
|
423 void CObexUsbConnector::TransportUp() |
|
424 { |
|
425 LOG_FUNC |
|
426 |
|
427 SetTransportPacketSize(); |
|
428 |
|
429 iTransportLinkAvailable = ETrue; |
|
430 |
|
431 if ((iMode == EServer) && (iWaitingForLink)) |
|
432 { |
|
433 FLOG(_L(" -- Signalling link available")); |
|
434 |
|
435 iWaitingForLink = EFalse; |
|
436 SignalUp(); |
|
437 } |
|
438 } |
|
439 |
|
440 /** |
|
441 Called to indicate transport layer has gone down. |
|
442 |
|
443 @param aErr Any error code associated with disconnection. Defaults to KErrDisconnected. |
|
444 */ |
|
445 void CObexUsbConnector::TransportDown(TInt aErr) |
|
446 { |
|
447 LOG_FUNC |
|
448 |
|
449 ResetTransportPacketSize(); |
|
450 |
|
451 iStaller->Cancel(); |
|
452 |
|
453 iTransportLinkAvailable = EFalse; |
|
454 |
|
455 if (iMode == EServer) |
|
456 { |
|
457 FLOG(_L(" -- In server mode, signal link down")); |
|
458 |
|
459 SignalDown(aErr); |
|
460 } |
|
461 else |
|
462 { |
|
463 FLOG(_L(" -- In client mode")); |
|
464 |
|
465 // Client or default client state |
|
466 if (iConnectRequested) |
|
467 { |
|
468 FLOG(_L(" -- Outstanding client connection. Signal link down")); |
|
469 |
|
470 iConnectRequested = EFalse; |
|
471 SignalDown(aErr); |
|
472 } |
|
473 } |
|
474 } |
|
475 |
|
476 /** |
|
477 Signals to the transport controller that the transport is up |
|
478 */ |
|
479 void CObexUsbConnector::SignalUp() |
|
480 { |
|
481 LOG_FUNC |
|
482 |
|
483 // Indicate transport now up |
|
484 TObexConnectionInfo sockinfo; |
|
485 sockinfo.iMaxRecvSize = 0; // set these to zero as we can't find them out |
|
486 sockinfo.iMaxSendSize = 0; // and they are not used |
|
487 sockinfo.iSocketType = TObexConnectionInfo::EUsbStream; |
|
488 Observer().TransportUp(sockinfo); |
|
489 } |
|
490 |
|
491 |
|
492 /** |
|
493 Signals (with an error code) to the transport controller that the transport has gone down |
|
494 */ |
|
495 void CObexUsbConnector::SignalDown(TInt aErr) |
|
496 { |
|
497 FLOG(_L("CObexUsbConnector::SignalDown")); |
|
498 |
|
499 Observer().Error(aErr); |
|
500 } |
|
501 |
|
502 |
|
503 /** |
|
504 The Obex server running over USB is not able to bring the transport |
|
505 down itself. It will only delete the transport object when an error |
|
506 has occurred (such as the link being brought down) and hence the |
|
507 transport is no longer valid. |
|
508 |
|
509 @return ETrue |
|
510 */ |
|
511 TBool CObexUsbConnector::BringTransportDown() |
|
512 { |
|
513 // This cancel function needs to be called here because it |
|
514 // doesn't get called anywhere else. Bluetooth and IrDA rely |
|
515 // on the socket shutdown to cancel the accept. |
|
516 CancelAccept(); |
|
517 return ETrue; |
|
518 } |
|
519 |
|
520 |
|
521 /** |
|
522 Return the transport layer object for use by USB transport objects |
|
523 |
|
524 @return Pointer to the USB transport layer object |
|
525 */ |
|
526 RDevUsbcClient* CObexUsbConnector::TransportObject() |
|
527 { |
|
528 return &iUsb; |
|
529 } |
|
530 |
|
531 |
|
532 /** |
|
533 Sets a bus stall condition on the IN endpoint. This will cause the USB |
|
534 host to initiate a CLEAR_FEATURE sequence, which notifies the server that the |
|
535 Obex link has been reset (equivalent to dropping the Obex level connection) |
|
536 */ |
|
537 void CObexUsbConnector::SignalTransportError() |
|
538 { |
|
539 LOG_FUNC |
|
540 |
|
541 iStaller->Start(); |
|
542 iTransportLinkAvailable = EFalse; |
|
543 iConnectRequested = EFalse; |
|
544 } |
|
545 |
|
546 |
|
547 /** |
|
548 Stall cleared => transport available. |
|
549 This upcall has been separated from the TransportUp upcall for two |
|
550 reasons---it's called from a different class and it happens when an |
|
551 error condition has been cleared. Currently it has no special |
|
552 meaning, but this could change in future. |
|
553 */ |
|
554 void CObexUsbConnector::StallCleared() |
|
555 { |
|
556 LOG_FUNC |
|
557 |
|
558 TransportUp(); |
|
559 } |
|
560 |
|
561 |
|
562 /** |
|
563 Opens USB and prepares it for use. |
|
564 |
|
565 @param aUnit According to the RDevUsbcClient documentation, this should be 0. |
|
566 */ |
|
567 void CObexUsbConnector::OpenUsbL(TInt aUnit) |
|
568 { |
|
569 LOG1(_L("CObexUsbConnector::OpenUsbL called for unit=%d"), aUnit); |
|
570 |
|
571 // Load ldd |
|
572 TInt err = User::LoadLogicalDevice(KUsbLddName); |
|
573 |
|
574 if (err != KErrNone && err != KErrAlreadyExists) |
|
575 { |
|
576 LEAVEIFERRORL(err); |
|
577 } |
|
578 |
|
579 // Open the requested unit and initialise local state |
|
580 LEAVEIFERRORL(iUsb.Open(aUnit)); |
|
581 } |
|
582 |
|
583 |
|
584 void CObexUsbConnector::ResetTransportPacketSize() |
|
585 { |
|
586 iPacketSize = 0; |
|
587 } |
|
588 |
|
589 |
|
590 void CObexUsbConnector::SetTransportPacketSize() |
|
591 { |
|
592 if (iUsb.CurrentlyUsingHighSpeed()) |
|
593 { |
|
594 iPacketSize = KMaxPacketTypeBulkHS; |
|
595 } |
|
596 else |
|
597 { |
|
598 iPacketSize = KMaxPacketTypeBulkFS; |
|
599 } |
|
600 } |
|
601 |
|
602 |
|
603 TInt CObexUsbConnector::GetTransportPacketSize() |
|
604 { |
|
605 return iPacketSize; |
|
606 } |
|
607 |
|
608 |
|
609 // |
|
610 |
|
611 /** |
|
612 Constructs a CObexUsbHandler object |
|
613 |
|
614 @param aUsbTransportInfo Reference to a TObexTransportInfo object. Will be cast to TObexUsbTransportInfo. |
|
615 @param aOwner Reference to a MObexUsbConnector that owns this handler |
|
616 @param aUsb Reference to a RDevUsbcClient object. |
|
617 |
|
618 @return A new CObexUsbHandler object |
|
619 */ |
|
620 CObexUsbHandler* CObexUsbHandler::NewL(TObexUsbTransportInfo& aUsbTransportInfo, |
|
621 MObexUsbConnector& aOwner, |
|
622 RDevUsbcClient& aUsb) |
|
623 { |
|
624 FLOG(_L("CObexUsbHandler::NewL")); |
|
625 |
|
626 CObexUsbHandler* self = new (ELeave) CObexUsbHandler(aUsbTransportInfo, aOwner, aUsb); |
|
627 CleanupStack::PushL(self); |
|
628 self->ConstructL(); |
|
629 CleanupStack::Pop(self); |
|
630 return self; |
|
631 } |
|
632 |
|
633 |
|
634 /** |
|
635 CObexUsbHandler constructor. |
|
636 |
|
637 Note that the iObexTransportInfo may not be valid outside of the construction phases |
|
638 The constructor copies out most of the information it needs into member variables |
|
639 apart from the interface string descriptor, which is used from RegInterfacesL |
|
640 |
|
641 @param aUsbTransportInfo Reference to a TObexTransportInfo object. Will be cast to TObexUsbTransportInfo. |
|
642 @param aOwner Reference to a MObexUsbConnector that owns this handler |
|
643 @param aUsb Reference to a RDevUsbcClient object. |
|
644 */ |
|
645 CObexUsbHandler::CObexUsbHandler(TObexUsbTransportInfo& aUsbTransportInfo, |
|
646 MObexUsbConnector& aOwner, |
|
647 RDevUsbcClient& aUsb) |
|
648 : CActive(EPriorityStandard), iObexTransportInfo(aUsbTransportInfo), |
|
649 iOwner(aOwner), iUsb(aUsb) |
|
650 { |
|
651 LOG_FUNC |
|
652 |
|
653 CActiveScheduler::Add(this); |
|
654 |
|
655 // Set interface performance configuration parameters |
|
656 if (aUsbTransportInfo.iTransportName == KObexUsbProtocol) |
|
657 // Default values if transport is normal USB - no extra bandwidth, no DMA |
|
658 { |
|
659 FLOG(_L("CObexUsbHandler - Using default USB protocol info")); |
|
660 iBandwidthPriority = EUsbcBandwidthOUTDefault | EUsbcBandwidthINDefault; |
|
661 iRequestDmaOnOutEndpoint = EFalse; |
|
662 iRequestDmaOnInEndpoint = EFalse; |
|
663 } |
|
664 else if (aUsbTransportInfo.iTransportName == KObexUsbProtocolV2) |
|
665 // If transport is extended USB take values from the protocol info |
|
666 { |
|
667 FLOG(_L("CObexUsbHandler - Using USB protocol extended info")); |
|
668 TObexUsbV2TransportInfo& infoV2 = static_cast<TObexUsbV2TransportInfo&>(aUsbTransportInfo); |
|
669 iBandwidthPriority = infoV2.iBandwidthPriority; |
|
670 iRequestDmaOnOutEndpoint = infoV2.iDmaOnOutEndpoint; |
|
671 iRequestDmaOnInEndpoint = infoV2.iDmaOnInEndpoint; |
|
672 } |
|
673 else |
|
674 { |
|
675 //aUsbTransportInfo.iTransportName is used to load the correct plug-in, so if this code |
|
676 //is being executed it must have contained one of the options above. Else something |
|
677 //has gone badly wrong. |
|
678 __ASSERT_DEBUG(false, PANIC(KPanicCat, EUnknownUsbTransport)); |
|
679 } |
|
680 |
|
681 LOG3(_L("CObexUsbHandler - iBandwidthPriority 0x%X, iDmaOnOutEndpoint, %d iDmaOnInEndpoint %d"), |
|
682 iBandwidthPriority, iRequestDmaOnOutEndpoint, iRequestDmaOnInEndpoint); |
|
683 } |
|
684 |
|
685 |
|
686 /** |
|
687 Second phase construction. |
|
688 */ |
|
689 void CObexUsbHandler::ConstructL() |
|
690 { |
|
691 |
|
692 // Check bandwidth priority to make sure it makes sense |
|
693 // Reasoning is that the bitwise OR of the maximum values of IN and OUT priorities |
|
694 // covers all the bits that can be set in iBandwidthPriority so, using this as a mask, |
|
695 // anything set outside of this indicates that iBandwidthPriority is corrupt |
|
696 if ( ( iBandwidthPriority & ~( EUsbcBandwidthOUTMaximum | EUsbcBandwidthINMaximum ) ) != 0 ) |
|
697 { |
|
698 LEAVEIFERRORL(KErrArgument); |
|
699 } |
|
700 |
|
701 FLOG(_L("About to open USB comms interface connection")); |
|
702 |
|
703 LEAVEIFERRORL(iUsbComms.Open(0)); |
|
704 |
|
705 FLOG(_L("Registering interfaces")); |
|
706 |
|
707 RegInterfacesL(); |
|
708 } |
|
709 |
|
710 |
|
711 /** |
|
712 CObexUsbHandler destructor. |
|
713 */ |
|
714 CObexUsbHandler::~CObexUsbHandler() |
|
715 { |
|
716 LOG_FUNC |
|
717 Cancel(); |
|
718 |
|
719 // Must release interfaces from highest alternate setting downwards |
|
720 if (iUsb.Handle()) |
|
721 { |
|
722 #ifndef NO_ALTERNATE_USB_INTERFACE_SUPPORT |
|
723 iUsb.ReleaseInterface(1 /*alternate setting*/); |
|
724 #endif |
|
725 iUsb.ReleaseInterface(0 /*alternate setting*/); |
|
726 } |
|
727 |
|
728 if (iUsbComms.Handle()) |
|
729 { |
|
730 iUsbComms.ReleaseInterface(0 /*alternate setting*/); |
|
731 } |
|
732 |
|
733 iUsbComms.Close(); |
|
734 } |
|
735 |
|
736 |
|
737 /** |
|
738 Standard active object error function. |
|
739 |
|
740 @return KErrNone because currently nothing should cause this to be called. |
|
741 */ |
|
742 TInt CObexUsbHandler::RunError(TInt /*aError*/) |
|
743 { |
|
744 return KErrNone; |
|
745 } |
|
746 |
|
747 |
|
748 /** |
|
749 This function will be called upon a change in the state of the device |
|
750 (as set up in AcceptL). |
|
751 */ |
|
752 void CObexUsbHandler::RunL() |
|
753 { |
|
754 LOG1(_L("CObexUsbHandler::RunL called state=0x%X"), iUsbState); |
|
755 |
|
756 if (iStatus != KErrNone) |
|
757 { |
|
758 LOG1(_L("CObexUsbHandler::RunL() - Error = %d"),iStatus.Int()); |
|
759 |
|
760 iTransportUp = EFalse; |
|
761 iOwner.TransportDown(iStatus.Int()); |
|
762 return; |
|
763 } |
|
764 |
|
765 // Check whether the alternate setting to use or the device state has changed. |
|
766 // We have to check the device state to handle the unplugging of the cable. We can't |
|
767 // rely on the always-outstanding read to complete with an error, because the driver |
|
768 // doesn't have a well-defined error code for this. |
|
769 |
|
770 if (iUsbState & KUsbAlternateSetting) |
|
771 { |
|
772 iUsbState &= ~KUsbAlternateSetting; |
|
773 |
|
774 LOG1(_L("switched to alternate setting %d"), iUsbState); |
|
775 |
|
776 if (iUsbState == KObexAlt0) |
|
777 { |
|
778 // alternate setting 0 - function inactive |
|
779 if (iTransportUp) |
|
780 { |
|
781 FLOG(_L("CObexUsbHandler::RunL - transport layer going down...")); |
|
782 |
|
783 iTransportUp = EFalse; |
|
784 iOwner.TransportDown(); |
|
785 } |
|
786 } |
|
787 else if (iUsbState == KObexAlt1) |
|
788 { |
|
789 // alternate setting 1 - function active |
|
790 if (!iTransportUp) |
|
791 { |
|
792 FLOG(_L("CObexUsbHandler::RunL - transport layer coming up...")); |
|
793 |
|
794 // Now the transport is selected, DMA can be allocated to the endpoints, if required |
|
795 AllocateDma(); |
|
796 |
|
797 iTransportUp = ETrue; |
|
798 |
|
799 iOwner.TransportUp(); |
|
800 } |
|
801 } |
|
802 else |
|
803 { |
|
804 FLOG(_L("WARNING: unknown setting!")); |
|
805 } |
|
806 } |
|
807 else |
|
808 { |
|
809 TUsbcDeviceState deviceState = static_cast<TUsbcDeviceState>(iUsbState); |
|
810 |
|
811 switch(deviceState) |
|
812 { |
|
813 case EUsbcDeviceStateUndefined: |
|
814 case EUsbcDeviceStateAttached: |
|
815 case EUsbcDeviceStatePowered: |
|
816 case EUsbcDeviceStateDefault: |
|
817 case EUsbcDeviceStateAddress: |
|
818 #ifdef ERRONEOUS_SUSPEND_INDICATIONS |
|
819 // On Lubbock, we sometimes get "suspended" when the cable is unplugged. |
|
820 case EUsbcDeviceStateSuspended: |
|
821 #endif // ERRONEOUS_SUSPEND_INDICATIONS |
|
822 if (iTransportUp) |
|
823 { |
|
824 FLOG(_L("CObexUsbHandler::RunL - transport layer going down...")); |
|
825 |
|
826 iTransportUp = EFalse; |
|
827 iOwner.TransportDown(); |
|
828 } |
|
829 break; |
|
830 |
|
831 #ifndef ERRONEOUS_SUSPEND_INDICATIONS |
|
832 case EUsbcDeviceStateSuspended: |
|
833 break; |
|
834 #endif // !ERRONEOUS_SUSPEND_INDICATIONS |
|
835 |
|
836 case EUsbcDeviceStateConfigured: |
|
837 // Normally, we don't do anything here, because the transport only goes up when |
|
838 // we actually receive the alternate interface change. |
|
839 #ifdef NO_ALTERNATE_USB_INTERFACE_SUPPORT |
|
840 if (!iTransportUp) |
|
841 { |
|
842 FLOG(_L("Device now configured: transport layer coming up...")); |
|
843 |
|
844 iTransportUp = ETrue; |
|
845 |
|
846 // DMA can be allocated to the endpoints, if required |
|
847 // This has to be done here for no alternate interface devices |
|
848 // as they will not receive interface change notification |
|
849 AllocateDma(); |
|
850 |
|
851 iOwner.TransportUp(); |
|
852 } |
|
853 #endif // NO_ALTERNATE_USB_INTERFACE_SUPPORT |
|
854 break; |
|
855 |
|
856 default: |
|
857 __ASSERT_DEBUG(false, PANIC(KPanicCat, EUnknownUsbState)); |
|
858 break; |
|
859 } |
|
860 } |
|
861 |
|
862 // Await further notification of a state change. We may have called Error(), which |
|
863 // would already have set this notification request. |
|
864 if (!IsActive()) |
|
865 { |
|
866 iUsb.AlternateDeviceStatusNotify(iStatus, iUsbState); |
|
867 SetActive(); |
|
868 } |
|
869 |
|
870 FLOG(_L("CObexUsbHandler::RunL finished")); |
|
871 } |
|
872 |
|
873 |
|
874 /** |
|
875 Standard active object cancellation function. |
|
876 */ |
|
877 void CObexUsbHandler::DoCancel() |
|
878 { |
|
879 LOG_FUNC |
|
880 |
|
881 iUsb.AlternateDeviceStatusNotifyCancel(); |
|
882 } |
|
883 |
|
884 |
|
885 /** |
|
886 Registers the required comms and data interfaces. |
|
887 */ |
|
888 void CObexUsbHandler::RegInterfacesL() |
|
889 { |
|
890 LOG_FUNC |
|
891 |
|
892 // Setup a CDC Communication Class interface |
|
893 TUsbcInterfaceInfoBuf ifc; |
|
894 |
|
895 // Extract the interface string from the transport info structure we were |
|
896 // passed on construction. This isn't const because the SetInterface API |
|
897 // requires it not to be. |
|
898 // This is the only point where iObexTransportInfo is used directly |
|
899 // Do not use iObexTransportInfo outside of construction phases |
|
900 TPtrC string(iObexTransportInfo.iInterfaceStringDescriptor); |
|
901 |
|
902 LOG1(_L("Using interface string \"%S\""), &string); |
|
903 |
|
904 ifc().iString = &string; |
|
905 ifc().iClass.iClassNum = KObexClassNumber; |
|
906 ifc().iClass.iSubClassNum = KObexSubClassNumber; |
|
907 ifc().iClass.iProtocolNum = KObexProtocolNumber; |
|
908 ifc().iTotalEndpointsUsed = 0; |
|
909 |
|
910 // Indicate that this interface does not expect any control transfers |
|
911 // from EP0. |
|
912 ifc().iFeatureWord |= KUsbcInterfaceInfo_NoEp0RequestsPlease; |
|
913 |
|
914 FLOG(_L("CObexUsbListeningConnector::RegInterfacesL - setting comms interface")); |
|
915 |
|
916 TInt err = iUsbComms.SetInterface(0, ifc); |
|
917 |
|
918 if (err != KErrNone) |
|
919 { |
|
920 LOG1(_L("SetInterface failed with error %d"), err); |
|
921 LEAVEIFERRORL(err); |
|
922 } |
|
923 |
|
924 // Get the interface number for later |
|
925 TInt intDescSize; |
|
926 err = iUsbComms.GetInterfaceDescriptorSize(0,intDescSize); |
|
927 if(err != KErrNone) |
|
928 { |
|
929 LOG1(_L("Failed to get interface descriptor size. Err = %d"),err); |
|
930 intDescSize = KObexDefaultInterfaceDescriptorLength; //Default is 100 |
|
931 } |
|
932 HBufC8* interfaceDescriptor; |
|
933 interfaceDescriptor = HBufC8::NewLC(intDescSize); |
|
934 TPtr8 pIntDesc = interfaceDescriptor->Des(); |
|
935 iUsbComms.GetInterfaceDescriptor(0, pIntDesc); |
|
936 TUint8 obexIntNo = interfaceDescriptor->Ptr()[2]; |
|
937 CleanupStack::PopAndDestroy(); |
|
938 |
|
939 TBuf8<KObexInterfaceDescriptorBlockLength> desc; |
|
940 |
|
941 // Comms Class Header Functional Descriptor |
|
942 |
|
943 desc.Append(KObexFunctionalDescriptorLength); |
|
944 desc.Append(KUsbDescType_CS_Interface); |
|
945 desc.Append(KHeaderFunctionalDescriptor); |
|
946 desc.Append(KCdcVersionNumber[0]); |
|
947 desc.Append(KCdcVersionNumber[1]); |
|
948 |
|
949 // Obex Functional Descriptor |
|
950 |
|
951 desc.Append(KObexFunctionalDescriptorLength); |
|
952 desc.Append(KUsbDescType_CS_Interface); |
|
953 desc.Append(KObexFunctionalDescriptor); |
|
954 desc.Append(KWmcdcVersionNumber[0]); |
|
955 desc.Append(KWmcdcVersionNumber[1]); |
|
956 |
|
957 // Union Functional Descriptor |
|
958 |
|
959 desc.Append(KObexFunctionalDescriptorLength); |
|
960 desc.Append(KUsbDescType_CS_Interface); |
|
961 desc.Append(KUnionFunctionalDescriptor); |
|
962 desc.Append(obexIntNo); |
|
963 TInt dataInt = obexIntNo + 1; |
|
964 desc.Append(static_cast<TUint8>(dataInt)); |
|
965 |
|
966 err = iUsbComms.SetCSInterfaceDescriptorBlock(0, desc); |
|
967 if (err != KErrNone) |
|
968 { |
|
969 LOG1(_L("SetCSInterfaceDescriptorBlock failed with error %d"), err); |
|
970 LEAVEIFERRORL(err); |
|
971 } |
|
972 |
|
973 // Setup CDC Data Class interfaces |
|
974 |
|
975 // Only set the "function inactive" interface (alternate setting 0) |
|
976 // if the device can support alternate interfaces |
|
977 #ifndef NO_ALTERNATE_USB_INTERFACE_SUPPORT |
|
978 TUsbcInterfaceInfoBuf dataifc; |
|
979 |
|
980 dataifc().iString = NULL; |
|
981 dataifc().iClass.iClassNum = KObexDataClass; |
|
982 dataifc().iClass.iSubClassNum = KObexDataSubClass; |
|
983 dataifc().iClass.iProtocolNum = 0; |
|
984 dataifc().iTotalEndpointsUsed = 0; |
|
985 |
|
986 // Indicate that this interface does not expect any control transfers |
|
987 // from EP0. |
|
988 dataifc().iFeatureWord |= KUsbcInterfaceInfo_NoEp0RequestsPlease; |
|
989 |
|
990 FLOG(_L("Setting data class interface (alt setting 0")); |
|
991 |
|
992 err = iUsb.SetInterface(0 /*alternate setting*/, dataifc, iBandwidthPriority); |
|
993 if (err != KErrNone) |
|
994 { |
|
995 LOG1(_L("Cannot set data interface (alternate setting 0): error %d"), err); |
|
996 LEAVEIFERRORL(err); |
|
997 } |
|
998 |
|
999 // If anything below this point leaves, make sure this alternate setting |
|
1000 // gets released. |
|
1001 CleanupStack::PushL(TCleanupItem(CleanupReleaseInterface0, &iUsb)); |
|
1002 #endif // NO_ALTERNATE_USB_INTERFACE_SUPPORT |
|
1003 |
|
1004 // Check the device has enough endpoints for the "function active" data interface |
|
1005 TUsbDeviceCaps dCaps; |
|
1006 LEAVEIFERRORL(iUsb.DeviceCaps(dCaps)); |
|
1007 |
|
1008 TInt n = dCaps().iTotalEndpoints; |
|
1009 if (n < KObexMinNumEndpoints) |
|
1010 { |
|
1011 LEAVEIFERRORL(KErrOverflow); |
|
1012 } |
|
1013 |
|
1014 // Use the hardware's HS capability to determine maximum bulk transfer packet size |
|
1015 TInt maxPacketSize = (dCaps().iHighSpeed) ? KMaxPacketTypeBulkHS : KMaxPacketTypeBulkFS; |
|
1016 |
|
1017 |
|
1018 // Get information on the available endpoints from the driver |
|
1019 TUsbcEndpointData data[KUsbcMaxEndpoints]; |
|
1020 TPtr8 dataptr(REINTERPRET_CAST(TUint8*, data), sizeof(data), sizeof(data)); |
|
1021 LEAVEIFERRORL(iUsb.EndpointCaps(dataptr)); |
|
1022 |
|
1023 // Check to see if there are suitably capable IN and OUT endpoints available |
|
1024 // and fill dataifc2 structure accordingly. |
|
1025 // |
|
1026 // NOTE: The order the iEndpointData array is filled matches the order used for the |
|
1027 // virtual endpoint numbers KTransmitEndpoint and KReceiveEndpoint - so change with caution! |
|
1028 // |
|
1029 // The virtual endpoint numbers are 1-based, whereas the iEndpointData array is 0 based |
|
1030 // hence the subtraction in the array indices |
|
1031 // |
|
1032 // NOTE: IN and OUT refer to the host so in this case: |
|
1033 // IN => device to PC = KTransmitEndpoint |
|
1034 // OUT => PC to device = KReceiveEndpoint |
|
1035 TUsbcInterfaceInfoBuf dataifc2; |
|
1036 TBool foundIn = EFalse; |
|
1037 TBool foundOut = EFalse; |
|
1038 for (TInt i = 0; !(foundIn && foundOut) && i < n; i++) |
|
1039 { |
|
1040 const TUsbcEndpointCaps* caps = &data[i].iCaps; |
|
1041 if (data[i].iInUse) |
|
1042 { |
|
1043 continue; |
|
1044 } |
|
1045 |
|
1046 const TUint KBulkInFlags = KUsbEpTypeBulk | KUsbEpDirIn; |
|
1047 const TUint KBulkOutFlags = KUsbEpTypeBulk | KUsbEpDirOut; |
|
1048 |
|
1049 if (!foundIn && (caps->iTypesAndDir & KBulkInFlags) == KBulkInFlags) |
|
1050 { |
|
1051 dataifc2().iEndpointData[KTransmitEndpoint - 1].iType = KUsbEpTypeBulk; |
|
1052 dataifc2().iEndpointData[KTransmitEndpoint - 1].iDir = KUsbEpDirIn; |
|
1053 TInt maxSize = caps->MaxPacketSize(); |
|
1054 if (maxSize > maxPacketSize) |
|
1055 { |
|
1056 maxSize = maxPacketSize; |
|
1057 } |
|
1058 dataifc2().iEndpointData[KTransmitEndpoint - 1].iSize = maxSize; |
|
1059 foundIn = ETrue; |
|
1060 } |
|
1061 else if (!foundOut && (caps->iTypesAndDir & KBulkOutFlags) == KBulkOutFlags) |
|
1062 { |
|
1063 dataifc2().iEndpointData[KReceiveEndpoint - 1].iType = KUsbEpTypeBulk; |
|
1064 dataifc2().iEndpointData[KReceiveEndpoint - 1].iDir = KUsbEpDirOut; |
|
1065 TInt maxSize = caps->MaxPacketSize(); |
|
1066 if (maxSize > maxPacketSize) |
|
1067 { |
|
1068 maxSize = maxPacketSize; |
|
1069 } |
|
1070 dataifc2().iEndpointData[KReceiveEndpoint - 1].iSize = maxSize; |
|
1071 foundOut = ETrue; |
|
1072 } |
|
1073 } |
|
1074 |
|
1075 if (!(foundIn && foundOut)) |
|
1076 { |
|
1077 LEAVEIFERRORL(KErrHardwareNotAvailable); |
|
1078 } |
|
1079 |
|
1080 // Set the active interface. |
|
1081 dataifc2().iString = NULL; |
|
1082 dataifc2().iClass.iClassNum = KObexDataClass; |
|
1083 dataifc2().iClass.iSubClassNum = KObexDataSubClass; |
|
1084 dataifc2().iClass.iProtocolNum = 0; |
|
1085 dataifc2().iTotalEndpointsUsed = KObexTotalEndpoints; |
|
1086 |
|
1087 // Indicate that this interface does not expect any control transfers |
|
1088 // from EP0. |
|
1089 dataifc2().iFeatureWord |= KUsbcInterfaceInfo_NoEp0RequestsPlease; |
|
1090 |
|
1091 #ifdef NO_ALTERNATE_USB_INTERFACE_SUPPORT |
|
1092 // For devices that don't suport alternate interfaces, have to place the "function active" |
|
1093 // interface at alternate setting 0, although the CDC specification says if should be alternate setting 1 |
|
1094 FLOG(_L("Setting data class interface (no alternate interface support)")); |
|
1095 |
|
1096 err = iUsb.SetInterface(0 /*alternate setting*/, dataifc2, iBandwidthPriority); |
|
1097 |
|
1098 if (err != KErrNone) |
|
1099 { |
|
1100 //FTRACE(FPrint(_L("Cannot set data interface (no alternate interface support): error %d"), err)); |
|
1101 LOG1(_L("Cannot set data interface (no alternate interface support): error %d"), err); |
|
1102 LEAVEIFERRORL(err); |
|
1103 } |
|
1104 #else |
|
1105 FLOG(_L("Setting data class interface (alternate setting 1)")); |
|
1106 |
|
1107 err = iUsb.SetInterface(1 /*alternate setting*/, dataifc2, iBandwidthPriority); |
|
1108 |
|
1109 if (err != KErrNone) |
|
1110 { |
|
1111 //FTRACE(FPrint(_L("Cannot set data interface (alternate setting 1): error %d"), err)); |
|
1112 LOG1(_L("Cannot set data interface (alternate setting 1): error %d"), err); |
|
1113 LEAVEIFERRORL(err); |
|
1114 } |
|
1115 |
|
1116 CleanupStack::Pop(); // ReleaseInterface0 |
|
1117 #endif |
|
1118 |
|
1119 FLOG(_L("CObexUsbHandler::RegInterfacesL - finished.")); |
|
1120 } |
|
1121 |
|
1122 |
|
1123 /** |
|
1124 Utility function which releases the first alternate setting of the specified |
|
1125 interface. Used when setting up Obex interfaces. |
|
1126 |
|
1127 @param aInterface The interface to release |
|
1128 */ |
|
1129 void CObexUsbHandler::CleanupReleaseInterface0(TAny* aInterface) |
|
1130 { |
|
1131 reinterpret_cast<RDevUsbcClient*>(aInterface)->ReleaseInterface(0 /*alternate setting*/); |
|
1132 } |
|
1133 |
|
1134 |
|
1135 /** |
|
1136 Accept an incoming connection. |
|
1137 */ |
|
1138 void CObexUsbHandler::Start() |
|
1139 { |
|
1140 LOG_FUNC |
|
1141 |
|
1142 // Await notification of a state change (this is like waiting for a connect...). |
|
1143 iUsb.AlternateDeviceStatusNotify(iStatus, iUsbState); |
|
1144 SetActive(); |
|
1145 } |
|
1146 |
|
1147 |
|
1148 /** |
|
1149 Utility function to allocate DMA to the bulk endpoints - if they have been requested |
|
1150 This function is called during a connect, once the device is configured, |
|
1151 so if the allocations fail it wont complain in release builds but debug builds will |
|
1152 panic with either EDmaAllocationFailedEndpointIn or EDmaAllocationFailedEndpointOut. |
|
1153 */ |
|
1154 void CObexUsbHandler::AllocateDma() |
|
1155 { |
|
1156 LOG_FUNC |
|
1157 |
|
1158 if (iRequestDmaOnInEndpoint) |
|
1159 { |
|
1160 TInt err = iUsb.AllocateEndpointResource(KTransmitEndpoint, EUsbcEndpointResourceDMA); |
|
1161 // The following log message is checked for in the test code - change with caution! |
|
1162 LOG1(_L("IN Endpoint DMA resource allocation result %d"), err); |
|
1163 (void)err; // to stop compilers complaining about unused variables |
|
1164 } |
|
1165 |
|
1166 if (iRequestDmaOnOutEndpoint) |
|
1167 { |
|
1168 TInt err = iUsb.AllocateEndpointResource(KReceiveEndpoint, EUsbcEndpointResourceDMA); |
|
1169 // The following log message is checked for in the test code - change with caution! |
|
1170 LOG1(_L("OUT Endpoint DMA resource allocation result %d"), err); |
|
1171 (void)err; // to stop compilers complaining about unused variables |
|
1172 } |
|
1173 } |
|
1174 |
|
1175 |
|
1176 // |
|
1177 |
|
1178 /** |
|
1179 Constructs a CObexUsbStaller object |
|
1180 |
|
1181 @param aUsb Reference to a RDevUsbcClient object. |
|
1182 @param aOwner Reference to a MObexUsbConnector that owns this handler |
|
1183 |
|
1184 @return A new CObexUsbStaller object |
|
1185 */ |
|
1186 CObexUsbStaller* CObexUsbStaller::NewL(RDevUsbcClient& aUsb, MObexUsbConnector& aOwner) |
|
1187 { |
|
1188 CObexUsbStaller* self = new(ELeave) CObexUsbStaller(aUsb, aOwner); |
|
1189 return self; |
|
1190 } |
|
1191 |
|
1192 /** |
|
1193 CObexUsbStaller constructor. |
|
1194 |
|
1195 @param aUsb Reference to a RDevUsbcClient object. |
|
1196 @param aOwner Reference to a MObexUsbConnector that owns this handler |
|
1197 */ |
|
1198 CObexUsbStaller::CObexUsbStaller(RDevUsbcClient& aUsb, MObexUsbConnector& aOwner) |
|
1199 : CActive(EPriorityStandard), iUsb(aUsb), iOwner(aOwner) |
|
1200 { |
|
1201 CActiveScheduler::Add(this); |
|
1202 } |
|
1203 |
|
1204 |
|
1205 /** |
|
1206 CObexUsbStaller destructor. |
|
1207 */ |
|
1208 CObexUsbStaller::~CObexUsbStaller() |
|
1209 { |
|
1210 Cancel(); |
|
1211 } |
|
1212 |
|
1213 |
|
1214 /** |
|
1215 Starts the staller |
|
1216 */ |
|
1217 void CObexUsbStaller::Start() |
|
1218 { |
|
1219 LOG_FUNC |
|
1220 |
|
1221 if (!IsActive()) |
|
1222 { |
|
1223 FLOG(_L("Halting transmit endpoint...")); |
|
1224 iUsb.HaltEndpoint(KTransmitEndpoint); |
|
1225 iUsb.EndpointStatusNotify(iStatus, iEndpointStatus); |
|
1226 SetActive(); |
|
1227 } |
|
1228 } |
|
1229 |
|
1230 |
|
1231 /** |
|
1232 Called when the transmit endpoint has changed state |
|
1233 */ |
|
1234 void CObexUsbStaller::RunL() |
|
1235 { |
|
1236 LOG_FUNC |
|
1237 |
|
1238 TEndpointState endpointState; |
|
1239 iUsb.EndpointStatus(KTransmitEndpoint, endpointState); |
|
1240 #ifdef __FLOG_ACTIVE |
|
1241 switch (endpointState) |
|
1242 { |
|
1243 case EEndpointStateNotStalled: |
|
1244 { |
|
1245 FLOG(_L("Receive endpoint not stalled")); |
|
1246 break; |
|
1247 } |
|
1248 case EEndpointStateStalled: |
|
1249 { |
|
1250 FLOG(_L("Receive endpoint stalled")); |
|
1251 break; |
|
1252 } |
|
1253 case EEndpointStateUnknown: |
|
1254 { |
|
1255 FLOG(_L("Receive endpoint unknown state")); |
|
1256 break; |
|
1257 } |
|
1258 } |
|
1259 #endif |
|
1260 if (endpointState == EEndpointStateNotStalled) |
|
1261 { |
|
1262 LOG1(_L("CObexUsbStallWatcher::RunL -- endpoint no longer stalled (0x%08x)"), iEndpointStatus); |
|
1263 iOwner.StallCleared(); |
|
1264 } |
|
1265 else |
|
1266 { |
|
1267 LOG1(_L("CObexUsbStallWatcher::RunL -- endpoint still stalled (0x%08x)"), iEndpointStatus); |
|
1268 iUsb.EndpointStatusNotify(iStatus, iEndpointStatus); |
|
1269 SetActive(); |
|
1270 } |
|
1271 } |
|
1272 |
|
1273 |
|
1274 /** |
|
1275 Standard active object error function. |
|
1276 |
|
1277 @return KErrNone because currently nothing should cause this to be called. |
|
1278 */ |
|
1279 TInt CObexUsbStaller::RunError(TInt /*aError*/) |
|
1280 { |
|
1281 LOG_FUNC |
|
1282 |
|
1283 return KErrNone; |
|
1284 } |
|
1285 |
|
1286 |
|
1287 /** |
|
1288 Standard active object cancellation function. |
|
1289 */ |
|
1290 void CObexUsbStaller::DoCancel() |
|
1291 { |
|
1292 FLOG(_L("CObexUsbStaller -- Cancelling status notification")); |
|
1293 iUsb.EndpointStatusNotifyCancel(); |
|
1294 } |
|
1295 |