|
1 // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // e32\include\drivers\usbcsc.h |
|
15 // Kernel side definitions for the USB Device driver stack (PIL + LDD). |
|
16 // |
|
17 // |
|
18 |
|
19 /** |
|
20 @file usbcsc.h |
|
21 @internalTechnology |
|
22 */ |
|
23 |
|
24 #ifndef __USBCSC_H__ |
|
25 #define __USBCSC_H__ |
|
26 |
|
27 #include <kernel/kernel.h> |
|
28 #include <kernel/kern_priv.h> |
|
29 #include <kernel/kpower.h> |
|
30 #include <platform.h> |
|
31 |
|
32 #include <d32usbcsc.h> |
|
33 |
|
34 #include <drivers/usbcshared.h> |
|
35 |
|
36 /** LDD Major version, This should agree with the information in RDevUsbcClient::TVer. |
|
37 */ |
|
38 const TInt KUsbcScMajorVersion = 0; |
|
39 |
|
40 /** LDD Minor version, This should agree with the information in RDevUsbcClient::TVer. |
|
41 */ |
|
42 const TInt KUsbcScMinorVersion = 1; |
|
43 |
|
44 /** LDD Build version, This should agree with the information in RDevUsbcClient::TVer. |
|
45 */ |
|
46 const TInt KUsbcScBuildVersion = KE32BuildVersionNumber; |
|
47 |
|
48 /** Must correspond to the max enum of TRequest + 1; |
|
49 currently this is ERequestOtgFeaturesNotify = 10. |
|
50 */ |
|
51 const TInt KUsbcScMaxRequests = 11; |
|
52 |
|
53 // Request queue sizes need to be power of 2. |
|
54 |
|
55 /** The number of requests that can be queued on any IN endpoint */ |
|
56 const TInt KUsbcScInRequests = 4; |
|
57 /** The number of requests that can be queued on any OUT endpoint */ |
|
58 const TInt KUsbcScOutRequests = 2; |
|
59 |
|
60 /** In TUsbcScBuffer.iDirection, this indicates that the endpoint is an IN endpoint */ |
|
61 const TInt KUsbcScIn = 0; |
|
62 /** In TUsbcScBuffer.iDirection, this indicates that the endpoint is an OUT endpoint */ |
|
63 const TInt KUsbcScOut = 1; |
|
64 |
|
65 |
|
66 /** In TUsbcScBuffer.iDirection, this indicates that the endpoint is an Bidirectional endpoint |
|
67 currently operating as an IN endpoint */ |
|
68 const TInt KUsbcScBiIn = 2; |
|
69 /** In TUsbcScBuffer.iDirection, this indicates that the endpoint is an Bidirectional endpoint |
|
70 currently operating as an OUT endpoint */ |
|
71 const TInt KUsbcScBiOut = 3; |
|
72 |
|
73 /** The number of directions supported for endpoints, other then EP0. Currently 2, IN and OUT. */ |
|
74 const TInt KUsbcScDirections = 2; |
|
75 |
|
76 /** In TUsbcScBuffer::iDirection, this indicates that the endpoint direction is Unknown. */ |
|
77 const TInt KUsbcScUnknown = 4; |
|
78 |
|
79 const TInt KPageSize = 0x1000; |
|
80 |
|
81 /** The default buffer size requested for a endpoint, if the user app does not specify a size.*/ |
|
82 const TInt KUsbcScDefaultBufferSize = 0x10000; // 64k |
|
83 |
|
84 /** The size of the unmapped region of memory between endpoint buffers. |
|
85 This serves as a guard region, making memory over/under runs more obviose.*/ |
|
86 const TInt KGuardSize = KPageSize; |
|
87 |
|
88 /** The size put aside for the chunk header structre.*/ |
|
89 const TInt KHeaderSize = KPageSize; |
|
90 |
|
91 /** For buffers of size >= KUsbScBigBuffIs, The smallest unit of continiouse memory that will be used. |
|
92 No read will be set up smaller then this, to avoid overly fragmenting the data. |
|
93 */ |
|
94 const TInt KUsbSc_BigBuff_MinimumRamRun = KPageSize; |
|
95 |
|
96 /** For buffers of size < KUsbScBigBuffIs, The smallest unit of continiouse memory that will be used. |
|
97 No read will be set up smaller then this, to avoid overly fragmenting the data.*/ |
|
98 const TInt KUsbSc_SmallBuff_MinimumRamRun = 1024; |
|
99 |
|
100 /** The size a buffer request has to be to switch to using KUsbSc_BigBuff_MinimumRamRun. |
|
101 If the requested buffer is smaller, then the smallest memory allocated to a buffer is KPageSize*/ |
|
102 const TInt KUsbScBigBuffIs = KPageSize*6; |
|
103 |
|
104 |
|
105 |
|
106 // EP0 is mapped manually, unlike the other endpoints. |
|
107 |
|
108 /** The position, within the chunk, that the EP0 IN buffer appears*/ |
|
109 const TInt KUsbScEP0InBufPos = 0x800; |
|
110 /** The position, within the chunk, that the EP0 IN buffer ends*/ |
|
111 const TInt KUsbScEP0InBufEnd = KUsbScEP0InBufPos + 0x400; |
|
112 |
|
113 // Its better for Out to go 2nd, so gaurd page after it. |
|
114 /** The position, within the chunk, that the EP0 OUT buffer appears*/ |
|
115 const TInt KUsbScEP0OutBufPos = 0xc00; |
|
116 /** The position, within the chunk, that the EP0 OUT buffer ends*/ |
|
117 const TInt KUsbScEP0OutBufEnd = KUsbScEP0OutBufPos + 0x400; |
|
118 |
|
119 /** The number of the entry within the chunk BufferRecord table, for the OUT ep0 buffer.*/ |
|
120 const TInt KUsbcScEp0OutBuff = 0; |
|
121 /** The number of the entry within the chunk BufferRecord table, for the IN ep0 buffer.*/ |
|
122 const TInt KUsbcScEp0InBuff = 1; |
|
123 |
|
124 |
|
125 // |
|
126 //########################### Logical Device Driver (LDD) ############################# |
|
127 // |
|
128 |
|
129 /** USB LDD factory class. |
|
130 */ |
|
131 class DUsbcScLogDevice : public DLogicalDevice |
|
132 { |
|
133 public: |
|
134 DUsbcScLogDevice(); |
|
135 virtual TInt Install(); |
|
136 virtual void GetCaps(TDes8& aDes) const; |
|
137 virtual TInt Create(DLogicalChannelBase*& aChannel); |
|
138 }; |
|
139 |
|
140 |
|
141 class DLddUsbcScChannel; |
|
142 class TUsbcScBuffer; |
|
143 /** Endpoint tracking for the LDD buffering etc. |
|
144 */ |
|
145 class TUsbcScEndpoint |
|
146 { |
|
147 public: |
|
148 TUsbcScEndpoint(DLddUsbcScChannel* aLDD, DUsbClientController* aController, |
|
149 const TUsbcScEndpointInfo* aEndpointInfo, TInt aEndpointNum |
|
150 ); |
|
151 ~TUsbcScEndpoint(); |
|
152 TInt Construct(); |
|
153 void CancelTransfer(DThread* aThread); |
|
154 void AbortTransfer(); |
|
155 inline TUsbcScEndpointInfo* EndpointInfo(); |
|
156 inline TInt RxBytesAvailable() const; |
|
157 inline void ResetTransferInfo(); |
|
158 inline void SetClientReadPending(TBool aVal); |
|
159 inline void SetClientWritePending(TBool aVal); |
|
160 inline TBool ClientWritePending(); |
|
161 inline TBool ClientReadPending(); |
|
162 inline void SetRealEpNumber(TInt aRealEpNumber); |
|
163 inline TInt RealEpNumber() const; |
|
164 inline TInt EpNumber() const; |
|
165 inline void StartBuffer(); |
|
166 inline void SetBuffer(TUsbcScBuffer* aBuffer); |
|
167 inline TUsbcScBuffer* GetBuffer(); |
|
168 |
|
169 |
|
170 private: |
|
171 static void RequestCallback(TAny* aTUsbcScEndpoint); |
|
172 void TxComplete(); |
|
173 TInt RxComplete(TBool aReEntrant); |
|
174 void RxCompleteNow(); |
|
175 |
|
176 |
|
177 |
|
178 public: |
|
179 TUsbcRequestCallback* iRequestCallbackInfo; |
|
180 |
|
181 private: |
|
182 DUsbClientController* iController; |
|
183 TUsbcScEndpointInfo iEndpointInfo; |
|
184 TBool iClientReadPending; |
|
185 TBool iClientWritePending; |
|
186 TInt iEndpointNumber; |
|
187 TInt iRealEpNumber; |
|
188 DLddUsbcScChannel* iLdd; |
|
189 TInt iError; |
|
190 TUint32 iBytesTransferred; |
|
191 TInt iBandwidthPriority; |
|
192 TUsbcScBuffer* iBuffer; |
|
193 |
|
194 }; |
|
195 |
|
196 |
|
197 /** Linked list of 'alternate setting' info for use by the LDD. |
|
198 */ |
|
199 class TUsbcScAlternateSetting |
|
200 { |
|
201 public: |
|
202 TUsbcScAlternateSetting(); |
|
203 ~TUsbcScAlternateSetting(); |
|
204 |
|
205 public: |
|
206 TUsbcScAlternateSetting* iNext; |
|
207 TUsbcScAlternateSetting* iPrevious; |
|
208 TInt iNumberOfEndpoints; |
|
209 TUint iSetting; |
|
210 TUsbcScEndpoint* iEndpoint[KMaxEndpointsPerClient + 1]; |
|
211 }; |
|
212 |
|
213 class TUsbcScAlternateSettingList |
|
214 { |
|
215 public: |
|
216 TUsbcScAlternateSettingList(); |
|
217 ~TUsbcScAlternateSettingList(); |
|
218 |
|
219 public: |
|
220 TUsbcScAlternateSetting* iHead; |
|
221 TUsbcScAlternateSetting* iTail; |
|
222 }; |
|
223 |
|
224 class TUsbcScChunkInfo |
|
225 { |
|
226 public: |
|
227 TUsbcScChunkInfo(DLogicalDevice* aLdd); |
|
228 TInt CreateChunk(TInt aTotalSize); |
|
229 void Close(); |
|
230 TInt ChunkAlloc(TInt aOffset, TInt aSize); |
|
231 void ChunkCleanup(); |
|
232 TInt GetPhysical(TInt aOffset, TPhysAddr* aPhysical); |
|
233 static TInt New(TUsbcScChunkInfo*& aChunk, TInt aSize, DLogicalDevice* aLdd); |
|
234 private: |
|
235 TUint* iPhysicalMap; |
|
236 public: |
|
237 DChunk* iChunk; |
|
238 TDfc iCleanup; |
|
239 |
|
240 TInt8 iPageNtz; // Number of trailing zeros for a page. (Eg 4k page has 12 t.z.) |
|
241 TInt iAllocatedSize; |
|
242 TInt8* iChunkMem; |
|
243 TUint32 iChunkMapAttr; |
|
244 DLogicalDevice* iLdd; |
|
245 }; |
|
246 |
|
247 |
|
248 // Used to represent a matrix of endpoints with a column of sizes. |
|
249 // Used by TRealizeInfo |
|
250 |
|
251 class TEndpointSortBufs |
|
252 { |
|
253 public: |
|
254 TUsbcScEndpoint** iEp; |
|
255 TInt* iSizes; |
|
256 TInt iEps; |
|
257 }; |
|
258 |
|
259 // This is used to calculate the layout of the shared chunk |
|
260 // based on a list of alternative settings / endpoints provided. |
|
261 |
|
262 class TRealizeInfo |
|
263 { |
|
264 public: |
|
265 void Init(TUsbcScAlternateSettingList* aAlternateSettingList); |
|
266 TInt CopyAndSortEndpoints(); |
|
267 void CalcBuffSizes(); |
|
268 void Free(); |
|
269 |
|
270 void LayoutChunkHeader(TUsbcScChunkInfo* aChunkInfo); |
|
271 public: |
|
272 TInt iMaxEndpoints; |
|
273 TInt iTotalSize; |
|
274 TInt iTotalBuffers; |
|
275 TInt iAltSettings; |
|
276 TEndpointSortBufs iBufs[KUsbcScDirections]; |
|
277 TUsbcScAlternateSettingList* iAlternateSettingList; |
|
278 |
|
279 // Chunk layout info. |
|
280 TUsbcScChunkBuffersHeader* iChunkStuct; |
|
281 TUsbcScChunkAltSettingHeader* iAltSettingsTbl; |
|
282 }; |
|
283 |
|
284 |
|
285 |
|
286 /** The channel class - the actual USB LDD. |
|
287 */ |
|
288 class DLddUsbcScChannel : public DLogicalChannel |
|
289 { |
|
290 public: |
|
291 DLddUsbcScChannel(); |
|
292 ~DLddUsbcScChannel(); |
|
293 virtual void HandleMsg(TMessageBase* aMsg); |
|
294 virtual TInt DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer); |
|
295 virtual TInt RequestUserHandle(DThread* aThread, TOwnerType aType); |
|
296 inline DThread* Client() const {return iClient;} |
|
297 inline TBool ChannelClosing() const {return iChannelClosing;} |
|
298 inline TUint AlternateSetting() const {return iAlternateSetting;} |
|
299 |
|
300 static void RequestCallbackEp0(TAny* aTUsbcScChannel); |
|
301 |
|
302 private: |
|
303 |
|
304 TInt DoCancel(TInt aReqNo, TUint aMask, TUint a1); |
|
305 TInt DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2); |
|
306 TInt DoControl(TInt aFunction, TAny* a1, TAny* a2); |
|
307 TInt DoReadDataNotify(TRequestStatus* aStatus, TInt aBufferNum, TInt aLength); |
|
308 void StartDataRead(TInt aBufferNum); |
|
309 TInt DoWriteData(TRequestStatus* aStatus,TInt aBufferNum, TUint aStart, TUint aLength, TUint aFlags); |
|
310 TBool AlternateDeviceStateTestComplete(); |
|
311 TInt SetInterface(TInt aInterfaceNum, TUsbcScIfcInfo* aUserInterfaceInfoBuf); |
|
312 void StartEpReads(); |
|
313 void DestroyAllInterfaces(); |
|
314 void DestroyInterface(TUint aInterface); |
|
315 void DestroyEp0(); |
|
316 inline TBool ValidEndpoint(TInt aEndpoint); |
|
317 TInt GetRealEpForEpResource(TInt aEndpoint, TInt& aRealEp); |
|
318 inline TBool Configured(); |
|
319 TInt DoEmergencyComplete(); |
|
320 void ReadDes8(const TAny* aPtr, TDes8& aDes); |
|
321 TInt SetupEp0(); |
|
322 void CancelNotifyEndpointStatus(); |
|
323 void CancelNotifyOtgFeatures(); |
|
324 static void StatusChangeCallback(TAny* aDLddUsbcChannel); |
|
325 static void EndpointStatusChangeCallback(TAny* aDLddUsbcChannel); |
|
326 static void OtgFeatureChangeCallback(TAny* aDLddUsbcChannel); |
|
327 static void EmergencyCompleteDfc(TAny* aDLddUsbcChannel); |
|
328 void DeConfigure(TInt aErrorCode); |
|
329 TInt SelectAlternateSetting(TUint aAlternateSetting); |
|
330 TInt EpFromAlternateSetting(TUint aAlternateSetting, TInt aEndpoint); |
|
331 TInt ProcessAlternateSetting(TUint aAlternateSetting); |
|
332 TInt32 StartNextInAlternateSetting(); |
|
333 TInt ProcessDeviceState(TUsbcDeviceState aDeviceState); |
|
334 void ResetInterface(TInt aErrorCode); |
|
335 void PanicClientThread(TInt aReason); |
|
336 |
|
337 TInt RealizeInterface(void); |
|
338 |
|
339 private: |
|
340 DUsbClientController* iController; |
|
341 DThread* iClient; |
|
342 TBool iValidInterface; |
|
343 |
|
344 TUsbcScAlternateSettingList* iAlternateSettingList; |
|
345 TUsbcScEndpoint** iEndpoint; // Pointer to the current endpoint set. |
|
346 |
|
347 static const TInt KUsbcMaxRequests = RDevUsbcScClient::ERequestMaxRequests; |
|
348 TRequestStatus* iRequestStatus[KUsbcMaxRequests]; |
|
349 TUsbcClientCallback iCompleteAllCallbackInfo; |
|
350 TAny* iStatusChangePtr; |
|
351 TUsbcStatusCallback iStatusCallbackInfo; |
|
352 TAny* iEndpointStatusChangePtr; |
|
353 TUsbcEndpointStatusCallback iEndpointStatusCallbackInfo; |
|
354 TAny* iOtgFeatureChangePtr; |
|
355 TUsbcOtgFeatureCallback iOtgFeatureCallbackInfo; |
|
356 TUint8* iBufferBaseEp0; |
|
357 TInt iBufferSizeEp0; |
|
358 TInt iNumberOfEndpoints; |
|
359 TUsbcDeviceState iDeviceState; |
|
360 TUsbcDeviceState iOldDeviceState; |
|
361 TBool iOwnsDeviceControl; |
|
362 TUint16 iAlternateSetting; |
|
363 TUint16 iAsSeq; |
|
364 |
|
365 TUsbcDeviceStatusQueue* iStatusFifo; |
|
366 TBool iUserKnowsAltSetting; |
|
367 TBool iDeviceStatusNeeded; |
|
368 TBool iChannelClosing; |
|
369 TBool iRealizeCalled; |
|
370 |
|
371 TUsbcScChunkInfo* iChunkInfo; |
|
372 TInt iNumBuffers; |
|
373 TUsbcScBuffer *iBuffers; |
|
374 |
|
375 TUsbcScEndpoint* iEp0Endpoint; |
|
376 TInt iEP0InBuff; |
|
377 TInt iEP0OutBuff; |
|
378 |
|
379 friend class TUsbcScBuffer; |
|
380 friend void TUsbcScEndpoint::AbortTransfer(); |
|
381 }; |
|
382 |
|
383 /** |
|
384 This class is used by TUsbcScStatusList to form a queue of status requests. |
|
385 These requests are on a buffer basis, so that all buffers can have at least two requests |
|
386 pending, at the same time. (i.e. buffer 1 could have two requests outstanding, as well as 2 on buffer 2.) |
|
387 */ |
|
388 |
|
389 class TUsbcScStatusElement |
|
390 { |
|
391 public: |
|
392 TRequestStatus* iStatus; |
|
393 TInt iLength; |
|
394 TUint iStart; |
|
395 TUint iFlags; |
|
396 }; |
|
397 |
|
398 enum TUsbcScStatusState |
|
399 { |
|
400 ENotRunning, |
|
401 EInProgress, |
|
402 EReadingAhead, |
|
403 EFramgementInProgress |
|
404 }; |
|
405 |
|
406 class TUsbcScStatusList |
|
407 { |
|
408 public: |
|
409 TInt Construct(TInt aSize, DThread* aThread); |
|
410 void Destroy(); |
|
411 |
|
412 TUsbcScStatusElement* Next(); |
|
413 void Pop(); |
|
414 TInt Add(TRequestStatus* aStatus, TInt aLength, TUint aStart, TUint aFlags); |
|
415 void CancelQueued(TInt aErrorCode=KErrCancel); |
|
416 TInt Complete(TInt aError); |
|
417 void Complete(); |
|
418 public: |
|
419 TUsbcScStatusState iState; |
|
420 |
|
421 private: |
|
422 DThread* iClient; |
|
423 TInt iHead; // The element at the head of the queue, ie, the earliest added, and next to be removed. |
|
424 TInt iLength; // Length of queue, ie number of elements within |
|
425 TInt iSize; // size of array, ie, max # of requests at a time. |
|
426 TUsbcScStatusElement* iElements; |
|
427 |
|
428 }; |
|
429 |
|
430 |
|
431 |
|
432 /** |
|
433 This class holds the kernel's copy of all the details related to a shared endpoint buffer, |
|
434 and provides methods for the LDD to manipulate it. |
|
435 */ |
|
436 class TUsbcScBuffer |
|
437 { |
|
438 public: |
|
439 static const TInt8 KNoEpAssigned=0; |
|
440 static const TInt8 KEpIsEnding=1; |
|
441 static const TInt8 KEpIsStarting=2; |
|
442 |
|
443 public: |
|
444 TInt Construct(TInt aDirection, DLddUsbcScChannel* aLdd, TInt aBufferOffset, TInt aBufferEndOffset, TInt aMinReadSize, TInt aMaxPacketSize, TInt aMaxReadSize); |
|
445 void CreateChunkBufferHeader(); |
|
446 void StartEndpoint(TUsbcRequestCallback* iRequestInfo, TUint iFlags); |
|
447 |
|
448 void Destroy(); |
|
449 |
|
450 TInt StartDataRead(); |
|
451 void CompleteRead(TBool aStartNextRead=ETrue); |
|
452 void PopStall(); |
|
453 void StartDataWrite(); |
|
454 void CompleteWrite(); |
|
455 void Cancel(TInt aErrorCode); |
|
456 |
|
457 void UpdateBufferList(TInt aByteCount,TUint aFlags, TBool aStartNextRead=ETrue); |
|
458 void Ep0CancelLddRead(); |
|
459 void SendEp0StatusPacket(TInt aState); |
|
460 |
|
461 public: |
|
462 |
|
463 TInt8 iDirection; |
|
464 TInt8 iMode; |
|
465 TInt8 iNeedsPacket; |
|
466 TInt8 iReserved; |
|
467 DLddUsbcScChannel* iLdd; |
|
468 TLinAddr iChunkAddr; |
|
469 SUsbcScBufferHeader* iBufferStart; |
|
470 TUint iBufferEnd; // One word on from the last word in the buffer. |
|
471 TUint iAlignMask; |
|
472 TUsbcScStatusList iStatusList; |
|
473 TUsbcRequestCallback* iCallback; |
|
474 union |
|
475 { |
|
476 TInt iHead; // Out endpoints only; |
|
477 TUint iSent; // In endpoints only |
|
478 }; |
|
479 TUsbcScChunkInfo* iChunkInfo; |
|
480 TInt iMinReadSize; |
|
481 TInt iMaxReadSize; |
|
482 TInt iMaxPacketSize; // 0 indicates unconfiured. |
|
483 TInt iFirstPacket; |
|
484 TInt iStalled; |
|
485 |
|
486 // needed for backwards compatibility |
|
487 TUsbcPacketArray iIndexArray[KUsbcDmaBufNumMax]; // Has 2 elements |
|
488 TUsbcPacketArray iSizeArray[KUsbcDmaBufNumMax]; // Has 2 elements |
|
489 #ifdef _DEBUG |
|
490 TUint iSequence; |
|
491 #endif |
|
492 |
|
493 }; |
|
494 |
|
495 |
|
496 |
|
497 #include <drivers/usbcsc.inl> |
|
498 |
|
499 #endif // __USBCSC_H__ |