usbdrv/peripheral/public/usbcsc.h
branchRCL_3
changeset 15 f92a4f87e424
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/public/usbcsc.h	Tue Aug 31 17:01:47 2010 +0300
@@ -0,0 +1,500 @@
+// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32\include\drivers\usbcsc.h
+// Kernel side definitions for the USB Device driver stack (PIL + LDD).
+// 
+//
+
+/**
+ @file usbcsc.h
+ @internalTechnology
+*/
+
+#ifndef __USBCSC_H__
+#define __USBCSC_H__
+
+#include <kernel/kernel.h>
+#include <kernel/kern_priv.h>
+#include <kernel/kpower.h>
+#include <platform.h>
+
+#include <usb/d32usbcsc.h>
+
+// #include <drivers/usbcshared.h>
+#include <usb/usbcshared.h>
+
+/** LDD Major version, This should agree with the information in RDevUsbcClient::TVer.
+*/
+const TInt KUsbcScMajorVersion = 0;
+
+/** LDD Minor version, This should agree with the information in RDevUsbcClient::TVer.
+*/
+const TInt KUsbcScMinorVersion = 1;
+
+/** LDD Build version, This should agree with the information in RDevUsbcClient::TVer.
+*/
+const TInt KUsbcScBuildVersion = KE32BuildVersionNumber;
+
+/** Must correspond to the max enum of TRequest + 1;
+    currently this is ERequestOtgFeaturesNotify = 10.
+*/
+const TInt KUsbcScMaxRequests = 11;
+
+// Request queue sizes need to be power of 2.
+
+/** The number of requests that can be queued on any IN endpoint */
+const TInt KUsbcScInRequests = 4;
+/** The number of requests that can be queued on any OUT endpoint */
+const TInt KUsbcScOutRequests = 2;
+
+/** In TUsbcScBuffer.iDirection, this indicates that the endpoint is an IN endpoint */
+const TInt KUsbcScIn =  0;
+/** In TUsbcScBuffer.iDirection, this indicates that the endpoint is an OUT endpoint */
+const TInt KUsbcScOut = 1;
+
+
+/** In TUsbcScBuffer.iDirection, this indicates that the endpoint is an Bidirectional endpoint
+currently operating as an IN endpoint */
+const TInt KUsbcScBiIn = 2;
+/** In TUsbcScBuffer.iDirection, this indicates that the endpoint is an Bidirectional endpoint
+currently operating as an OUT endpoint */
+const TInt KUsbcScBiOut = 3;
+
+/** The number of directions supported for endpoints, other then EP0.  Currently 2, IN and OUT. */
+const TInt KUsbcScDirections = 2;
+
+/** In TUsbcScBuffer::iDirection, this indicates that the endpoint direction is Unknown. */
+const TInt KUsbcScUnknown = 4;
+
+const TInt KPageSize = 0x1000;
+
+/** The default buffer size requested for a endpoint, if the user app does not specify a size.*/
+const TInt KUsbcScDefaultBufferSize = 0x10000; // 64k
+
+/** The size of the unmapped region of memory between endpoint buffers.
+This serves as a guard region, making memory over/under runs more obviose.*/
+const TInt KGuardSize = KPageSize;
+
+/** The size put aside for the chunk header structre.*/
+const TInt KHeaderSize = KPageSize;
+
+/** For buffers of size >= KUsbScBigBuffIs, The smallest unit of continiouse memory that will be used.
+No read will be set up smaller then this, to avoid overly fragmenting the data.
+*/
+const TInt KUsbSc_BigBuff_MinimumRamRun = KPageSize;
+
+/** For buffers of size < KUsbScBigBuffIs, The smallest unit of continiouse memory that will be used.
+No read will be set up smaller then this, to avoid overly fragmenting the data.*/
+const TInt KUsbSc_SmallBuff_MinimumRamRun = 1024;
+
+/** The size a buffer request has to be to switch to using KUsbSc_BigBuff_MinimumRamRun.
+If the requested buffer is smaller, then the smallest memory allocated to a buffer is KPageSize*/
+const TInt KUsbScBigBuffIs = KPageSize*6;
+
+
+
+// EP0 is mapped manually, unlike the other endpoints.
+
+/** The position, within the chunk, that the EP0 IN buffer appears*/
+const TInt KUsbScEP0InBufPos = 0x800;
+/** The position, within the chunk, that the EP0 IN buffer ends*/
+const TInt KUsbScEP0InBufEnd = KUsbScEP0InBufPos + 0x400;
+
+// Its better for Out to go 2nd, so gaurd page after it.
+/** The position, within the chunk, that the EP0 OUT buffer appears*/
+const TInt KUsbScEP0OutBufPos = 0xc00;
+/** The position, within the chunk, that the EP0 OUT buffer ends*/
+const TInt KUsbScEP0OutBufEnd = KUsbScEP0OutBufPos + 0x400;
+
+/** The number of the entry within the chunk BufferRecord table, for the OUT ep0 buffer.*/
+const TInt KUsbcScEp0OutBuff = 0;
+/** The number of the entry within the chunk BufferRecord table, for the IN ep0 buffer.*/
+const TInt KUsbcScEp0InBuff = 1;
+
+
+//
+//########################### Logical Device Driver (LDD) #############################
+//
+
+/** USB LDD factory class.
+*/
+class DUsbcScLogDevice : public DLogicalDevice
+    {
+public:
+    DUsbcScLogDevice();
+    virtual TInt Install();
+    virtual void GetCaps(TDes8& aDes) const;
+    virtual TInt Create(DLogicalChannelBase*& aChannel);
+    };
+
+
+class DLddUsbcScChannel;
+class TUsbcScBuffer;
+/** Endpoint tracking for the LDD buffering etc.
+*/
+class TUsbcScEndpoint
+    {
+public:
+    TUsbcScEndpoint(DLddUsbcScChannel* aLDD, DUsbClientController* aController,
+                  const TUsbcScEndpointInfo* aEndpointInfo, TInt aEndpointNum
+                  );
+    ~TUsbcScEndpoint();
+    TInt Construct();
+    void CancelTransfer(DThread* aThread);
+    void AbortTransfer();
+    inline TUsbcScEndpointInfo* EndpointInfo();
+    inline TInt RxBytesAvailable() const;
+    inline void ResetTransferInfo();
+    inline void SetClientReadPending(TBool aVal);
+    inline void SetClientWritePending(TBool aVal);
+    inline TBool ClientWritePending();
+    inline TBool ClientReadPending();
+    inline void SetRealEpNumber(TInt aRealEpNumber);
+    inline TInt RealEpNumber() const;
+    inline TInt EpNumber() const;
+    inline void StartBuffer();
+    inline void SetBuffer(TUsbcScBuffer* aBuffer);
+    inline TUsbcScBuffer* GetBuffer();
+
+
+private:
+    static void RequestCallback(TAny* aTUsbcScEndpoint);
+    void TxComplete();
+    TInt RxComplete(TBool aReEntrant);
+    void RxCompleteNow();
+
+
+
+public:
+    TUsbcRequestCallback* iRequestCallbackInfo;
+
+private:
+    DUsbClientController* iController;
+    TUsbcScEndpointInfo iEndpointInfo;
+    TBool iClientReadPending;
+    TBool iClientWritePending;
+    TInt iEndpointNumber;
+    TInt iRealEpNumber;
+    DLddUsbcScChannel* iLdd;
+    TInt iError;
+    TUint32 iBytesTransferred;
+    TInt iBandwidthPriority;
+    TUsbcScBuffer* iBuffer;
+
+    };
+
+
+/** Linked list of 'alternate setting' info for use by the LDD.
+*/
+class TUsbcScAlternateSetting
+    {
+public:
+    TUsbcScAlternateSetting();
+    ~TUsbcScAlternateSetting();
+
+public:
+    TUsbcScAlternateSetting* iNext;
+    TUsbcScAlternateSetting* iPrevious;
+    TInt iNumberOfEndpoints;
+    TUint iSetting;
+    TUsbcScEndpoint* iEndpoint[KMaxEndpointsPerClient + 1];
+    };
+
+class TUsbcScAlternateSettingList
+    {
+public:
+    TUsbcScAlternateSettingList();
+    ~TUsbcScAlternateSettingList();
+
+public:
+    TUsbcScAlternateSetting* iHead;
+    TUsbcScAlternateSetting* iTail;
+    };
+
+class TUsbcScChunkInfo
+    {
+public:
+    TUsbcScChunkInfo(DLogicalDevice* aLdd);
+    TInt CreateChunk(TInt aTotalSize);
+    void Close();
+    TInt ChunkAlloc(TInt aOffset, TInt aSize);
+    void ChunkCleanup();
+    TInt GetPhysical(TInt aOffset, TPhysAddr* aPhysical);
+    static TInt New(TUsbcScChunkInfo*& aChunk, TInt aSize, DLogicalDevice* aLdd);
+private:
+    TUint* iPhysicalMap;
+public:
+    DChunk* iChunk;
+    TDfc iCleanup;
+
+    TInt8 iPageNtz; // Number of trailing zeros for a page. (Eg 4k page has 12 t.z.)
+    TInt iAllocatedSize;
+    TInt8* iChunkMem;
+    TUint32 iChunkMapAttr;
+    DLogicalDevice* iLdd;
+    };
+
+
+// Used to represent a matrix of endpoints with a column of sizes.
+// Used by TRealizeInfo
+
+class TEndpointSortBufs
+    {
+    public:
+        TUsbcScEndpoint** iEp;
+        TInt* iSizes;
+        TInt iEps;
+    };
+
+// This is used to calculate the layout of the shared chunk
+// based on a list of alternative settings / endpoints provided.
+ 
+class TRealizeInfo
+    {
+    public:
+        void Init(TUsbcScAlternateSettingList* aAlternateSettingList);
+        TInt CopyAndSortEndpoints();
+        void CalcBuffSizes();
+        void Free();
+
+        void LayoutChunkHeader(TUsbcScChunkInfo* aChunkInfo);
+    public:
+        TInt iMaxEndpoints;
+        TInt iTotalSize;
+        TInt iTotalBuffers;
+        TInt iAltSettings;
+        TEndpointSortBufs iBufs[KUsbcScDirections];
+        TUsbcScAlternateSettingList* iAlternateSettingList;
+
+        // Chunk layout info.
+        TUsbcScChunkBuffersHeader* iChunkStuct;
+        TUsbcScChunkAltSettingHeader* iAltSettingsTbl;
+    };
+
+
+
+/** The channel class - the actual USB LDD.
+*/
+class DLddUsbcScChannel : public DLogicalChannel
+    {
+public:
+    DLddUsbcScChannel();
+    ~DLddUsbcScChannel();
+    virtual void HandleMsg(TMessageBase* aMsg);
+    virtual TInt DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer);
+    virtual TInt RequestUserHandle(DThread* aThread, TOwnerType aType);
+    inline DThread* Client() const {return iClient;}
+    inline TBool ChannelClosing() const {return iChannelClosing;}
+    inline TUint AlternateSetting() const {return iAlternateSetting;}
+    
+    static void RequestCallbackEp0(TAny* aTUsbcScChannel);
+
+private:
+
+    TInt DoCancel(TInt aReqNo, TUint aMask, TUint a1);
+    TInt DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2);
+    TInt DoControl(TInt aFunction, TAny* a1, TAny* a2);
+    TInt DoReadDataNotify(TRequestStatus* aStatus, TInt aBufferNum, TInt aLength);
+    void StartDataRead(TInt aBufferNum);
+    TInt DoWriteData(TRequestStatus* aStatus,TInt aBufferNum, TUint aStart, TUint aLength, TUint aFlags);
+    TBool AlternateDeviceStateTestComplete();
+    TInt SetInterface(TInt aInterfaceNum, TUsbcScIfcInfo* aUserInterfaceInfoBuf);
+    void StartEpReads();
+    void DestroyAllInterfaces();
+    void DestroyInterface(TUint aInterface);
+    void DestroyEp0();
+    inline TBool ValidEndpoint(TInt aEndpoint);
+    TInt GetRealEpForEpResource(TInt aEndpoint, TInt& aRealEp);
+    inline TBool Configured();
+    TInt DoEmergencyComplete();
+    void ReadDes8(const TAny* aPtr, TDes8& aDes);
+    TInt SetupEp0();
+    void CancelNotifyEndpointStatus();
+    void CancelNotifyOtgFeatures();
+    static void StatusChangeCallback(TAny* aDLddUsbcChannel);
+    static void EndpointStatusChangeCallback(TAny* aDLddUsbcChannel);
+    static void OtgFeatureChangeCallback(TAny* aDLddUsbcChannel);
+    static void EmergencyCompleteDfc(TAny* aDLddUsbcChannel);
+    void DeConfigure(TInt aErrorCode);
+    TInt SelectAlternateSetting(TUint aAlternateSetting);
+    TInt EpFromAlternateSetting(TUint aAlternateSetting, TInt aEndpoint);
+    TInt ProcessAlternateSetting(TUint aAlternateSetting);
+    TInt32 StartNextInAlternateSetting();
+    TInt ProcessDeviceState(TUsbcDeviceState aDeviceState);
+    void ResetInterface(TInt aErrorCode);
+    void PanicClientThread(TInt aReason);
+
+    TInt RealizeInterface(void);
+
+private:
+    DUsbClientController* iController;
+    DThread* iClient;
+    TBool iValidInterface;
+    
+    TUsbcScAlternateSettingList* iAlternateSettingList;
+    TUsbcScEndpoint** iEndpoint;  // Pointer to the current endpoint set.
+
+    static const TInt KUsbcMaxRequests = RDevUsbcScClient::ERequestMaxRequests;
+    TRequestStatus* iRequestStatus[KUsbcMaxRequests];
+    TUsbcClientCallback iCompleteAllCallbackInfo;
+    TAny* iStatusChangePtr;
+    TUsbcStatusCallback iStatusCallbackInfo;
+    TAny* iEndpointStatusChangePtr;
+    TUsbcEndpointStatusCallback iEndpointStatusCallbackInfo;
+    TAny* iOtgFeatureChangePtr;
+    TUsbcOtgFeatureCallback iOtgFeatureCallbackInfo;
+    TUint8* iBufferBaseEp0;
+    TInt iBufferSizeEp0;
+    TInt iNumberOfEndpoints;
+    TUsbcDeviceState iDeviceState;
+    TUsbcDeviceState iOldDeviceState;
+    TBool iOwnsDeviceControl;
+    TUint16 iAlternateSetting;
+    TUint16 iAsSeq;
+
+    TUsbcDeviceStatusQueue* iStatusFifo;
+    TBool iUserKnowsAltSetting;
+    TBool iDeviceStatusNeeded;
+    TBool iChannelClosing;
+    TBool iRealizeCalled;
+
+    TUsbcScChunkInfo* iChunkInfo;
+    TInt iNumBuffers;
+    TUsbcScBuffer *iBuffers;
+
+    TUsbcScEndpoint* iEp0Endpoint;
+    TInt iEP0InBuff;
+    TInt iEP0OutBuff;
+
+    friend class TUsbcScBuffer;
+    friend void TUsbcScEndpoint::AbortTransfer();
+    };
+
+/**
+This class is used by TUsbcScStatusList to form a queue of status requests.
+These requests are on a buffer basis, so that all buffers can have at least two requests
+pending, at the same time. (i.e. buffer 1 could have two requests outstanding, as well as 2 on buffer 2.)
+*/
+
+class TUsbcScStatusElement
+{
+public:
+    TRequestStatus* iStatus;
+    TInt iLength;
+    TUint iStart;
+    TUint iFlags;    
+};
+
+enum TUsbcScStatusState
+{
+    ENotRunning,
+    EInProgress,
+    EReadingAhead,
+    EFramgementInProgress
+};
+
+class TUsbcScStatusList
+{
+public:
+    TInt Construct(TInt aSize, DThread* aThread);
+    void Destroy();
+
+    TUsbcScStatusElement* Next();
+    void Pop();
+    TInt Add(TRequestStatus* aStatus, TInt aLength, TUint aStart, TUint aFlags);
+    void CancelQueued(TInt aErrorCode=KErrCancel);
+    TInt Complete(TInt aError);
+    void Complete();
+public:
+    TUsbcScStatusState iState;
+
+private:
+    DThread* iClient;
+    TInt iHead;   // The element at the head of the queue, ie, the earliest added, and next to be removed.
+    TInt iLength; // Length of queue, ie number of elements within
+    TInt iSize;   // size of array, ie, max # of requests at a time.
+    TUsbcScStatusElement* iElements;
+
+};
+
+
+
+/**
+This class holds the kernel's copy of all the details related to a shared endpoint buffer,
+and provides methods for the LDD to manipulate it.
+*/
+class TUsbcScBuffer
+{
+public:
+    static const TInt8 KNoEpAssigned=0;
+    static const TInt8 KEpIsEnding=1;
+    static const TInt8 KEpIsStarting=2;
+
+public:
+    TInt Construct(TInt aDirection, DLddUsbcScChannel* aLdd, TInt aBufferOffset, TInt aBufferEndOffset, TInt aMinReadSize, TInt aMaxPacketSize, TInt aMaxReadSize);
+    void CreateChunkBufferHeader();
+    void StartEndpoint(TUsbcRequestCallback* iRequestInfo, TUint iFlags);
+
+    void Destroy();
+
+    TInt StartDataRead();
+    void CompleteRead(TBool aStartNextRead=ETrue);
+    void PopStall();
+    void StartDataWrite();
+    void CompleteWrite();
+    void Cancel(TInt aErrorCode);
+
+    void UpdateBufferList(TInt aByteCount,TUint aFlags, TBool aStartNextRead=ETrue);
+    void Ep0CancelLddRead();
+    void SendEp0StatusPacket(TInt aState);
+
+public:
+    
+    TInt8 iDirection;
+    TInt8 iMode;
+    TInt8 iNeedsPacket;
+    TInt8 iReserved;
+    DLddUsbcScChannel* iLdd;
+    TLinAddr iChunkAddr;
+    SUsbcScBufferHeader* iBufferStart;
+    TUint iBufferEnd; // One word on from the last word in the buffer.
+    TUint iAlignMask;
+    TUsbcScStatusList iStatusList;
+    TUsbcRequestCallback* iCallback;
+    union 
+    {
+        TInt iHead; // Out endpoints only;
+        TUint iSent; // In endpoints only
+    };
+    TUsbcScChunkInfo* iChunkInfo;
+    TInt iMinReadSize;
+    TInt iMaxReadSize;
+    TInt iMaxPacketSize;  // 0 indicates unconfiured.
+    TInt iFirstPacket;
+    TInt iStalled;
+
+    // needed for backwards compatibility
+    TUsbcPacketArray iIndexArray[KUsbcDmaBufNumMax]; // Has 2 elements
+    TUsbcPacketArray iSizeArray[KUsbcDmaBufNumMax];  // Has 2 elements
+#ifdef _DEBUG
+    TUint iSequence;
+#endif
+
+};
+
+
+
+#include <usb/usbcsc.inl>
+
+#endif    // __USBCSC_H__