sl@0: // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: // All rights reserved.
sl@0: // This component and the accompanying materials are made available
sl@0: // under the terms of the License "Eclipse Public License v1.0"
sl@0: // which accompanies this distribution, and is available
sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: //
sl@0: // Initial Contributors:
sl@0: // Nokia Corporation - initial contribution.
sl@0: //
sl@0: // Contributors:
sl@0: //
sl@0: // Description:
sl@0: // e32/include/drivers/usbc.h
sl@0: // Kernel side definitions for the USB Device driver stack (PIL + LDD).
sl@0: // 
sl@0: //
sl@0: 
sl@0: /**
sl@0:  @file usbc.h
sl@0:  @internalTechnology
sl@0: */
sl@0: 
sl@0: #ifndef __USBC_H__
sl@0: #define __USBC_H__
sl@0: 
sl@0: #include <kernel/kernel.h>
sl@0: #include <kernel/kern_priv.h>
sl@0: #include <kernel/kpower.h>
sl@0: #include <platform.h>
sl@0: 
sl@0: #include <d32usbc.h>
sl@0: 
sl@0: #include <drivers/usbcshared.h>
sl@0: 
sl@0: 
sl@0: 
sl@0: /** LDD Major version, This should agree with the information in RDevUsbcClient::TVer.
sl@0: */
sl@0: const TInt KUsbcMajorVersion = 0;
sl@0: 
sl@0: /** LDD Minor version, This should agree with the information in RDevUsbcClient::TVer.
sl@0: */
sl@0: const TInt KUsbcMinorVersion = 1;
sl@0: 
sl@0: /** LDD Build version, This should agree with the information in RDevUsbcClient::TVer.
sl@0: */
sl@0: const TInt KUsbcBuildVersion = KE32BuildVersionNumber;
sl@0: 
sl@0: /** Must correspond to the max enum of TRequest + 1;
sl@0: 	currently this is ERequestOtgFeaturesNotify = 10.
sl@0: */
sl@0: const TInt KUsbcMaxRequests = 11;
sl@0: 
sl@0: //
sl@0: //########################### Logical Device Driver (LDD) #############################
sl@0: //
sl@0: 
sl@0: /** USB LDD factory class.
sl@0: */
sl@0: class DUsbcLogDevice : public DLogicalDevice
sl@0: 	{
sl@0: public:
sl@0: 	DUsbcLogDevice();
sl@0: 	virtual TInt Install();
sl@0: 	virtual void GetCaps(TDes8& aDes) const;
sl@0: 	virtual TInt Create(DLogicalChannelBase*& aChannel);
sl@0: 	};
sl@0: 
sl@0: 
sl@0: /** OUT buffering is a collection of flat buffers. Each is either fillable or drainable.
sl@0: 	When one buffer becomes full (notified by the PIL) it is marked as not-fillable and the next
sl@0: 	fillable buffer is used. When the buffer has finished draining it is marked as fillable.
sl@0: */
sl@0: class TDmaBuf
sl@0: 	{
sl@0: public:
sl@0: 	TDmaBuf();
sl@0:  	TDmaBuf(TUsbcEndpointInfo* aEndpointInfo, TInt aBandwidthPriority);
sl@0: 	~TDmaBuf();
sl@0: 	TInt Construct(TUsbcEndpointInfo* aEndpointInfo);
sl@0: 	TInt BufferTotalSize() const;
sl@0: 	TInt BufferSize() const;
sl@0: 	TInt SetBufferAddr(TInt aBufInd, TUint8* aBufAddr);
sl@0: 	TInt BufferNumber() const;
sl@0: 	void SetMaxPacketSize(TInt aSize);
sl@0: 	void Flush();
sl@0: 	// Rx (OUT) variants
sl@0: 	void RxSetActive();
sl@0: 	void RxSetInActive();
sl@0: 	TBool RxIsActive();
sl@0: 	TBool IsReaderEmpty();
sl@0: 	void ReadXferComplete(TInt aNoBytesRx, TInt aNoPacketsRx, TInt aErrorCode);
sl@0: 	TInt RxCopyDataToClient(DThread* aThread, TClientBuffer *aTcb, TInt aLength, TUint32& aDestOffset,
sl@0: 							TBool aRUS, TBool& aCompleteNow);
sl@0: 	TInt RxCopyPacketToClient(DThread* aThread,TClientBuffer *aTcb, TInt aLength);
sl@0: 	TInt RxGetNextXfer(TUint8*& aBufferAddr, TUsbcPacketArray*& aIndexArray, TUsbcPacketArray*& aSizeArray,
sl@0: 					   TInt& aLength, TPhysAddr& aBufferPhys);
sl@0: 	TBool RxIsEnoughSpace(TInt aSize);
sl@0: 	inline TInt RxBytesAvailable() const;
sl@0: 	inline void IncrementBufferIndex(TInt& aIndex);
sl@0: 	inline TInt NoRxPackets() const;
sl@0: 	TInt SetDrainable(TInt aBufferNum);
sl@0: 	// Tx (IN) variants
sl@0: 	void TxSetActive();
sl@0: 	void TxSetInActive();
sl@0: 	TBool TxIsActive();
sl@0: 	TInt TxStoreData(DThread* aThread,TClientBuffer *aTcb, TInt aTxLength, TUint32 aBufferOffset);
sl@0: 	TInt TxGetNextXfer(TUint8*& aBufferAddr, TInt& aTxLength, TPhysAddr& aBufferPhys);
sl@0: 	TBool ShortPacketExists();
sl@0: 
sl@0: #if defined(USBC_LDD_BUFFER_TRACE)
sl@0: 	TInt NoRxPacketsAlt() const;
sl@0: 	TInt NoRxBytesAlt() const;
sl@0: #endif
sl@0: 
sl@0: private:
sl@0: 	TBool AdvancePacket();
sl@0: 	inline TInt GetCurrentError();
sl@0: 	TBool NextDrainableBuffer();
sl@0: 	TBool NextFillableBuffer();
sl@0: 	void FreeDrainedBuffers();
sl@0: 	TInt PeekNextPacketSize();
sl@0: 	TInt PeekNextDrainableBuffer();
sl@0: 	void ModifyTotalRxBytesAvail(TInt aVal);
sl@0: 	void ModifyTotalRxPacketsAvail(TInt aVal);
sl@0: 	void AddToDrainQueue(TInt aBufferIndex);
sl@0: 	inline TInt CopyToUser(DThread* aThread, const TUint8* aSourceAddr, TInt aLength,
sl@0: 						   TClientBuffer *aTcb, TUint32& aDestOffset);
sl@0: private:
sl@0: 	TInt iExtractOffset;									// offset into current packet for data read
sl@0: 	TInt iMaxPacketSize;
sl@0: 	TInt iNumberofBuffers;
sl@0: 	TInt iBufSz;
sl@0: 	TBool iRxActive;
sl@0: 	TBool iTxActive;
sl@0: 	TInt iTotalRxBytesAvail;
sl@0: 	TInt iTotalRxPacketsAvail;
sl@0: 	//
sl@0: 	TUint8* iBufBasePtr;
sl@0: 	TUint8* iCurrentDrainingBuffer;
sl@0: 	TInt iCurrentDrainingBufferIndex;
sl@0: 	TInt iCurrentFillingBufferIndex;
sl@0: 	TUint iCurrentPacket;
sl@0: 	TUsbcPacketArray* iCurrentPacketIndexArray;
sl@0: 	TUsbcPacketArray* iCurrentPacketSizeArray;
sl@0: 	TUint8* iBuffers[KUsbcDmaBufNumMax];
sl@0: 	TBool iDrainable[KUsbcDmaBufNumMax];
sl@0: 	TUsbcPacketArray iPacketInfoStorage[KUsbcDmaBufNumMax * KUsbcDmaBufNumArrays * KUsbcDmaBufMaxPkts];
sl@0: 	TUsbcPacketArray* iPacketIndex[KUsbcDmaBufNumMax];
sl@0: 	TUsbcPacketArray* iPacketSize[KUsbcDmaBufNumMax];
sl@0: 	TUint iNumberofBytesRx[KUsbcDmaBufNumMax];
sl@0: 	TUint iNumberofPacketsRx[KUsbcDmaBufNumMax];
sl@0: 	TInt iError[KUsbcDmaBufNumMax];
sl@0: 	TPhysAddr iBufferPhys[KUsbcDmaBufNumMax];
sl@0: 	TBool iCanBeFreed[KUsbcDmaBufNumMax];
sl@0: 	TInt iDrainQueue[KUsbcDmaBufNumMax + 1];
sl@0: 	TInt iDrainQueueIndex;
sl@0: 	TUint iEndpointType;
sl@0: 
sl@0: #if defined(USBC_LDD_BUFFER_TRACE)
sl@0: 	TInt iFillingOrder;
sl@0: 	TInt iFillingOrderArray[KUsbcDmaBufNumMax];
sl@0: 	TInt iDrainingOrder;
sl@0:  	TUint iNumberofBytesRxRemain[KUsbcDmaBufNumMax];
sl@0:  	TUint iNumberofPacketsRxRemain[KUsbcDmaBufNumMax];
sl@0: #endif
sl@0: 	};
sl@0: 
sl@0: 
sl@0: class DLddUsbcChannel;
sl@0: 
sl@0: /** Endpoint tracking for the LDD buffering etc.
sl@0: */
sl@0: class TUsbcEndpoint
sl@0: 	{
sl@0: public:
sl@0: 	TUsbcEndpoint();
sl@0: 	TUsbcEndpoint(DLddUsbcChannel* aLDD, DUsbClientController* aController,
sl@0: 				  const TUsbcEndpointInfo* aEndpointInfo, TInt aEndpointNum,
sl@0: 				  TInt aBandwidthPriority);
sl@0: 	~TUsbcEndpoint();
sl@0: 	TInt Construct();
sl@0: 	TInt TryToStartRead(TBool aReEntrant);
sl@0: 	TInt TryToStartWrite(TEndpointTransferInfo* pTfr);
sl@0: 	TInt CopyToClient(DThread* aThread, TClientBuffer *aTcb);
sl@0: 	TInt CopyToClient(DThread* aClient, TBool& aCompleteNow, TClientBuffer *aTcb);
sl@0: 	TInt ContinueWrite();
sl@0: 	void SetMaxPacketSize(TInt aSize);
sl@0: 	void CancelTransfer(DThread* aThread, TClientBuffer *aTcb);
sl@0: 	void AbortTransfer();
sl@0: 	inline TUsbcEndpointInfo* EndpointInfo();
sl@0: 	inline TInt RxBytesAvailable() const;
sl@0: 
sl@0: 	inline TInt BufferSize() const;
sl@0: 	inline TInt SetBufferAddr( TInt aBufInd, TUint8* aAddr);
sl@0: 	inline TInt BufferNumber() const;
sl@0: 
sl@0: 	inline void SetTransferInfo(TEndpointTransferInfo* aTransferInfo);
sl@0: 	inline void ResetTransferInfo();
sl@0: 	inline void SetClientReadPending(TBool aVal);
sl@0: 	inline void SetClientWritePending(TBool aVal);
sl@0: 	inline TBool ClientWritePending();
sl@0: 	inline TBool ClientReadPending();
sl@0: 	inline void SetRealEpNumber(TInt aRealEpNumber);
sl@0: 	inline TInt RealEpNumber() const;
sl@0: 
sl@0: public:
sl@0: 	TDmaBuf* iDmaBuffers;
sl@0: 
sl@0: private:
sl@0: 	static void RequestCallback(TAny* aTUsbcEndpoint);
sl@0: 	void TxComplete();
sl@0: 	TInt RxComplete(TBool aReEntrant);
sl@0: 	void RxCompleteNow();
sl@0: 	TInt EndpointComplete();
sl@0: 
sl@0: private:
sl@0: 	DUsbClientController* iController;
sl@0: 	TUsbcEndpointInfo iEndpointInfo;
sl@0: 	TEndpointTransferInfo iTransferInfo;
sl@0: 	TBool iClientReadPending;
sl@0: 	TBool iClientWritePending;
sl@0: 	TInt iEndpointNumber;
sl@0: 	TInt iRealEpNumber;
sl@0: 	DLddUsbcChannel* iLdd;
sl@0: 	TInt iError;
sl@0: 	TUsbcRequestCallback* iRequestCallbackInfo;
sl@0: 	TUint32 iBytesTransferred;
sl@0: 	TInt iBandwidthPriority;
sl@0: 	};
sl@0: 
sl@0: 
sl@0: /** Linked list of 'alternate setting' info for use by the LDD.
sl@0: */
sl@0: class TUsbcAlternateSettingList
sl@0: 	{
sl@0: public:
sl@0: 	TUsbcAlternateSettingList();
sl@0: 	~TUsbcAlternateSettingList();
sl@0: 
sl@0: public:
sl@0: 	TUsbcAlternateSettingList* iNext;
sl@0: 	TInt iNumberOfEndpoints;
sl@0: 	TUint iSetting;
sl@0: 	TInt iEpNumDeOrderedByBufSize[KMaxEndpointsPerClient + 1];
sl@0: 	TUsbcEndpoint* iEndpoint[KMaxEndpointsPerClient + 1];
sl@0: 	};
sl@0: 
sl@0: 
sl@0: struct TClientAsynchNotify
sl@0: 	{
sl@0: 		TClientBufferRequest *iBufferRequest;
sl@0: 		TClientBuffer *iClientBuffer;
sl@0: 		void Reset();
sl@0: 	};
sl@0: /** The channel class - the actual USB LDD.
sl@0: */
sl@0: class DLddUsbcChannel : public DLogicalChannel
sl@0: 	{
sl@0: public:
sl@0: 	DLddUsbcChannel();
sl@0: 	~DLddUsbcChannel();
sl@0: 	virtual TInt SendMsg(TMessageBase * aMsg);
sl@0: 	TInt PreSendRequest(TMessageBase * aMsg,TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2);
sl@0: 	TInt SendControl(TMessageBase* aMsg);
sl@0: 	virtual void HandleMsg(TMessageBase* aMsg);
sl@0: 	virtual TInt DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer);
sl@0: 	virtual TInt RequestUserHandle(DThread* aThread, TOwnerType aType);
sl@0: 	TInt DoRxComplete(TUsbcEndpoint* aTUsbcEndpoint, TInt aEndpoint, TBool aReentrant);
sl@0: 	void DoRxCompleteNow(TUsbcEndpoint* aTUsbcEndpoint, TInt aEndpoint);
sl@0: 	void DoTxComplete(TUsbcEndpoint* aTUsbcEndpoint, TInt aEndpoint, TInt aError);
sl@0: 	inline DThread* Client() const {return iClient;}
sl@0: 	inline TBool ChannelClosing() const {return iChannelClosing;}
sl@0: 	inline TUint AlternateSetting() const {return iAlternateSetting;}
sl@0: 	TClientBuffer *GetClientBuffer(TInt aEndpoint);
sl@0: 
sl@0: private:
sl@0: 	TInt DoCancel(TInt aReqNo);
sl@0: 	void DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2);
sl@0: 	TInt DoControl(TInt aFunction, TAny* a1, TAny* a2);
sl@0: 	TInt DoTransferAsyncReq(TInt aEndpointNum, TAny* a1, TAny* a2, TBool& aNeedsCompletion);
sl@0: 	TInt DoOtherAsyncReq(TInt aReqNo, TAny* a1, TAny* a2, TBool& aNeedsCompletion);
sl@0: 	TBool AlternateDeviceStateTestComplete();
sl@0: 	TInt SetInterface(TInt aInterfaceNum, TUsbcIfcInfo* aUserInterfaceInfoBuf);
sl@0: 	void StartEpReads();
sl@0: 	void DestroyAllInterfaces();
sl@0: 	void DestroyInterface(TUint aInterface);
sl@0: 	void DestroyEp0();
sl@0: 	inline TBool ValidEndpoint(TInt aEndpoint);
sl@0: 	TInt DoEmergencyComplete();
sl@0: 	void ReadDes8(const TAny* aPtr, TDes8& aDes);
sl@0: 	TInt SetupEp0();
sl@0: 	DPlatChunkHw* ReAllocate(TInt aBuffersize, DPlatChunkHw* aHwChunk, TUint32 aCacheAttribs);
sl@0: 	DPlatChunkHw* Allocate(TInt aBuffersize, TUint32 aCacheAttribs);
sl@0: 	void ClosePhysicalChunk(DPlatChunkHw* &aHwChunk);
sl@0: 	void CancelNotifyEndpointStatus();
sl@0: 	void CancelNotifyOtgFeatures();
sl@0: 	static void StatusChangeCallback(TAny* aDLddUsbcChannel);
sl@0: 	static void EndpointStatusChangeCallback(TAny* aDLddUsbcChannel);
sl@0: 	static void OtgFeatureChangeCallback(TAny* aDLddUsbcChannel);
sl@0: 	static void EmergencyCompleteDfc(TAny* aDLddUsbcChannel);
sl@0: 	void DeConfigure(TInt aErrorCode);
sl@0: 	TInt SelectAlternateSetting(TUint aAlternateSetting);
sl@0: 	TInt EpFromAlternateSetting(TUint aAlternateSetting, TInt aEndpoint);
sl@0: 	TInt ProcessAlternateSetting(TUint aAlternateSetting);
sl@0: 	TInt ProcessDeviceState(TUsbcDeviceState aDeviceState);
sl@0: 	void ResetInterface(TInt aErrorCode);
sl@0: 	void AbortInterface();
sl@0: 	// Set buffer address of the interface
sl@0: 	void ReSetInterfaceMemory(TUsbcAlternateSettingList* aAlternateSettingListRec,
sl@0: 	        RArray<DPlatChunkHw*> &aHwChunks );
sl@0: 	void UpdateEndpointSizes();
sl@0: 	// Check and alloc memory for the interface
sl@0: 	TInt SetupInterfaceMemory(RArray<DPlatChunkHw*> &aHwChunks, 
sl@0: 	        TUint32 aCacheAttribs );
sl@0: 	void PanicClientThread(TInt aReason);
sl@0: 	TInt PinMemory(TDesC8 *aDes, TVirtualPinObject *iPinObj); //Descriptor pinning helper.
sl@0: 	void CompleteBufferRequest(DThread* aThread, TInt aReqNo, TInt aReason);
sl@0: private:
sl@0: 	DUsbClientController* iController;
sl@0: 	DThread* iClient;
sl@0: 	TBool iValidInterface;
sl@0: 	TUsbcAlternateSettingList* iAlternateSettingList;
sl@0: 	TUsbcEndpoint* iEndpoint[KMaxEndpointsPerClient + 1];	// include ep0
sl@0: 	TRequestStatus* iRequestStatus[KUsbcMaxRequests];
sl@0: 	TClientAsynchNotify* iClientAsynchNotify[KUsbcMaxRequests];
sl@0: 	TUsbcClientCallback iCompleteAllCallbackInfo;
sl@0: 	TAny* iStatusChangePtr;
sl@0: 	TUsbcStatusCallback iStatusCallbackInfo;
sl@0: 	TAny* iEndpointStatusChangePtr;
sl@0: 	TUsbcEndpointStatusCallback iEndpointStatusCallbackInfo;
sl@0: 	TAny* iOtgFeatureChangePtr;
sl@0: 	TUsbcOtgFeatureCallback iOtgFeatureCallbackInfo;
sl@0: 	TInt iNumberOfEndpoints;
sl@0:     RArray<DPlatChunkHw*> iHwChunksEp0;
sl@0:     RArray<DPlatChunkHw*> iHwChunks;
sl@0: 
sl@0: 	TUsbcDeviceState iDeviceState;
sl@0: 	TUsbcDeviceState iOldDeviceState;
sl@0: 	TBool iOwnsDeviceControl;
sl@0: 	TUint iAlternateSetting;
sl@0: 	TBool iDeviceStatusNeeded;
sl@0: 	TUsbcDeviceStatusQueue* iStatusFifo;
sl@0: 	TBool iChannelClosing;
sl@0: 	TVirtualPinObject *iPinObj1;
sl@0: 	TVirtualPinObject *iPinObj2;
sl@0: 	TVirtualPinObject *iPinObj3;
sl@0: 	TClientDataRequest<TUint> *iStatusChangeReq;
sl@0: 	TClientDataRequest<TUint> *iEndpointStatusChangeReq;
sl@0: 	TClientDataRequest<TUint> *iOtgFeatureChangeReq;
sl@0: 	TEndpointTransferInfo iTfrInfo;
sl@0: 	};
sl@0: 
sl@0: 
sl@0: #include <drivers/usbc.inl>
sl@0: 
sl@0: #endif	// __USBC_H__