diff -r 866b4af7ffbe -r 4dc88a4ac6f4 obex/obexprotocol/obexusbtransport/src/usbconn.cpp --- a/obex/obexprotocol/obexusbtransport/src/usbconn.cpp Tue Sep 28 20:14:08 2010 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1321 +0,0 @@ -// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). -// All rights reserved. -// This component and the accompanying materials are made available -// under the terms of "Eclipse Public License v1.0" -// which accompanies this distribution, and is available -// at the URL "http://www.eclipse.org/legal/epl-v10.html". -// -// Initial Contributors: -// Nokia Corporation - initial contribution. -// -// Contributors: -// -// Description: -// - -/** - @file - @internalComponent -*/ - - -#include -#include "usbconn.h" -#include -#include "logger.h" -#include "obexusbfaults.h" - -#ifdef __FLOG_ACTIVE -_LIT8(KLogComponent, "USB"); -#endif - -#ifdef _DEBUG -_LIT(KPanicCat, "ObexUsbHandler"); -#endif - - -// - -/** -CObexUsbActiveWriter factory function - -@param aTransport Reference to a CObexUsbTransportController object. Required for a call to the CObexUsbActiveReader -@param aOwner Reference to a MObexTransportNotify object -@param aUsb Reference to a RDevUsbcClient object -@param aInfo Reference to a TObexConnectionInfo object -@param aPacketSize The size of packets used on the underlying link, dependent on High Speed mode. -@return Ownership of a new CObexUsbActiveWriter. -*/ -CObexUsbActiveWriter* CObexUsbActiveWriter::NewL(MObexTransportNotify& aOwner, RDevUsbcClient& aUsb, - TObexConnectionInfo& aInfo, TInt aPacketSize) - { - CObexUsbActiveWriter* self = new(ELeave) CObexUsbActiveWriter(aOwner, aUsb, aInfo, aPacketSize); - CleanupStack::PushL(self); - self->BaseConstructL(); - CleanupStack::Pop(self); - return self; - } - -/** -CObexUsbActiveWriter constructor - -@param aTransport Reference to a CObexUsbTransportController object. Required for a call to the CObexUsbActiveReader -@param aOwner Reference to a MObexTransportNotify object -@param aUsb Reference to a RDevUsbcClient object -@param aInfo Reference to a TObexConnectionInfo object -@param aPacketSize The size of packets used on the underlying link, dependent on High Speed mode. -*/ -CObexUsbActiveWriter::CObexUsbActiveWriter(MObexTransportNotify& aOwner, RDevUsbcClient& aUsb, - TObexConnectionInfo& aInfo, TInt aPacketSize) -: CObexWriterBase(EPriorityHigh, aOwner, aInfo), - iUsb(aUsb), iPacketSize(aPacketSize) - { - } - - -/** -CObexUsbActiveWriter destructor. -*/ -CObexUsbActiveWriter::~CObexUsbActiveWriter() - { - LOG_FUNC - - Cancel(); - } - - -/** -Start actual transfer. May be called several times by CObexActiveRW::RunL. -Queues a write on USB endpoint. -*/ -void CObexUsbActiveWriter::DoTransfer() - { - LOG_FUNC - LOG1(_L("CObexUsbActiveWriter::DoTransfer [Length=%d]"),iLocation.Length()); - - iLocation.SetMax(); - iUsb.Write(iStatus, KTransmitEndpoint, iLocation, iLocation.Length(), ETrue); - SetActive(); - } - - -/** -Cancels an outstanding write. -*/ -void CObexUsbActiveWriter::DoCancel() - { - LOG_FUNC - - //Only cancel the write if there's more than 1 packet left to write. - //This restriction is imposed to prevent the SUCCESS response being - //cancelled when an ObexServer is handling a disconnect and bringing - //the transport down. - if(Remaining() > iPacketSize) - { - iUsb.WriteCancel(KTransmitEndpoint); - } - } - - -// - -/** -CObexUsbActiveReader factory function - -@param aOwner Reference to a MObexTransportNotify object -@param aUsb Reference to a RDevUsbcClient object -@param aInfo Reference to a TObexConnectionInfo object -@return Ownership of a new CObexUsbActiveWriter. -*/ -CObexUsbActiveReader* CObexUsbActiveReader::NewL(MObexTransportNotify& aOwner, RDevUsbcClient& aUsb, - TObexConnectionInfo& aInfo) - { - CObexUsbActiveReader* self = new(ELeave) CObexUsbActiveReader(aOwner, aUsb, aInfo); - CleanupStack::PushL(self); - self->BaseConstructL(); - CleanupStack::Pop(self); - return self; - } - -/** -CObexUsbActiveReader constructor - -@param aOwner Reference to a MObexTransportNotify object -@param aUsb Reference to a RDevUsbcClient object -@param aInfo Reference to a TObexConnectionInfo object -*/ -CObexUsbActiveReader::CObexUsbActiveReader(MObexTransportNotify& aOwner, RDevUsbcClient& aUsb, - TObexConnectionInfo& aInfo) -: CObexReaderBase(EPriorityStandard, aOwner, aInfo), iUsb(aUsb) - { - } - - -/** -CObexUsbActiveReader destructor. -*/ -CObexUsbActiveReader::~CObexUsbActiveReader() - { - LOG_FUNC - - Cancel(); - } - - -/** -Start actual transfer. May be called several times by CObexActiveRW::RunL. -Queues a read on USB endpoint. -*/ -void CObexUsbActiveReader::DoTransfer() - { - LOG_FUNC - LOG1(_L("CObexUsbActiveReader::DoTransfer [maxLength=%d]"),iLocation.MaxLength()); - - iUsb.ReadUntilShort(iStatus, KReceiveEndpoint, iLocation); - SetActive(); - } - - -/** -Cancels an outstanding read, - */ -void CObexUsbActiveReader::DoCancel() - { - FLOG(_L("CObexUsbActiveReader::DoCancel")); - - iUsb.ReadCancel(KReceiveEndpoint); - } - - -/** -Return the maximum packet size -@return TInt the maximum packet size for this transport -*/ -TInt CObexUsbActiveReader::GetMaxPacketSize() - { - LOG_FUNC - - return GetObexPacketDataLimit(); - } - - -/** -Returns a initial packet size when the packet size of iPacket is not know. This is used -when determining the remaining bytes to be read. -@return TInt the initial packet size -*/ -TInt CObexUsbActiveReader::GetInitialPacketSize () - { - LOG_FUNC - - return GetObexPacketBufferSize(); - } -// - -/** -CObexUsbConnector constructor. -*/ -CObexUsbConnector::CObexUsbConnector(MObexTransportNotify& aObserver, TObexUsbTransportInfo& aUsbTransportInfo) - : CObexConnector(aObserver), - iObexTransportInfo(aUsbTransportInfo), - iMode(EDefaultClient) - { - LOG_FUNC - // Note iObexTransportInfo reference is only kept so that it can be used in the ConstructL - // It may not be safe to use this variables outside of the construction phases - } - - -/* -Returns an instance of CObexUsbConnector - -@param aController Reference to a MObexTransportNotify object (the CObexUsbTransportController that owns this) -@param aTransportInfo Reference to a TObexUsbTransportInfo object containing the transport information - -@return A pointer to a CObexUsbConnector object -*/ -CObexUsbConnector* CObexUsbConnector::NewL(MObexTransportNotify& aController, TObexUsbTransportInfo& aTransportInfo) - { - CObexUsbConnector* self = new(ELeave) CObexUsbConnector(aController, aTransportInfo); - CleanupStack::PushL(self); - self->ConstructL(); - CleanupStack::Pop(self); - return(self); - } - - -/** -Second phase construction. -*/ -void CObexUsbConnector::ConstructL() - { - LOG_FUNC - - OpenUsbL(0); - - FLOG(_L("USB opened")); - - iHandler = CObexUsbHandler::NewL(iObexTransportInfo, *this, iUsb); - iCallback = new(ELeave) CAsyncCallBack(EPriorityHigh); - iStaller = CObexUsbStaller::NewL(iUsb, *this); - iHandler->Start(); - - BaseConstructL(); - } - - -/** -CObexUsbConnector destructor. Releases endpoint and closes USB object if we have an open connection. -*/ -CObexUsbConnector::~CObexUsbConnector() - { - LOG_FUNC - - delete iCallback; - delete iHandler; - delete iStaller; - - if (iUsb.Handle()) - { - iUsb.Close(); - } - } - - -/** -Attempt to open a client-type connection. -This will succeed if the USB host has already opened a connection to us -*/ -void CObexUsbConnector::ConnectL() - { - LOG_FUNC - - if (iMode == EServer) - { - // Already performed a server-type connect, so can't act as a - // client as well. - FLOG(_L(" -- In server mode, give up")); - LEAVEIFERRORL(KErrNotSupported); - } - - - FLOG(_L(" -- Not in server mode")); - - iMode = EClient; - if (iTransportLinkAvailable) - { - FLOG(_L(" -- Link available, set a callback")); - - TCallBack callback(LinkUp, this); - iCallback->Set(callback); - iCallback->CallBack(); - iConnectRequested = ETrue; - } - else - { - FLOG(_L(" -- No link available, set a callback")); - - TCallBack callback(NoDevice, this); - iCallback->Set(callback); - iCallback->CallBack(); - } - } - - -/* -@param aConn A pointer to a connector object. Will be cast to CObexUsbConnector - -@return KErrNone -*/ -TInt CObexUsbConnector::LinkUp(TAny* aConn) - { - FLOG(_L("CObexUsbConnector::LinkUp")); - - reinterpret_cast(aConn)->SignalUp(); - return KErrNone; - } - - -/* -@param aConn A pointer to a connector object. Will be cast to CObexUsbConnector - -@return KErrNone -*/ -TInt CObexUsbConnector::NoDevice(TAny* aConn) - { - FLOG(_L("CObexUsbConnector::NoDevice")); - - reinterpret_cast(aConn)->SignalDown(KErrIrObexClientPeerDoesNotHaveObex); - return KErrNone; - } - - -/** -Cancel an active connection attempt. This is unlikely to succeed, as a client -connection over USB will complete almost immediately. -*/ -void CObexUsbConnector::CancelConnect() - { - LOG_FUNC - - if (iMode == EClient) - { - iCallback->Cancel(); - } - - iConnectRequested = EFalse; - } - - -/** -Start listening for a connection to us. -*/ -void CObexUsbConnector::AcceptL() - { - LOG_FUNC - - if (iMode == EClient) - { - // Already carried out a client side connection. Therefore we - // can't be a server as well. - FLOG(_L(" -- In client mode, give up")); - - LEAVEIFERRORL(KErrNotSupported); - } - - FLOG(_L(" -- Not in client mode")); - - iMode = EServer; - if (iTransportLinkAvailable) - { - FLOG(_L(" -- Transport link currently available, set a callback")); - - TCallBack callback(LinkUp, this); - iCallback->Set(callback); - iCallback->CallBack(); - } - else - { - FLOG(_L(" -- No link available, wait for one")); - - iWaitingForLink = ETrue; - } - } - -/** -Stop listening for connections. -*/ -void CObexUsbConnector::CancelAccept() - { - LOG_FUNC - - if (iMode == EServer) - { - iWaitingForLink = EFalse; - iCallback->Cancel(); - } - } - - -/** -Called to indicate transport layer has come up. -*/ -void CObexUsbConnector::TransportUp() - { - LOG_FUNC - - SetTransportPacketSize(); - - iTransportLinkAvailable = ETrue; - - if ((iMode == EServer) && (iWaitingForLink)) - { - FLOG(_L(" -- Signalling link available")); - - iWaitingForLink = EFalse; - SignalUp(); - } - } - -/** -Called to indicate transport layer has gone down. - -@param aErr Any error code associated with disconnection. Defaults to KErrDisconnected. -*/ -void CObexUsbConnector::TransportDown(TInt aErr) - { - LOG_FUNC - - ResetTransportPacketSize(); - - iStaller->Cancel(); - - iTransportLinkAvailable = EFalse; - - if (iMode == EServer) - { - FLOG(_L(" -- In server mode, signal link down")); - - SignalDown(aErr); - } - else - { - FLOG(_L(" -- In client mode")); - - // Client or default client state - if (iConnectRequested) - { - FLOG(_L(" -- Outstanding client connection. Signal link down")); - - iConnectRequested = EFalse; - SignalDown(aErr); - } - } - } - -/** -Signals to the transport controller that the transport is up -*/ -void CObexUsbConnector::SignalUp() - { - LOG_FUNC - - // Indicate transport now up - TObexConnectionInfo sockinfo; - sockinfo.iMaxRecvSize = 0; // set these to zero as we can't find them out - sockinfo.iMaxSendSize = 0; // and they are not used - sockinfo.iSocketType = TObexConnectionInfo::EUsbStream; - Observer().TransportUp(sockinfo); - } - - -/** -Signals (with an error code) to the transport controller that the transport has gone down -*/ -void CObexUsbConnector::SignalDown(TInt aErr) - { - FLOG(_L("CObexUsbConnector::SignalDown")); - - Observer().Error(aErr); - } - - -/** -The Obex server running over USB is not able to bring the transport -down itself. It will only delete the transport object when an error -has occurred (such as the link being brought down) and hence the -transport is no longer valid. - -@return ETrue -*/ -TBool CObexUsbConnector::BringTransportDown() -{ - // This cancel function needs to be called here because it - // doesn't get called anywhere else. Bluetooth and IrDA rely - // on the socket shutdown to cancel the accept. - CancelAccept(); - return ETrue; -} - - -/** -Return the transport layer object for use by USB transport objects - -@return Pointer to the USB transport layer object -*/ -RDevUsbcClient* CObexUsbConnector::TransportObject() - { - return &iUsb; - } - - -/** -Sets a bus stall condition on the IN endpoint. This will cause the USB -host to initiate a CLEAR_FEATURE sequence, which notifies the server that the -Obex link has been reset (equivalent to dropping the Obex level connection) -*/ -void CObexUsbConnector::SignalTransportError() - { - LOG_FUNC - - iStaller->Start(); - iTransportLinkAvailable = EFalse; - iConnectRequested = EFalse; - } - - -/** -Stall cleared => transport available. -This upcall has been separated from the TransportUp upcall for two -reasons---it's called from a different class and it happens when an -error condition has been cleared. Currently it has no special -meaning, but this could change in future. -*/ -void CObexUsbConnector::StallCleared() - { - LOG_FUNC - - TransportUp(); - } - - -/** -Opens USB and prepares it for use. - -@param aUnit According to the RDevUsbcClient documentation, this should be 0. -*/ -void CObexUsbConnector::OpenUsbL(TInt aUnit) - { - LOG1(_L("CObexUsbConnector::OpenUsbL called for unit=%d"), aUnit); - - // Load ldd - TInt err = User::LoadLogicalDevice(KUsbLddName); - - if (err != KErrNone && err != KErrAlreadyExists) - { - LEAVEIFERRORL(err); - } - - // Open the requested unit and initialise local state - LEAVEIFERRORL(iUsb.Open(aUnit)); - } - - -void CObexUsbConnector::ResetTransportPacketSize() - { - iPacketSize = 0; - } - - -void CObexUsbConnector::SetTransportPacketSize() - { - if (iUsb.CurrentlyUsingHighSpeed()) - { - iPacketSize = KMaxPacketTypeBulkHS; - } - else - { - iPacketSize = KMaxPacketTypeBulkFS; - } - } - - -TInt CObexUsbConnector::GetTransportPacketSize() - { - return iPacketSize; - } - - -// - -/** -Constructs a CObexUsbHandler object - -@param aUsbTransportInfo Reference to a TObexTransportInfo object. Will be cast to TObexUsbTransportInfo. -@param aOwner Reference to a MObexUsbConnector that owns this handler -@param aUsb Reference to a RDevUsbcClient object. - -@return A new CObexUsbHandler object -*/ -CObexUsbHandler* CObexUsbHandler::NewL(TObexUsbTransportInfo& aUsbTransportInfo, - MObexUsbConnector& aOwner, - RDevUsbcClient& aUsb) - { - FLOG(_L("CObexUsbHandler::NewL")); - - CObexUsbHandler* self = new (ELeave) CObexUsbHandler(aUsbTransportInfo, aOwner, aUsb); - CleanupStack::PushL(self); - self->ConstructL(); - CleanupStack::Pop(self); - return self; - } - - -/** -CObexUsbHandler constructor. - -Note that the iObexTransportInfo may not be valid outside of the construction phases -The constructor copies out most of the information it needs into member variables -apart from the interface string descriptor, which is used from RegInterfacesL - -@param aUsbTransportInfo Reference to a TObexTransportInfo object. Will be cast to TObexUsbTransportInfo. -@param aOwner Reference to a MObexUsbConnector that owns this handler -@param aUsb Reference to a RDevUsbcClient object. -*/ -CObexUsbHandler::CObexUsbHandler(TObexUsbTransportInfo& aUsbTransportInfo, - MObexUsbConnector& aOwner, - RDevUsbcClient& aUsb) - : CActive(EPriorityStandard), iObexTransportInfo(aUsbTransportInfo), - iOwner(aOwner), iUsb(aUsb) - { - LOG_FUNC - - CActiveScheduler::Add(this); - - // Set interface performance configuration parameters - if (aUsbTransportInfo.iTransportName == KObexUsbProtocol) - // Default values if transport is normal USB - no extra bandwidth, no DMA - { - FLOG(_L("CObexUsbHandler - Using default USB protocol info")); - iBandwidthPriority = EUsbcBandwidthOUTDefault | EUsbcBandwidthINDefault; - iRequestDmaOnOutEndpoint = EFalse; - iRequestDmaOnInEndpoint = EFalse; - } - else if (aUsbTransportInfo.iTransportName == KObexUsbProtocolV2) - // If transport is extended USB take values from the protocol info - { - FLOG(_L("CObexUsbHandler - Using USB protocol extended info")); - TObexUsbV2TransportInfo& infoV2 = static_cast(aUsbTransportInfo); - iBandwidthPriority = infoV2.iBandwidthPriority; - iRequestDmaOnOutEndpoint = infoV2.iDmaOnOutEndpoint; - iRequestDmaOnInEndpoint = infoV2.iDmaOnInEndpoint; - } - else - { - //aUsbTransportInfo.iTransportName is used to load the correct plug-in, so if this code - //is being executed it must have contained one of the options above. Else something - //has gone badly wrong. - __ASSERT_DEBUG(false, PANIC(KPanicCat, EUnknownUsbTransport)); - } - - LOG3(_L("CObexUsbHandler - iBandwidthPriority 0x%X, iDmaOnOutEndpoint, %d iDmaOnInEndpoint %d"), - iBandwidthPriority, iRequestDmaOnOutEndpoint, iRequestDmaOnInEndpoint); - } - - -/** -Second phase construction. -*/ -void CObexUsbHandler::ConstructL() - { - - // Check bandwidth priority to make sure it makes sense - // Reasoning is that the bitwise OR of the maximum values of IN and OUT priorities - // covers all the bits that can be set in iBandwidthPriority so, using this as a mask, - // anything set outside of this indicates that iBandwidthPriority is corrupt - if ( ( iBandwidthPriority & ~( EUsbcBandwidthOUTMaximum | EUsbcBandwidthINMaximum ) ) != 0 ) - { - LEAVEIFERRORL(KErrArgument); - } - - FLOG(_L("About to open USB comms interface connection")); - - LEAVEIFERRORL(iUsbComms.Open(0)); - - FLOG(_L("Registering interfaces")); - - RegInterfacesL(); - } - - -/** -CObexUsbHandler destructor. -*/ -CObexUsbHandler::~CObexUsbHandler() - { - LOG_FUNC - Cancel(); - - // Must release interfaces from highest alternate setting downwards - if (iUsb.Handle()) - { -#ifndef NO_ALTERNATE_USB_INTERFACE_SUPPORT - iUsb.ReleaseInterface(1 /*alternate setting*/); -#endif - iUsb.ReleaseInterface(0 /*alternate setting*/); - } - - if (iUsbComms.Handle()) - { - iUsbComms.ReleaseInterface(0 /*alternate setting*/); - } - - iUsbComms.Close(); - } - - -/** -Standard active object error function. - -@return KErrNone because currently nothing should cause this to be called. -*/ -TInt CObexUsbHandler::RunError(TInt /*aError*/) - { - return KErrNone; - } - - -/** -This function will be called upon a change in the state of the device -(as set up in AcceptL). -*/ -void CObexUsbHandler::RunL() - { - LOG1(_L("CObexUsbHandler::RunL called state=0x%X"), iUsbState); - - if (iStatus != KErrNone) - { - LOG1(_L("CObexUsbHandler::RunL() - Error = %d"),iStatus.Int()); - - iTransportUp = EFalse; - iOwner.TransportDown(iStatus.Int()); - return; - } - - // Check whether the alternate setting to use or the device state has changed. - // We have to check the device state to handle the unplugging of the cable. We can't - // rely on the always-outstanding read to complete with an error, because the driver - // doesn't have a well-defined error code for this. - - if (iUsbState & KUsbAlternateSetting) - { - iUsbState &= ~KUsbAlternateSetting; - - LOG1(_L("switched to alternate setting %d"), iUsbState); - - if (iUsbState == KObexAlt0) - { - // alternate setting 0 - function inactive - if (iTransportUp) - { - FLOG(_L("CObexUsbHandler::RunL - transport layer going down...")); - - iTransportUp = EFalse; - iOwner.TransportDown(); - } - } - else if (iUsbState == KObexAlt1) - { - // alternate setting 1 - function active - if (!iTransportUp) - { - FLOG(_L("CObexUsbHandler::RunL - transport layer coming up...")); - - // Now the transport is selected, DMA can be allocated to the endpoints, if required - AllocateDma(); - - iTransportUp = ETrue; - - iOwner.TransportUp(); - } - } - else - { - FLOG(_L("WARNING: unknown setting!")); - } - } - else - { - TUsbcDeviceState deviceState = static_cast(iUsbState); - - switch(deviceState) - { - case EUsbcDeviceStateUndefined: - case EUsbcDeviceStateAttached: - case EUsbcDeviceStatePowered: - case EUsbcDeviceStateDefault: - case EUsbcDeviceStateAddress: -#ifdef ERRONEOUS_SUSPEND_INDICATIONS - // On Lubbock, we sometimes get "suspended" when the cable is unplugged. - case EUsbcDeviceStateSuspended: -#endif // ERRONEOUS_SUSPEND_INDICATIONS - if (iTransportUp) - { - FLOG(_L("CObexUsbHandler::RunL - transport layer going down...")); - - iTransportUp = EFalse; - iOwner.TransportDown(); - } - break; - -#ifndef ERRONEOUS_SUSPEND_INDICATIONS - case EUsbcDeviceStateSuspended: - break; -#endif // !ERRONEOUS_SUSPEND_INDICATIONS - - case EUsbcDeviceStateConfigured: - // Normally, we don't do anything here, because the transport only goes up when - // we actually receive the alternate interface change. -#ifdef NO_ALTERNATE_USB_INTERFACE_SUPPORT - if (!iTransportUp) - { - FLOG(_L("Device now configured: transport layer coming up...")); - - iTransportUp = ETrue; - - // DMA can be allocated to the endpoints, if required - // This has to be done here for no alternate interface devices - // as they will not receive interface change notification - AllocateDma(); - - iOwner.TransportUp(); - } -#endif // NO_ALTERNATE_USB_INTERFACE_SUPPORT - break; - - default: - __ASSERT_DEBUG(false, PANIC(KPanicCat, EUnknownUsbState)); - break; - } - } - - // Await further notification of a state change. We may have called Error(), which - // would already have set this notification request. - if (!IsActive()) - { - iUsb.AlternateDeviceStatusNotify(iStatus, iUsbState); - SetActive(); - } - - FLOG(_L("CObexUsbHandler::RunL finished")); - } - - -/** -Standard active object cancellation function. -*/ -void CObexUsbHandler::DoCancel() - { - LOG_FUNC - - iUsb.AlternateDeviceStatusNotifyCancel(); - } - - -/** -Registers the required comms and data interfaces. -*/ -void CObexUsbHandler::RegInterfacesL() - { - LOG_FUNC - - // Setup a CDC Communication Class interface - TUsbcInterfaceInfoBuf ifc; - - // Extract the interface string from the transport info structure we were - // passed on construction. This isn't const because the SetInterface API - // requires it not to be. - // This is the only point where iObexTransportInfo is used directly - // Do not use iObexTransportInfo outside of construction phases - TPtrC string(iObexTransportInfo.iInterfaceStringDescriptor); - - LOG1(_L("Using interface string \"%S\""), &string); - - ifc().iString = &string; - ifc().iClass.iClassNum = KObexClassNumber; - ifc().iClass.iSubClassNum = KObexSubClassNumber; - ifc().iClass.iProtocolNum = KObexProtocolNumber; - ifc().iTotalEndpointsUsed = 0; - - // Indicate that this interface does not expect any control transfers - // from EP0. - ifc().iFeatureWord |= KUsbcInterfaceInfo_NoEp0RequestsPlease; - - FLOG(_L("CObexUsbListeningConnector::RegInterfacesL - setting comms interface")); - - TInt err = iUsbComms.SetInterface(0, ifc); - - if (err != KErrNone) - { - LOG1(_L("SetInterface failed with error %d"), err); - LEAVEIFERRORL(err); - } - - // Get the interface number for later - TInt intDescSize; - err = iUsbComms.GetInterfaceDescriptorSize(0,intDescSize); - if(err != KErrNone) - { - LOG1(_L("Failed to get interface descriptor size. Err = %d"),err); - intDescSize = KObexDefaultInterfaceDescriptorLength; //Default is 100 - } - HBufC8* interfaceDescriptor; - interfaceDescriptor = HBufC8::NewLC(intDescSize); - TPtr8 pIntDesc = interfaceDescriptor->Des(); - iUsbComms.GetInterfaceDescriptor(0, pIntDesc); - TUint8 obexIntNo = interfaceDescriptor->Ptr()[2]; - CleanupStack::PopAndDestroy(); - - TBuf8 desc; - - // Comms Class Header Functional Descriptor - - desc.Append(KObexFunctionalDescriptorLength); - desc.Append(KUsbDescType_CS_Interface); - desc.Append(KHeaderFunctionalDescriptor); - desc.Append(KCdcVersionNumber[0]); - desc.Append(KCdcVersionNumber[1]); - - // Obex Functional Descriptor - - desc.Append(KObexFunctionalDescriptorLength); - desc.Append(KUsbDescType_CS_Interface); - desc.Append(KObexFunctionalDescriptor); - desc.Append(KWmcdcVersionNumber[0]); - desc.Append(KWmcdcVersionNumber[1]); - - // Union Functional Descriptor - - desc.Append(KObexFunctionalDescriptorLength); - desc.Append(KUsbDescType_CS_Interface); - desc.Append(KUnionFunctionalDescriptor); - desc.Append(obexIntNo); - TInt dataInt = obexIntNo + 1; - desc.Append(static_cast(dataInt)); - - err = iUsbComms.SetCSInterfaceDescriptorBlock(0, desc); - if (err != KErrNone) - { - LOG1(_L("SetCSInterfaceDescriptorBlock failed with error %d"), err); - LEAVEIFERRORL(err); - } - - // Setup CDC Data Class interfaces - - // Only set the "function inactive" interface (alternate setting 0) - // if the device can support alternate interfaces -#ifndef NO_ALTERNATE_USB_INTERFACE_SUPPORT - TUsbcInterfaceInfoBuf dataifc; - - dataifc().iString = NULL; - dataifc().iClass.iClassNum = KObexDataClass; - dataifc().iClass.iSubClassNum = KObexDataSubClass; - dataifc().iClass.iProtocolNum = 0; - dataifc().iTotalEndpointsUsed = 0; - - // Indicate that this interface does not expect any control transfers - // from EP0. - dataifc().iFeatureWord |= KUsbcInterfaceInfo_NoEp0RequestsPlease; - - FLOG(_L("Setting data class interface (alt setting 0")); - - err = iUsb.SetInterface(0 /*alternate setting*/, dataifc, iBandwidthPriority); - if (err != KErrNone) - { - LOG1(_L("Cannot set data interface (alternate setting 0): error %d"), err); - LEAVEIFERRORL(err); - } - - // If anything below this point leaves, make sure this alternate setting - // gets released. - CleanupStack::PushL(TCleanupItem(CleanupReleaseInterface0, &iUsb)); -#endif // NO_ALTERNATE_USB_INTERFACE_SUPPORT - - // Check the device has enough endpoints for the "function active" data interface - TUsbDeviceCaps dCaps; - LEAVEIFERRORL(iUsb.DeviceCaps(dCaps)); - - TInt n = dCaps().iTotalEndpoints; - if (n < KObexMinNumEndpoints) - { - LEAVEIFERRORL(KErrOverflow); - } - - // Use the hardware's HS capability to determine maximum bulk transfer packet size - TInt maxPacketSize = (dCaps().iHighSpeed) ? KMaxPacketTypeBulkHS : KMaxPacketTypeBulkFS; - - - // Get information on the available endpoints from the driver - TUsbcEndpointData data[KUsbcMaxEndpoints]; - TPtr8 dataptr(REINTERPRET_CAST(TUint8*, data), sizeof(data), sizeof(data)); - LEAVEIFERRORL(iUsb.EndpointCaps(dataptr)); - - // Check to see if there are suitably capable IN and OUT endpoints available - // and fill dataifc2 structure accordingly. - // - // NOTE: The order the iEndpointData array is filled matches the order used for the - // virtual endpoint numbers KTransmitEndpoint and KReceiveEndpoint - so change with caution! - // - // The virtual endpoint numbers are 1-based, whereas the iEndpointData array is 0 based - // hence the subtraction in the array indices - // - // NOTE: IN and OUT refer to the host so in this case: - // IN => device to PC = KTransmitEndpoint - // OUT => PC to device = KReceiveEndpoint - TUsbcInterfaceInfoBuf dataifc2; - TBool foundIn = EFalse; - TBool foundOut = EFalse; - for (TInt i = 0; !(foundIn && foundOut) && i < n; i++) - { - const TUsbcEndpointCaps* caps = &data[i].iCaps; - if (data[i].iInUse) - { - continue; - } - - const TUint KBulkInFlags = KUsbEpTypeBulk | KUsbEpDirIn; - const TUint KBulkOutFlags = KUsbEpTypeBulk | KUsbEpDirOut; - - if (!foundIn && (caps->iTypesAndDir & KBulkInFlags) == KBulkInFlags) - { - dataifc2().iEndpointData[KTransmitEndpoint - 1].iType = KUsbEpTypeBulk; - dataifc2().iEndpointData[KTransmitEndpoint - 1].iDir = KUsbEpDirIn; - TInt maxSize = caps->MaxPacketSize(); - if (maxSize > maxPacketSize) - { - maxSize = maxPacketSize; - } - dataifc2().iEndpointData[KTransmitEndpoint - 1].iSize = maxSize; - - // Allocate dma if requested and the device support resource allocation scheme version 2 - // for resource allocation scheme version1, refer to AllocateDma() - if (iRequestDmaOnInEndpoint && - ((dCaps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) != 0)) - { - dataifc2().iEndpointData[KTransmitEndpoint - 1].iFeatureWord1 |= KUsbcEndpointInfoFeatureWord1_DMA; - } - - foundIn = ETrue; - } - else if (!foundOut && (caps->iTypesAndDir & KBulkOutFlags) == KBulkOutFlags) - { - dataifc2().iEndpointData[KReceiveEndpoint - 1].iType = KUsbEpTypeBulk; - dataifc2().iEndpointData[KReceiveEndpoint - 1].iDir = KUsbEpDirOut; - TInt maxSize = caps->MaxPacketSize(); - if (maxSize > maxPacketSize) - { - maxSize = maxPacketSize; - } - dataifc2().iEndpointData[KReceiveEndpoint - 1].iSize = maxSize; - - //Allocate dma here if requested and the device support resource allocation scheme version 2 - // for resource allocation scheme version1, refer to AllocateDma() - if (iRequestDmaOnOutEndpoint && - ((dCaps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) != 0)) - { - dataifc2().iEndpointData[KReceiveEndpoint - 1].iFeatureWord1 |= KUsbcEndpointInfoFeatureWord1_DMA; - } - - foundOut = ETrue; - } - } - - if (!(foundIn && foundOut)) - { - LEAVEIFERRORL(KErrHardwareNotAvailable); - } - - // Set the active interface. - dataifc2().iString = NULL; - dataifc2().iClass.iClassNum = KObexDataClass; - dataifc2().iClass.iSubClassNum = KObexDataSubClass; - dataifc2().iClass.iProtocolNum = 0; - dataifc2().iTotalEndpointsUsed = KObexTotalEndpoints; - - // Indicate that this interface does not expect any control transfers - // from EP0. - dataifc2().iFeatureWord |= KUsbcInterfaceInfo_NoEp0RequestsPlease; - -#ifdef NO_ALTERNATE_USB_INTERFACE_SUPPORT - // For devices that don't suport alternate interfaces, have to place the "function active" - // interface at alternate setting 0, although the CDC specification says if should be alternate setting 1 - FLOG(_L("Setting data class interface (no alternate interface support)")); - - err = iUsb.SetInterface(0 /*alternate setting*/, dataifc2, iBandwidthPriority); - - if (err != KErrNone) - { - //FTRACE(FPrint(_L("Cannot set data interface (no alternate interface support): error %d"), err)); - LOG1(_L("Cannot set data interface (no alternate interface support): error %d"), err); - LEAVEIFERRORL(err); - } -#else - FLOG(_L("Setting data class interface (alternate setting 1)")); - - err = iUsb.SetInterface(1 /*alternate setting*/, dataifc2, iBandwidthPriority); - - if (err != KErrNone) - { - //FTRACE(FPrint(_L("Cannot set data interface (alternate setting 1): error %d"), err)); - LOG1(_L("Cannot set data interface (alternate setting 1): error %d"), err); - LEAVEIFERRORL(err); - } - - CleanupStack::Pop(); // ReleaseInterface0 -#endif - - FLOG(_L("CObexUsbHandler::RegInterfacesL - finished.")); - } - - -/** -Utility function which releases the first alternate setting of the specified -interface. Used when setting up Obex interfaces. - -@param aInterface The interface to release -*/ -void CObexUsbHandler::CleanupReleaseInterface0(TAny* aInterface) - { - reinterpret_cast(aInterface)->ReleaseInterface(0 /*alternate setting*/); - } - - -/** -Accept an incoming connection. -*/ -void CObexUsbHandler::Start() - { - LOG_FUNC - - // Await notification of a state change (this is like waiting for a connect...). - iUsb.AlternateDeviceStatusNotify(iStatus, iUsbState); - SetActive(); - } - - -/** -Utility function to allocate DMA to the bulk endpoints - if they have been requested -This function is called during a connect, once the device is configured, -so if the allocations fail it wont complain in release builds but debug builds will -panic with either EDmaAllocationFailedEndpointIn or EDmaAllocationFailedEndpointOut. -*/ -void CObexUsbHandler::AllocateDma() - { - LOG_FUNC - - TUsbDeviceCaps dCaps; - iUsb.DeviceCaps(dCaps); - if ((dCaps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) != 0) - { - // for resource allocation version2, refer to CObexUsbHandler::RegInterfacesL() - return; - } - - if (iRequestDmaOnInEndpoint) - { - TInt err = iUsb.AllocateEndpointResource(KTransmitEndpoint, EUsbcEndpointResourceDMA); - // The following log message is checked for in the test code - change with caution! - LOG1(_L("IN Endpoint DMA resource allocation result %d"), err); - (void)err; // to stop compilers complaining about unused variables - } - - if (iRequestDmaOnOutEndpoint) - { - TInt err = iUsb.AllocateEndpointResource(KReceiveEndpoint, EUsbcEndpointResourceDMA); - // The following log message is checked for in the test code - change with caution! - LOG1(_L("OUT Endpoint DMA resource allocation result %d"), err); - (void)err; // to stop compilers complaining about unused variables - } - } - - -// - -/** -Constructs a CObexUsbStaller object - -@param aUsb Reference to a RDevUsbcClient object. -@param aOwner Reference to a MObexUsbConnector that owns this handler - -@return A new CObexUsbStaller object -*/ -CObexUsbStaller* CObexUsbStaller::NewL(RDevUsbcClient& aUsb, MObexUsbConnector& aOwner) - { - CObexUsbStaller* self = new(ELeave) CObexUsbStaller(aUsb, aOwner); - return self; - } - -/** -CObexUsbStaller constructor. - -@param aUsb Reference to a RDevUsbcClient object. -@param aOwner Reference to a MObexUsbConnector that owns this handler -*/ -CObexUsbStaller::CObexUsbStaller(RDevUsbcClient& aUsb, MObexUsbConnector& aOwner) - : CActive(EPriorityStandard), iUsb(aUsb), iOwner(aOwner) - { - CActiveScheduler::Add(this); - } - - -/** -CObexUsbStaller destructor. -*/ -CObexUsbStaller::~CObexUsbStaller() - { - Cancel(); - } - - -/** -Starts the staller -*/ -void CObexUsbStaller::Start() - { - LOG_FUNC - - if (!IsActive()) - { - FLOG(_L("Halting transmit endpoint...")); - iUsb.HaltEndpoint(KTransmitEndpoint); - iUsb.EndpointStatusNotify(iStatus, iEndpointStatus); - SetActive(); - } - } - - -/** -Called when the transmit endpoint has changed state -*/ -void CObexUsbStaller::RunL() - { - LOG_FUNC - - TEndpointState endpointState; - iUsb.EndpointStatus(KTransmitEndpoint, endpointState); -#ifdef __FLOG_ACTIVE - switch (endpointState) - { - case EEndpointStateNotStalled: - { - FLOG(_L("Receive endpoint not stalled")); - break; - } - case EEndpointStateStalled: - { - FLOG(_L("Receive endpoint stalled")); - break; - } - case EEndpointStateUnknown: - { - FLOG(_L("Receive endpoint unknown state")); - break; - } - } -#endif - if (endpointState == EEndpointStateNotStalled) - { - LOG1(_L("CObexUsbStallWatcher::RunL -- endpoint no longer stalled (0x%08x)"), iEndpointStatus); - iOwner.StallCleared(); - } - else - { - LOG1(_L("CObexUsbStallWatcher::RunL -- endpoint still stalled (0x%08x)"), iEndpointStatus); - iUsb.EndpointStatusNotify(iStatus, iEndpointStatus); - SetActive(); - } - } - - -/** -Standard active object error function. - -@return KErrNone because currently nothing should cause this to be called. -*/ -TInt CObexUsbStaller::RunError(TInt /*aError*/) - { - LOG_FUNC - - return KErrNone; - } - - -/** -Standard active object cancellation function. -*/ -void CObexUsbStaller::DoCancel() - { - FLOG(_L("CObexUsbStaller -- Cancelling status notification")); - iUsb.EndpointStatusNotifyCancel(); - } -