diff -r 000000000000 -r c9bc50fca66e usbmgmt/usbmgr/device/classdrivers/acm/classimplementation/ecacm/src/CdcControlInterface.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usbmgmt/usbmgr/device/classdrivers/acm/classimplementation/ecacm/src/CdcControlInterface.cpp Tue Feb 02 02:02:59 2010 +0200 @@ -0,0 +1,509 @@ +/* +* 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 +#include +#include "CdcControlInterface.h" +#include "CdcControlInterfaceReader.h" +#include "ClassDescriptor.h" +#include "CdcAcmClass.h" +#include "AcmPanic.h" +#include "AcmUtils.h" +#include + +#ifdef __FLOG_ACTIVE +_LIT8(KLogComponent, "ECACM"); +#endif + +CCdcControlInterface::CCdcControlInterface(const TUint8 aProtocolNum, const TDesC16& aIfcName) +/** + * Constructor using interface name. + * @param aProtocolNum Contains the Table 17 protocol number. + * @param aIfcName contains the interface name + */ + : CCdcInterfaceBase(aIfcName), + iSerialState(0xFFFF), + iProtocolNum(aProtocolNum) + { + } + +CCdcControlInterface* CCdcControlInterface::NewL(CCdcAcmClass& aParent, const TUint8 aProtocolNum, const TDesC16& aIfcName) +/** + * Create a new CCDCCommClass object and construct it using interface name + * This call will return an object with a valid USB configuration + * + * @param aParent Pointer to the Port using this object + * @param aProtocolNum contains the Table 17 protocol number. + * @param aIfcName Contains the interface name + * @return A pointer to the new object + */ + { + LOG_STATIC_FUNC_ENTRY + + LOGTEXT2(_L("\tControl Ifc Name = %S"), &aIfcName); + + CCdcControlInterface* self = new(ELeave) CCdcControlInterface(aProtocolNum, aIfcName); + CleanupStack::PushL(self); + self->ConstructL(aParent); + CLEANUPSTACK_POP(self); + return self; + } + +void CCdcControlInterface::ConstructL(CCdcAcmClass& aParent) +/** + * 2nd-phase construction. + * This call registers the object with the USB device driver + * + * @param aParent The ACM class. + */ + { + BaseConstructL(); + + iReader = CCdcControlInterfaceReader::NewL(aParent, iLdd); + + LOGTEXT2(_L8("\tcreated CdcControlInterface iProtocolNum = %d"), iProtocolNum); + } + +TInt CCdcControlInterface::SetUpInterface() +/** + * Set up the interface for use. This involves finding a "Interrupt IN" + * endpoint and, if found, configuring the interface. + */ + { + LOGTEXT(_L8(">>CCdcControlInterface::SetUpInterface")); + + TUsbDeviceCaps dCaps; + TInt ret = iLdd.DeviceCaps(dCaps); + LOGTEXT(_L8("\tchecking result of DeviceCaps")); + if ( ret ) + { + LOGTEXT2(_L8("<(dCaps().iTotalEndpoints); + LOGTEXT2(_L8("\tiTotalEndpoints = %d"), totalEndpoints); + if ( totalEndpoints < KRequiredNumberOfEndpoints ) + { + LOGTEXT2(_L8("<(data), sizeof(data), sizeof(data)); + ret = iLdd.EndpointCaps(dataptr); + LOGTEXT(_L8("\tchecking result of EndpointCaps")); + if ( ret ) + { + LOGTEXT2(_L8("<iTypesAndDir & (KUsbEpTypeInterrupt | KUsbEpDirIn)) == + (KUsbEpTypeInterrupt | KUsbEpDirIn)) + { + // EEndpoint1 is interrupt endpoint + ifc().iEndpointData[0].iType = KUsbEpTypeInterrupt; + ifc().iEndpointData[0].iDir = KUsbEpDirIn; + + //get the max packet size it can potentially support + //it's possible that it can support Isoch (1023) which is greater + //than max for Int at 64 + TInt maxSize = Min(caps->MaxPacketSize(), KMaxPacketTypeInterrupt); + + ifc().iEndpointData[0].iSize = maxSize; + + ifc().iEndpointData[0].iInterval = KPollInterval; + epFound = ETrue; + break; + } + } + LOGTEXT(_L8("\tchecking epFound")); + if ( !epFound ) + { + LOGTEXT2(_L8("< iBuffer; + }; + +TDes8& TUSBNotificationNetworkConnection::PackBuffer() +/** + * This function packs the TUSBNotificationSerialState class into a + * byte buffer with the correct byte alignment for transmission on + * the little-endian USB bus. + */ + { + iBuffer.SetLength(KUSBNotificationNetworkConnectionSize); + + iBuffer[0] = bmRequestType; + iBuffer[1] = bNotification; + iBuffer[2] = static_cast( wValue & 0x00ff); + iBuffer[3] = static_cast((wValue & 0xff00) >> 8); + iBuffer[4] = static_cast( wIndex & 0x00ff); + iBuffer[5] = static_cast((wIndex & 0xff00) >> 8); + iBuffer[6] = static_cast( wLength & 0x00ff); + iBuffer[7] = static_cast((wLength & 0xff00) >> 8); + + return iBuffer; + } + +TInt CCdcControlInterface::SendNetworkConnection(TBool aValue) +/** + * Sends a Network Connection message to the host. + * Note that this function has not been tested. It is included for + * completeness as it may need to be used in modem (DCE) mode. However, it is + * unclear how a C32 client would indicate to the CSY that a network + * connection had been established. + * + * @param aValue ETrue if Network Connected + * @return Error. + */ + { + LOGTEXT2(_L8(">>CCdcControlInterface::SendNetworkConnection aValue=%d"), + aValue); + + // form the message and prime it down to the interrupt handler + // (that is 'interrupt' in the USB sense) + + // Note that this does not need to be aware of endian-ness, this + // is taken care of in the PackBuffer() function. + TUSBNotificationNetworkConnection notification; + + notification.bmRequestType = 0xA1; + notification.bNotification = 0x00; // NETWORK_CONNECTION + notification.wValue = static_cast((aValue)?0x0001:0x0000); //1 - connected, 0 - disconnected + notification.wIndex = static_cast((aValue)?0x0001:0x0000); + notification.wLength = 0x00; + + TInt ret = WriteData(EEndpoint1, + notification.PackBuffer(), + notification.PackBuffer().Length()); + + LOGTEXT2(_L8("< iBuffer; + }; + +TDes8& TUSBNotificationSerialState::PackBuffer() +/** + * This function packs the TUSBNotificationSerialState class into a + * byte buffer with the correct byte alignment for transmission on + * the little-endian USB bus. + */ + { + iBuffer.SetLength(KUSBNotificationSerialStateSize); + + iBuffer[0] = bmRequestType; + iBuffer[1] = bNotification; + iBuffer[2] = static_cast( wValue & 0x00ff); + iBuffer[3] = static_cast((wValue & 0xff00) >> 8); + iBuffer[4] = static_cast( wIndex & 0x00ff); + iBuffer[5] = static_cast((wIndex & 0xff00) >> 8); + iBuffer[6] = static_cast( wLength & 0x00ff); + iBuffer[7] = static_cast((wLength & 0xff00) >> 8); + iBuffer[8] = static_cast( wData & 0x00ff); + iBuffer[9] = static_cast((wData & 0xff00) >> 8); + + return iBuffer; + } + +TInt CCdcControlInterface::SendSerialState(TBool aOverRun, + TBool aParity, + TBool aFraming, + TBool aRing, + TBool aBreak, + TBool aTxCarrier, + TBool aRxCarrier) +/** + * Sends a Serial State message to the host + * + * @param aOverRun True if data discarded due to overrun + * @param aParity True if a parity error has occured + * @param aFraming True if a framing error has occured + * @param aRing True if the device is Ringing + * @param aBreak True if the device is detecting a break condition + * @param aTxCarrier True if the transmit carrier is present + * @param aRxCarrier True if the receive carrier is present + * @return Error. + */ + { + LOG_FUNC + LOGTEXT2(_L8("\taOverRun=%d"), aOverRun); + LOGTEXT2(_L8("\taParity=%d"), aParity); + LOGTEXT2(_L8("\taFraming=%d"), aFraming); + LOGTEXT2(_L8("\taRing=%d"), aRing); + LOGTEXT2(_L8("\taBreak=%d"), aBreak); + LOGTEXT2(_L8("\taTxCarrier=%d"), aTxCarrier); + LOGTEXT2(_L8("\taRxCarrier=%d"), aRxCarrier); + + // First work out what might need to be sent by assembling the bits into + // the correct places. See CDC spec table 69 (UART state bitmap values). + TUint16 data = static_cast + ( + (aRxCarrier ) | + (aTxCarrier << 1) | + (aBreak << 2) | + (aRing << 3) | + (aFraming << 4) | + (aParity << 5) | + (aOverRun << 6) + ); + + // now check to see if this has created a different state than + // last time it was sent, if it is the same, don't bother to + // send it off. + if ( data == iSerialState ) + { + LOGTEXT(_L8("\tdata == iSerialState")); + return KErrNone; + } + + // state is different, store local to the class object ready for + // testing next time through + iSerialState = data; + + // now form the message and prime it down to the interrupt handler + // (that is 'interrupt' in the USB sense) + + // Note that this does not need to be aware of endian-ness, this + // is taken care of in the PackBuffer() function. + TUSBNotificationSerialState notification; + + notification.bmRequestType = 0xA1; + notification.bNotification = 0x20; // SERIAL_STATE + notification.wValue = 0x0000; + notification.wIndex = 0x0000; + notification.wLength = 0x0002; + notification.wData = data; + + TInt ret = WriteData( EEndpoint1, + notification.PackBuffer(), + notification.PackBuffer().Length()); + LOGTEXT2(_L8("\tWriteData = %d"), ret); + + return ret; + } + +TInt CCdcControlInterface::WriteData(TEndpointNumber aEndPoint, + TDes8& aDes, + TInt aLength) +/** + * + * + * @param aEndPoint + * @param aDes + * @param aLength + */ + { + LOG_FUNC + LOGTEXT2(_L8("\taEndpoint=%d"), aEndPoint); + + TInt ret; + RTimer timer; + ret = timer.CreateLocal(); + if ( ret ) + { + LOGTEXT2(_L8("\ttimer.CreateLocal = %d- returning"), ret); + return ret; + } + TRequestStatus status; + TRequestStatus timerStatus; + LOGTEXT(_L8("\tAttempting to write data to control interface")); + iLdd.Write(status, aEndPoint, aDes, aLength); + timer.After(timerStatus, KWriteDataTimeout); + User::WaitForRequest(status, timerStatus); + if ( timerStatus != KRequestPending ) + { + // Timeout occurred, silently ignore error condition. + // Assuming that the line has been disconnected + LOGTEXT(_L8("CCdcControlInterface::WriteData() - Timeout occurred")); + iLdd.WriteCancel(aEndPoint); + User::WaitForRequest(status); + ret = timerStatus.Int(); + } + else + { + LOGTEXT(_L8("CCdcControlInterface::WriteData() - Write completed")); + timer.Cancel(); + User::WaitForRequest(timerStatus); + ret = status.Int(); + } + + LOGTEXT2(_L8("\treturning %d"), ret); + return ret; + } + +// +// End of file