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