diff -r 84c26be382f0 -r bbdce6bffaad usbdrv/peripheral/pdd/pil/inc/controltransfersm.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usbdrv/peripheral/pdd/pil/inc/controltransfersm.h Wed Oct 20 12:04:53 2010 +0800 @@ -0,0 +1,292 @@ +/* +* Copyright (c) 2010 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: +* +*/ + +// Control transfer state machine. +// Generally used for Endpoint zero. + +#ifndef CONTROLTRANSFER_SM_H +#define CONTROLTRANSFER_SM_H + +#include // General types definition +#include // Peripheral SHAI Header +#include // Usb const + +#include + +// Forward class declaration +class TControlStageSm; + +// Refer usb setup packet definition +const TUint8 KUSB_SETUPKT_DATA_DIR_MASK = 0x80; +const TUint8 KUSB_SETUPKT_REQ_TYPE_VENDOR_MASK = 0x40; +const TUint8 KUSB_SETUPKT_REQ_TYPE_CLASS_MASK = 0x20; +const TUint8 KUSB_SETUPKT_REQ_TYPE_STANDARD_MASK = 0x60; + +/** + * TUsbPeripheralSetup + * @brief A USB Setup packet's structure. + * @see ProcessSetConfiguration(const TUsbPeripheralSetup&) + * + */ +struct TUsbcSetup + { + /** bmRequestType */ + TUint8 iRequestType; + + /** bRequest */ + TUint8 iRequest; + + /** wValue */ + TUint16 iValue; + + /** wIndex */ + TUint16 iIndex; + + /** wLength */ + TUint16 iLength; + }; + +/** Valid request catogary that a client(PIL or App) can request + * via this state machine + */ +enum TControlTransferRequest + { + // Write . Data IN . From Device to Host + TControlTransferRequestWrite, + + // Read . Data OUT . From Host to Device + TControlTransferRequestRead, + + // Zero bytes status, Write . Status IN + // Status from Device to Host + TControlTransferRequestSendStatus + + // Status from Host to device will be ignored + }; + +// Data dir as spec defined +enum TUsbDataDir + { + EUsbDataDir_ToDevice, + EUsbDataDir_ToHost + }; + +// Request catogary from Host to device as spec defined +enum TUsbRequestType + { + EUsbStandardRequest, + EUsbClassRequest, + EUsbVendorRequest + }; + +// Target of the request(from host to device) +enum TUsbRequestTarget + { + EUsbRequestTargetToDevice, + EUsbRequestTargetToInterface, + EUsbRequestTargetToEndpoint, + EUsbRequestTargetToElement + }; + +typedef TUint8 TUsbRequest; + +/** Helper function which can parse a setup packet + * and explain it as what's spec required + */ +NONSHARABLE_CLASS(TSetupPkgParser) + { + public: + TSetupPkgParser(); + // Set the setup buffer + // this class does't hold this buffer, it do a bitwise copy + // assumed length is 8 bytes + static void Set(const TUint8* aSetupBuf); + + // Get what the next stage following the received setup + // packet + static UsbShai::TControlStage NextStage(); + + static TUsbDataDir DataDirection(); + + static TBool IsVendorRequest(); + static TBool IsClassRequest(); + static TBool IsStandardRequest(); + + static TUsbRequest Request(); + static TUint16 Value(); + static TUint16 Index(); + + // data length if there is a data packet(in/out) follows + // data length will be modified during a transfer + static TUint16 DataLength(); + + static TUsbcSetup& SetupPacket(); + + private: + static TUsbcSetup iSetupPkt; + }; + + +// State machine manager +// +NONSHARABLE_CLASS(DControlTransferManager) + { + friend class TControlStageSm; + + public: + DControlTransferManager(MControlTransferIf& aPktProcessor); + + // PSL will complete to PIL directly, in our cases, PIL will delegate to us via this interface + void Ep0RequestComplete(TUint8* aBuf, TInt aSize, TInt aError, UsbShai::TControlPacketType aPktType); + + // Add a new state processor + void AddState(UsbShai::TControlStage aStage, TControlStageSm& aStageSm); + + public: + // Helper inline function + MControlTransferIf& CtrTransferIf(); + TSetupPkgParser& PktParser(); + + public: + // EP0 Access interface + // They are the same as it shows in SHAI header + // so, PIL code can delegate those task to us, we will perform a series of checking + // depending on which state we are in, if each condition meet, we will callback via + // interface MControlTransferIf to perform the real work. + TInt SetupEndpointZeroRead(); + TInt SetupEndpointZeroWrite(const TUint8* aBuffer, TInt aLength, TBool aZlpReqd=EFalse); + TInt SendEp0ZeroByteStatusPacket(); + TInt StallEndpoint(TInt aRealEndpoint); + void Ep0SetupPacketProceed(); + void Ep0DataPacketProceed(); + + // Reset state machine. + void Reset(); + + // Data received for data out stage + void DataReceived(TUint16 aCount); + TBool IsMoreBytesNeeded(); + + private: + // State machines for each stage + TControlStageSm* iState[UsbShai::EControlTransferStageMax]; + // Current stage + UsbShai::TControlStage iCurrentStage; + TSetupPkgParser iPacketParser; + + MControlTransferIf& iCtrTransferIf; + + TBool iReadPending; + + TUint16 iDataTransfered; + }; + +// Base class of state machine +NONSHARABLE_CLASS(TControlStageSm) + { + public: + + /** PSL --Ep0RequestComplete()--> PIL --Ep0RequestComplete()---------> + * | + * (ProcessXXX)PIL <-- RequestComplete()<--DControlTransferManager <- + * + * @param aPktSize the size of the packet recieved + * aError error code if something wrong + * aPktType one of the packet type specified in UsbShai::TControlPacketType + * + * @return ETrue if the packet need to be further processed + * EFalse if the packet was consumed + */ + virtual TBool RequestComplete(TInt aPktSize, TInt aError, UsbShai::TControlPacketType aPktType) = 0; + + /** Query whether a kind of operation is allowed in specified state + * + * @param aRequest the request to be queried + * + * @return ETrue is the operation is allowed + * EFalse if not + */ + virtual TBool IsRequstAllowed(TControlTransferRequest aRequest) = 0; + + TControlStageSm(DControlTransferManager& aTransferMgr); + + protected: + // change state of SM in iTransferMgr + void ChangeToStage(UsbShai::TControlStage aToStage); + + // Clear ReadPending in ControlTransferMgr so that it won't + // block any further read operation + void ClearPendingRead(); + + protected: + DControlTransferManager& iTransferMgr; + }; + +// Concreate state class +// State of "Setup", used to wait for a setup packet +// it will ignore all non-setup-packet +NONSHARABLE_CLASS(DSetupStageSm) : public TControlStageSm + { + public: + DSetupStageSm(DControlTransferManager& aTransferMgr); + + TBool RequestComplete(TInt aPktSize, TInt aError, UsbShai::TControlPacketType aPktType); + TBool IsRequstAllowed(TControlTransferRequest aRequest); + }; + +// State used to wait for user to write something to host +// The write is supposed to be done in one shot +NONSHARABLE_CLASS(DDataInStageSm) : public TControlStageSm + { + public: + DDataInStageSm(DControlTransferManager& aTransferMgr); + + TBool RequestComplete(TInt aPktSize, TInt aError, UsbShai::TControlPacketType aPktType); + TBool IsRequstAllowed(TControlTransferRequest aRequest); + }; + +// State used to wait some data from Host +NONSHARABLE_CLASS(DDataOutStageSm) : public TControlStageSm + { + public: + DDataOutStageSm(DControlTransferManager& aTransferMgr); + + TBool RequestComplete(TInt aPktSize, TInt aError, UsbShai::TControlPacketType aPktType); + TBool IsRequstAllowed(TControlTransferRequest aRequest); + }; + +NONSHARABLE_CLASS(DStatusInStageSm) : public TControlStageSm + { + public: + DStatusInStageSm(DControlTransferManager& aTransferMgr); + + TBool RequestComplete(TInt aPktSize, TInt aError, UsbShai::TControlPacketType aPktType); + TBool IsRequstAllowed(TControlTransferRequest aRequest); + }; + +NONSHARABLE_CLASS(DStatusOutStageSm) : public TControlStageSm + { + public: + DStatusOutStageSm(DControlTransferManager& aTransferMgr); + + TBool RequestComplete(TInt aPktSize, TInt aError, UsbShai::TControlPacketType aPktType); + TBool IsRequstAllowed(TControlTransferRequest aRequest); + }; + +#include "controltransfersm.inl" + +#endif //CONTROLTRANSFER_SM_H