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