kernel/eka/include/drivers/usbcsc.h
changeset 0 a41df078684a
child 189 a5496987b1da
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/include/drivers/usbcsc.h	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,499 @@
+// 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 <d32usbcsc.h>
+
+#include <drivers/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 <drivers/usbcsc.inl>
+
+#endif	// __USBCSC_H__