diff -r 000000000000 -r c9bc50fca66e usbmgmt/usbmgr/device/classdrivers/acm/classimplementation/ecacm/src/CdcControlInterfaceReader.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usbmgmt/usbmgr/device/classdrivers/acm/classimplementation/ecacm/src/CdcControlInterfaceReader.cpp Tue Feb 02 02:02:59 2010 +0200 @@ -0,0 +1,413 @@ +/* +* 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: +* +*/ + +#include +#include +#include "CdcControlInterfaceReader.h" +#include "AcmPanic.h" +#include "AcmUtils.h" +#include "CdcControlInterfaceRequestHandler.h" +#include "AcmConstants.h" +#include + +#ifdef __FLOG_ACTIVE +_LIT8(KLogComponent, "ECACM"); +#endif + +CCdcControlInterfaceReader::CCdcControlInterfaceReader( + MCdcCommsClassRequestHandler& aParent, + RDevUsbcClient& aLdd) +: CActive(KEcacmAOPriority), + iParent(aParent), + iLdd(aLdd) +/** + * Constructor. + * + * @param aParent Observer (ACM port) + * @param aLdd The USB LDD handle to be used. + */ + { + CActiveScheduler::Add(this); + ReadMessageHeader(); + } + +CCdcControlInterfaceReader::~CCdcControlInterfaceReader() +/** + * Destructor + */ + { + LOG_FUNC + + Cancel(); //Call CActive::Cancel() + } + +CCdcControlInterfaceReader* CCdcControlInterfaceReader::NewL( + MCdcCommsClassRequestHandler& aParent, + RDevUsbcClient& aLdd) +/** + * Create a new CCdcControlInterfaceReader object and start reading + * + * @param aParent Observer (ACM port) + * @param aLdd The USB LDD handle to be used. + */ + { + LOG_STATIC_FUNC_ENTRY + + CCdcControlInterfaceReader* self = new(ELeave) CCdcControlInterfaceReader( + aParent, + aLdd); + return self; + } + +void CCdcControlInterfaceReader::RunL() +/** + * This function will be called when a read completes. + */ + { + LOGTEXT2(_L8(">>CCdcControlInterfaceReader::RunL iStatus=%d"), iStatus.Int()); + HandleReadCompletion(iStatus.Int()); + LOGTEXT(_L8("<>CCdcControlInterfaceReader::HandleReadCompletion " + "aError=%d"), aError); + + if ( aError ) + { + ReadMessageHeader(); + LOGTEXT(_L8("<(iLdd.EndpointZeroRequestError()); + ReadMessageHeader(); + return; + } + + LOGTEXT2(_L8("\t- New read! Request 0x%x"), iRequestHeader.iRequest); + + if ( iRequestHeader.IsDataResponseRequired() ) + { + DecodeMessageDataWithResponseRequired(); + } + else if ( iRequestHeader.iLength == 0 ) + { + iMessageData.SetLength(0); + DecodeMessageData(); + } + else + { + ReadMessageData(iRequestHeader.iLength); + } + } + +void CCdcControlInterfaceReader::DecodeMessageDataWithResponseRequired() +/** + * Decode a message which requires data to be sent to the host in response. + */ + { + LOG_FUNC + + LOGTEXT2(_L8("\t- New read! Request 0x%x"), iRequestHeader.iRequest); + TBuf8 returnBuffer; + + switch ( iRequestHeader.iRequest ) + { + case KGetEncapsulated: + { + if ( iParent.HandleGetEncapResponse(returnBuffer) == KErrNone ) + { + // Write Back data here + // At least ack the packet or host will keep sending. If this + // fails, the host will ask again until we do successfully reply. + static_cast(iLdd.SendEp0StatusPacket()); + } + else + { + // Stall bus- unknown message. If this fails, there's nothing we + // can do. + static_cast(iLdd.EndpointZeroRequestError()); + } + } + break; + + case KGetCommFeature: + { + if ( iParent.HandleGetCommFeature(iRequestHeader.iValue, returnBuffer) + == KErrNone ) + { + TRequestStatus status; + iLdd.Write(status, EEndpoint0, + returnBuffer, + returnBuffer.Length(), + EFalse); + User::WaitForRequest(status); + // If this failed, the host will ask again until we do + // successfully reply. + } + else + { + // Stall bus- unknown message. If this fails, there's nothing we + // can do. + static_cast(iLdd.EndpointZeroRequestError()); + } + } + break; + + case KGetLineCoding: + { + if ( iParent.HandleGetLineCoding(returnBuffer) == KErrNone ) + { + TRequestStatus status; + iLdd.Write(status, EEndpoint0, + returnBuffer, + 7, + EFalse); + User::WaitForRequest(status); + } + else + { + // Stall bus- unknown message. If this fails, there's nothing we + // can do. + static_cast(iLdd.EndpointZeroRequestError()); + } + } + break; + + default: + { + LOGTEXT2(_L8("\t- request number not recognised (%d)"), + iRequestHeader.iRequest); + // Stall bus- unknown message. If this fails, there's nothing we can + // do. + static_cast(iLdd.EndpointZeroRequestError()); + } + break; + } + + ReadMessageHeader(); + } + +void CCdcControlInterfaceReader::DecodeMessageData() +/** + * Decode a message that does not require any data to be sent to the host in + * response. In all the requests here, the completion of the class-specific + * function is ack'ed by sending an endpoint zero status packet. The request + * can be nack'ed by signalling an endpoint zero request error. + */ + { + LOG_FUNC + + if ( iMessageData.Length() != iRequestHeader.iLength ) + { + LOGTEXT(_L8("\t- Data length is incorrect")); + ReadMessageHeader(); + return; + } + + LOGTEXT2(_L8("\tNew read! Request %d"), iRequestHeader.iRequest); + + switch ( iRequestHeader.iRequest ) + { + case KSendEncapsulated: + if(iParent.HandleSendEncapCommand(iMessageData) == KErrNone) + { + // If this fails, the host will send again. + static_cast(iLdd.SendEp0StatusPacket()); + } + else + { + // Stall bus- unknown message. If this fails, there's nothing we + // can do. + static_cast(iLdd.EndpointZeroRequestError()); + } + break; + case KSetCommFeature: + if(iParent.HandleSetCommFeature(iRequestHeader.iValue,iMessageData) + == KErrNone) + { + // If this fails, the host will send again. + static_cast(iLdd.SendEp0StatusPacket()); + } + else + { + // Stall bus- unknown message. If this fails, there's nothing we + // can do. + static_cast(iLdd.EndpointZeroRequestError()); + } + break; + case KClearCommFeature: + if(iParent.HandleClearCommFeature(iRequestHeader.iValue) == KErrNone) + { + // If this fails, the host will send again. + static_cast(iLdd.SendEp0StatusPacket()); + } + else + { + // Stall bus- unknown message. If this fails, there's nothing we + // can do. + static_cast(iLdd.EndpointZeroRequestError()); + } + break; + case KSetLineCoding: + if(iParent.HandleSetLineCoding(iMessageData) == KErrNone) + { + // If this fails, the host will send again. + static_cast(iLdd.SendEp0StatusPacket()); + } + else + { + // Stall bus- unknown message. If this fails, there's nothing we + // can do. + static_cast(iLdd.EndpointZeroRequestError()); + } + break; + case KSetControlLineState: + if(iParent.HandleSetControlLineState( + // See CDC spec table 69 (UART state bitmap values)... + (iRequestHeader.iValue & 0x0002) ? ETrue : EFalse, // bTxCarrier + (iRequestHeader.iValue & 0x0001) ? ETrue : EFalse) // bRxCarrier + == KErrNone) + { + // If this fails, the host will send again. + static_cast(iLdd.SendEp0StatusPacket()); + } + else + { + // Stall bus- unknown message. If this fails, there's nothing we + // can do. + static_cast(iLdd.EndpointZeroRequestError()); + } + break; + case KSendBreak: + // The time value sent from the host is in milliseconds. + if(iParent.HandleSendBreak(iRequestHeader.iValue) == KErrNone) + { + // If this fails, the host will send again. + static_cast(iLdd.SendEp0StatusPacket()); + } + else + { + // Stall bus- unknown message. If this fails, there's nothing we + // can do. + static_cast(iLdd.EndpointZeroRequestError()); + } + break; + default: + LOGTEXT2(_L8("\t***request number not recognised (%d)"), + iRequestHeader.iRequest); + // Stall bus- unknown message. If this fails, there's nothing we can + // do. + static_cast(iLdd.EndpointZeroRequestError()); + break; + } + + ReadMessageHeader(); + } + +void CCdcControlInterfaceReader::ReadMessageHeader() +/** + * Post a read request and set the state to indicate that we're waiting for a + * message header. + */ + { + LOG_FUNC + + iState = EWaitingForHeader; + + iLdd.ReadPacket(iStatus, EEndpoint0, iMessageHeader, KUsbRequestHdrSize); + SetActive(); + } + +void CCdcControlInterfaceReader::ReadMessageData(TUint aLength) +/** + * Post a read request and set the state to indicate that we're waiting for + * some message data. + * + * @param aLength Length of data to read. + */ + { + LOG_FUNC + + LOGTEXT2(_L8("\tqueuing read, length = %d"),aLength); + + iState = EWaitingForData; + + iLdd.Read(iStatus, EEndpoint0, iMessageData, static_cast(aLength)); + SetActive(); + } + +// +// End of file