usbdrv/peripheral/ldd/perilddsc/src/d_usbcsc.cpp
branchRCL_3
changeset 42 f92a4f87e424
child 48 21625e5de155
equal deleted inserted replaced
37:d3e8e7d462dd 42:f92a4f87e424
       
     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\drivers\usbcsc\d_usbcsc.cpp
       
    15 // LDD for USB Device driver stack, using shared chunks:
       
    16 // The channel object.
       
    17 // 
       
    18 //
       
    19 
       
    20 /**
       
    21  @file d_usbcsc.cpp
       
    22  @internalTechnology
       
    23 */
       
    24 
       
    25 // #include <drivers/usbcsc.h>
       
    26 #include <usb/usbcsc.h>
       
    27 #include "platform.h"
       
    28 
       
    29 /*****************************************************************************\
       
    30 *   DUsbcScLogDevice                                                          *
       
    31 *                                                                             *
       
    32 *   Inherits from DLogicalDevice, the USB Shared Chunk LDD factory class      *
       
    33 *                                                                             *
       
    34 \*****************************************************************************/
       
    35 
       
    36 _LIT(KUsbScLddName, "Usbcsc");
       
    37 
       
    38 static const TInt KUsbRequestCallbackPriority = 2;
       
    39 
       
    40 /** Real entry point from the Kernel: return a new driver.
       
    41  */
       
    42 DECLARE_STANDARD_LDD()
       
    43     {
       
    44     return new DUsbcScLogDevice;
       
    45     }
       
    46 
       
    47 /** Create a channel on the device.
       
    48 
       
    49     @internalComponent
       
    50 */
       
    51 TInt DUsbcScLogDevice::Create(DLogicalChannelBase*& aChannel)
       
    52     {
       
    53     aChannel = new DLddUsbcScChannel;
       
    54     return aChannel ? KErrNone : KErrNoMemory;
       
    55     }
       
    56 
       
    57 
       
    58 DUsbcScLogDevice::DUsbcScLogDevice()
       
    59       {
       
    60       iParseMask = KDeviceAllowUnit;
       
    61       iUnitsMask = 0xffffffff;                                // Leave units decision to the Controller
       
    62       iVersion = TVersion(KUsbcScMajorVersion, KUsbcScMinorVersion, KUsbcScBuildVersion);
       
    63       }
       
    64 
       
    65 
       
    66 TInt DUsbcScLogDevice::Install()
       
    67     {
       
    68     // Only proceed if we have the Controller underneath us
       
    69     if (!DUsbClientController::UsbcControllerPointer())
       
    70         {
       
    71         __KTRACE_OPT(KPANIC, Kern::Printf("LDD Install: USB Controller Not Present"));
       
    72         return KErrGeneral;
       
    73         }
       
    74     return SetName(&KUsbScLddName);
       
    75     }
       
    76 
       
    77 
       
    78 //
       
    79 // Return the USB controller capabilities.
       
    80 //
       
    81 void DUsbcScLogDevice::GetCaps(TDes8& aDes) const
       
    82     {
       
    83     TPckgBuf<TCapsDevUsbc> b;
       
    84     b().version = iVersion;
       
    85     Kern::InfoCopy(aDes, b);
       
    86     }
       
    87 
       
    88 // End DUsbcScLogDevice
       
    89 
       
    90 /*****************************************************************************\
       
    91 *   TUsbcScChunkInfo                                                          *
       
    92 *                                                                             *
       
    93 *   Where Chunk information is stored for the channel, and preseved for the   *
       
    94 *   life of the chunk.                                                        *
       
    95 *                                                                             *
       
    96 \*****************************************************************************/
       
    97 
       
    98 void DfcChunkCleanup(TAny*);
       
    99 
       
   100 TUsbcScChunkInfo::TUsbcScChunkInfo(DLogicalDevice* aLdd)
       
   101     :     iChunk(NULL),
       
   102         iCleanup((TDfcFn)&DfcChunkCleanup,this,Kern::SvMsgQue(),0),
       
   103         iChunkMem(NULL),
       
   104         iLdd(aLdd)
       
   105     {
       
   106     iPageNtz = (TInt8)__e32_find_ls1_32(Kern::RoundToPageSize(1));
       
   107     }
       
   108 
       
   109 TInt TUsbcScChunkInfo::CreateChunk(TInt aTotalSize)
       
   110     {
       
   111     // First, reserve an TUint of memory for each of pages needed to hold aTotalSize of memory.
       
   112     // This will form the chunk map, so that we can look up the memory geometry.
       
   113     iAllocatedSize = (aTotalSize>>iPageNtz)*sizeof(TUint);
       
   114     iPhysicalMap = (TUint*) Kern::AllocZ(iAllocatedSize);
       
   115     TInt r;
       
   116     if (iPhysicalMap==NULL)
       
   117         r = KErrNoMemory;
       
   118     else
       
   119         {
       
   120         TChunkCreateInfo chunkInfo;
       
   121         chunkInfo.iType = TChunkCreateInfo::ESharedKernelMultiple;
       
   122         chunkInfo.iMaxSize = aTotalSize;
       
   123         chunkInfo.iMapAttr = EMapAttrCachedMax;
       
   124         chunkInfo.iOwnsMemory = EFalse;
       
   125         chunkInfo.iDestroyedDfc = &iCleanup;
       
   126 
       
   127         TLinAddr chunkMem;
       
   128         r = Kern::ChunkCreate(chunkInfo, iChunk, chunkMem, iChunkMapAttr);
       
   129         iChunkMem = (TInt8*) chunkMem;
       
   130         if (r==KErrNone)
       
   131             iLdd->Open();
       
   132         }
       
   133 
       
   134     return r;
       
   135 }
       
   136 
       
   137 
       
   138 // This method requests closing the chunk.
       
   139 // Note that nothing may happen immediately, as something else may have the chunk open.
       
   140 void TUsbcScChunkInfo::Close()
       
   141 {
       
   142     Kern::ChunkClose(iChunk);    
       
   143 }
       
   144 
       
   145 
       
   146 TInt TUsbcScChunkInfo::ChunkAlloc(TInt aOffset, TInt aSize)
       
   147     {
       
   148     TUint pageMask = (~0)<<iPageNtz;
       
   149     TUint rleMask = ~pageMask;
       
   150     TUint pageSize = rleMask+1;
       
   151     TInt r;
       
   152     TLinAddr physAddr;
       
   153 
       
   154     __KTRACE_OPT(KUSB, Kern::Printf("::chunkalloc  AllocPhysicalRam aSize %d", aSize));
       
   155 
       
   156     r = Epoc::AllocPhysicalRam(aSize, physAddr);
       
   157     __KTRACE_OPT(KUSB, if (r!=KErrNone) Kern::Printf("::chunkalloc AllocPhysicalRam r=%d  (Error!)", r));
       
   158     if (r==KErrNone)
       
   159         {    
       
   160         __KTRACE_OPT(KUSB, Kern::Printf("::chunkalloc ChunkCommitPhysical iChunk 0x%x size(%d), aOffset 0x%x, aSize 0x%x phsAddr 0x%x",
       
   161                                                                                      iChunk, sizeof(DChunk), aOffset, aSize,physAddr ));
       
   162 
       
   163         r = Kern::ChunkCommitPhysical(iChunk, aOffset, aSize, physAddr);
       
   164         __KTRACE_OPT(KUSB, if (r!=KErrNone) Kern::Printf("::chunkalloc ChunkCommitPhysical r=%d  (Error!)", r));
       
   165 
       
   166         if (r!=KErrNone)
       
   167                 Epoc::FreePhysicalRam(physAddr, aSize);
       
   168         else 
       
   169             { // record physical address and length in physical map
       
   170             TInt rle;
       
   171             TInt i=0;
       
   172             for (rle=(aSize>>iPageNtz); rle>0; rle--, i++,physAddr+=pageSize) 
       
   173                 {
       
   174                 __KTRACE_OPT(KUSB, Kern::Printf("::phys offset 0x%x = 0x%x",
       
   175                                                 (aOffset>>iPageNtz)+i,  (physAddr & pageMask) | ((rle>(TInt)rleMask)?(TInt)rleMask:rle)));
       
   176                 iPhysicalMap[(aOffset>>iPageNtz)+i] = (physAddr & pageMask) | ((rle>(TInt)rleMask)?(TInt)rleMask:rle);
       
   177                 }
       
   178             }
       
   179         }
       
   180     else if (r==KErrNoMemory)
       
   181         r = -KErrNoMemory;  // Semi-expected error.
       
   182     return r;
       
   183     }
       
   184 
       
   185 /**
       
   186 This method retrieves the physical address of a given offset into the Chunk, and returns
       
   187 the length of contiguous physical memory from this point.
       
   188 
       
   189 @param aOffset        the offset from the start of the chunk, to be queried.
       
   190 @param aPhysical    a pointer to a TPhysAddr, to be filled with the physical
       
   191                     address of the memory at the given offset.
       
   192 
       
   193 @returns the length of contiguous physical memory from the given offset.
       
   194 */
       
   195 
       
   196 TInt TUsbcScChunkInfo::GetPhysical(TInt aOffset, TPhysAddr* aPhysical)
       
   197     {
       
   198     // Use masks, to retrieve the two components from the physical map, we created of the memory.
       
   199     TUint pageMask = (~0)<<iPageNtz;
       
   200     TUint val =  iPhysicalMap[aOffset>>iPageNtz];
       
   201     *aPhysical=(val & pageMask)+(aOffset & ~pageMask);
       
   202     return ((val & ~pageMask)<<iPageNtz) -  (aOffset & ~pageMask);
       
   203     }
       
   204 
       
   205 
       
   206 // DFC calls this fuction, which invokes the cleanup method.
       
   207 
       
   208 void DfcChunkCleanup(TAny* aChunkInfo)
       
   209     {
       
   210     ((TUsbcScChunkInfo*) aChunkInfo)->ChunkCleanup();
       
   211     }
       
   212 
       
   213 
       
   214 void TUsbcScChunkInfo::ChunkCleanup()
       
   215 {
       
   216     __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChunkInfo::ChunkCleanup()"));
       
   217     TUint physAddr;
       
   218     TInt length;
       
   219     TInt offset = 0;
       
   220     
       
   221     // The part of the field used for the physical page address.
       
   222     TUint pageMask = (~0)<<iPageNtz;
       
   223 
       
   224     // The part of the field used for the run length encoding, of the contiguous pages.
       
   225     TUint rleMask = ~pageMask;
       
   226     TInt records=(iAllocatedSize>>2);
       
   227 
       
   228     while (offset < records) 
       
   229         {
       
   230         physAddr =     iPhysicalMap[offset] & pageMask;
       
   231         length = iPhysicalMap[offset] & rleMask;
       
   232 
       
   233         if (physAddr>0)    
       
   234             Epoc::FreePhysicalRam(physAddr, length);
       
   235 
       
   236         offset += (length>0)?length:1;
       
   237         }
       
   238     Kern::Free(iPhysicalMap);
       
   239 
       
   240     DLogicalDevice* ldd = iLdd;
       
   241     delete this;
       
   242     ldd->Close(NULL);
       
   243 }
       
   244 
       
   245 TInt TUsbcScChunkInfo::New(TUsbcScChunkInfo*& aChunk, TInt aSize, DLogicalDevice* aLdd)
       
   246 {
       
   247     __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChunkInfo::New totalSize %d", aSize));
       
   248 
       
   249     aChunk = new TUsbcScChunkInfo(aLdd);
       
   250     if (aChunk==NULL)
       
   251         {
       
   252         return KErrNoMemory;
       
   253         }
       
   254                     
       
   255     TInt r = aChunk->CreateChunk(aSize);
       
   256     if (r!=KErrNone)
       
   257         {
       
   258         delete aChunk;
       
   259         aChunk=NULL;
       
   260         return r;
       
   261         }
       
   262 
       
   263     __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChunkInfo::New Created at 0x%x",  aChunk->iChunkMem  ));
       
   264     return KErrNone;
       
   265 }
       
   266 
       
   267 // End TUsbcScChunkInfo
       
   268 
       
   269 /*****************************************************************************\
       
   270 *    TUsbcScBuffer                                                            *
       
   271 *                                                                             *
       
   272 *    Represents a buffer, within a chunk.  Each buffers can be used by        *
       
   273 *    differt endpoint on differnt alt settings                                *
       
   274 *                                                                             *
       
   275 \*****************************************************************************/
       
   276 
       
   277 
       
   278 TInt TUsbcScBuffer::Construct(TInt aDirection, DLddUsbcScChannel* aLdd, TInt aBufferOffset, TInt aBufferEndOffset, TInt aMinReadSize, TInt aMaxPacketSize, TInt aMaxReadSize)
       
   279     {
       
   280     TInt r;
       
   281 #ifdef _DEBUG
       
   282     iSequence = aBufferOffset; // Initialized at this, so that each buffer starts with a diffrent sequence number
       
   283 #endif
       
   284     iMinReadSize = aMinReadSize;
       
   285     TInt size = (aBufferEndOffset - aBufferOffset);
       
   286     TInt pageSize = Kern::RoundToPageSize(1);
       
   287     if (aMaxReadSize > 0)
       
   288         iMaxReadSize = aMaxReadSize;
       
   289     else
       
   290         iMaxReadSize = pageSize + ((size/3) & ~(pageSize -1));
       
   291     iLdd = aLdd;
       
   292     iDirection = aDirection;
       
   293     iMode=0;
       
   294     iChunkInfo = aLdd->iChunkInfo;
       
   295     iChunkAddr = (TLinAddr) (aLdd->iChunkInfo->iChunkMem);  //aChunkAddr;
       
   296 
       
   297     TInt headerSize =  sizeof(TUsbcScTransferHeader)-4; // TransferHeader includes 4 bytes of data.
       
   298 
       
   299 
       
   300     TUint maxAlignment; // Note:  This is a mask for max Alignment, 
       
   301 
       
   302     if (aMaxPacketSize)
       
   303         { // EP0 packets are not DMAed, and so dont need ialignment.
       
   304         iAlignMask = ~3;
       
   305         maxAlignment = 3;
       
   306         }
       
   307     else
       
   308          maxAlignment = 1023; // We don't know what the alignment requirement will be until enumeration, so assume worse case.
       
   309 
       
   310     iFirstPacket = aBufferOffset + sizeof(SUsbcScBufferHeader) + headerSize;
       
   311     iFirstPacket = (iFirstPacket + maxAlignment) & ~maxAlignment;
       
   312     
       
   313     iBufferStart = (SUsbcScBufferHeader *) (iChunkAddr+aBufferOffset);
       
   314     iBufferEnd = aBufferEndOffset;
       
   315 
       
   316     if ((iDirection&1)==KUsbcScOut)
       
   317         iHead = iFirstPacket-headerSize;//aBufferOffset + sizeof(SUsbcScBufferHeader);
       
   318     else
       
   319         iSent = 0;
       
   320 
       
   321     iStalled=0;
       
   322     iMaxPacketSize=0;
       
   323     
       
   324     r =  iStatusList.Construct((aDirection==KUsbcScIn)?KUsbcScInRequests:KUsbcScOutRequests, iLdd->iClient);
       
   325     if (!r)
       
   326         {
       
   327         iMaxPacketSize = aMaxPacketSize; // Indicates configured if ep0, otherwise not.
       
   328         }
       
   329     return r;
       
   330     }
       
   331 
       
   332 
       
   333 void TUsbcScBuffer::CreateChunkBufferHeader()
       
   334 {
       
   335     if ((iDirection&1)==KUsbcScOut)
       
   336         {
       
   337         iBufferStart->iHead= iHead;
       
   338         iBufferStart->iTail= iHead; // Initially no data!
       
   339         iBufferStart->iBilTail=iHead;
       
   340         __KTRACE_OPT(KUSB, Kern::Printf("Realize:  iHead 0x%x  bufferHeader 0x%x", iHead,iBufferStart ));
       
   341 
       
   342         // Dont need to round here, as we will round it up on endpoint change. (configuration)
       
   343         }
       
   344 }
       
   345 
       
   346 /*
       
   347 TUsbcScBuffer::StartEndpoint
       
   348 
       
   349 This method sets the nessesary paramenters to the buffer, for use for a particular endpoint.
       
   350 
       
   351 */
       
   352 void TUsbcScBuffer::StartEndpoint(TUsbcRequestCallback* aRequestInfo, TUint aFlags)
       
   353     {
       
   354     __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartEndpoint (0x%x) : ep %d(%d)",this,aRequestInfo->iEndpointNum, aRequestInfo->iRealEpNum));
       
   355     
       
   356     iCallback=aRequestInfo;
       
   357     iMaxPacketSize =  iLdd->iController->EndpointPacketSize(iLdd, aRequestInfo->iRealEpNum);
       
   358     iAlignMask = ~(((iMaxPacketSize+1) & 0xFFFFFFF8)-1);
       
   359     iMode = aFlags;
       
   360     __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartEndpoint : max Packets %d, mask 0x%x flags 0x%x", iMaxPacketSize, iAlignMask, iMode));
       
   361     if ((iDirection&1)==KUsbcScOut)
       
   362         {
       
   363         __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UsbcScOut\n"));
       
   364         // Add dummy packet (doesnt have to be aligned, which avoids what if it changes issue)
       
   365         // And Start next read.
       
   366         iNeedsPacket=KEpIsStarting;
       
   367         }
       
   368     }
       
   369 
       
   370 
       
   371 
       
   372 void TUsbcScBuffer::Destroy()
       
   373 {
       
   374     __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::Destroy()"));
       
   375     Cancel(KErrCancel);
       
   376     if (iLdd->iController && ((iDirection&1)==KUsbcScOut))  
       
   377         {  // Me must cancel reads to LDD to, an there will be no list for the callbacks to look into.
       
   378         iLdd->iController->CancelReadBuffer(iLdd, iCallback->iRealEpNum);
       
   379         }
       
   380     iStatusList.Destroy();
       
   381 }
       
   382 
       
   383 
       
   384 
       
   385 TInt TUsbcScBuffer::StartDataRead()
       
   386 {
       
   387     if (!iMaxPacketSize)
       
   388     {
       
   389         __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataRead() - Not Configured"));
       
   390         return KErrNone;
       
   391     }
       
   392     if (iStatusList.iState!=ENotRunning) 
       
   393         {
       
   394         __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataRead() - Already Stated! (%d)",iStatusList.iState));
       
   395         return KErrNone;
       
   396         }
       
   397 
       
   398     TInt maxLength;
       
   399     TInt freeSpace;
       
   400     TPhysAddr physAddr;
       
   401 
       
   402     // get next request
       
   403     TUsbcScStatusElement* nextJob = iStatusList.Next();
       
   404     if (nextJob == NULL)
       
   405         {
       
   406         __KTRACE_OPT(KUSB, Kern::Printf("No more jobs"));
       
   407         if (iMode && KUsbScCoupledRead)
       
   408             return KErrEof;
       
   409         iStatusList.iState=EReadingAhead;
       
   410         }
       
   411     else
       
   412         iStatusList.iState=EInProgress;
       
   413 
       
   414     TInt tail = iBufferStart->iTail;
       
   415     TInt headerSize =  sizeof(TUsbcScTransferHeader)-4; // TransferHeader includes 4 bytes of data.
       
   416     maxLength = iChunkInfo->GetPhysical(iHead + headerSize, &physAddr); //returns all the bytes available after iHead + headerSize)
       
   417 
       
   418     __ASSERT_DEBUG(maxLength>0,Kern::Fault("TUsbcScBuffer::StartDataRead(", __LINE__)); 
       
   419 
       
   420 
       
   421     if (tail>iHead)  //  # # # H _ _ _ T # # # #
       
   422         {
       
   423         __KTRACE_OPT(KUSB,Kern::Printf("TUsbcScBuffer::StartDataRead() - tail 0x%x>head 0x%x, maxlength 0x%x", tail, iHead, maxLength));
       
   424 
       
   425         freeSpace = (tail & iAlignMask) - (iHead +headerSize + (~iAlignMask+1) );  // Cant read right up to last buffer, or head/tail will cross.
       
   426 
       
   427         if (freeSpace<iMinReadSize)
       
   428             {
       
   429             iStatusList.iState=ENotRunning;
       
   430             __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataRead() - Stall!!"));
       
   431             return KErrOverflow;                 // Read STALL !! !! !!
       
   432             }
       
   433 
       
   434         if (freeSpace<maxLength)
       
   435             maxLength = freeSpace;
       
   436         }
       
   437     if (maxLength> iMaxReadSize) 
       
   438         maxLength =  iMaxReadSize;
       
   439     // else  tail<iHead (or empty)      _ _ _ T # # # H _ _ _ _
       
   440     // We would not have set iHead here if too small. So must be ok.
       
   441         
       
   442     __ASSERT_DEBUG(maxLength>=iMinReadSize,Kern::Fault("TUsbcScBuffer::StartDataRead(", __LINE__)); 
       
   443 
       
   444     TUint8* data = ((TUsbcScTransferHeader *) (iHead + iChunkAddr))->iData.b;
       
   445     // set up callback stucture
       
   446 
       
   447     iCallback->SetRxBufferInfo(data, physAddr, iIndexArray, iSizeArray,maxLength);
       
   448     TInt r;
       
   449     // Go!!
       
   450     r = iLdd->iController->SetupReadBuffer(*iCallback);
       
   451     if (r!=KErrNone)
       
   452         {
       
   453         __KTRACE_OPT(KUSB,Kern::Printf("SetupReadBuffer Error: %d, RT %d",r, iStatusList.iState));
       
   454         iStatusList.Complete(r);
       
   455         }
       
   456     // After this, TUsbcScEndpoint::RequestCallback is called in a DFC.
       
   457     // This in turn calls either TUsbcScBuffer::CompleteRead.
       
   458     return KErrNone;
       
   459 }
       
   460 
       
   461 
       
   462 void TUsbcScBuffer::CompleteRead(TBool aStartNextRead)
       
   463 {
       
   464     __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::CompleteRead buff=%x",this));
       
   465 
       
   466     // The first packet always contains the total #of bytes
       
   467     const TInt byteCount = iCallback->iPacketSize[0];
       
   468     const TInt packetCount = iCallback->iRxPackets;
       
   469      iCallback->iRxPackets=0;
       
   470     TUint flags = 0;
       
   471 
       
   472     if (iCallback->iPacketSize[packetCount - 1] < (TUint) iMaxPacketSize)
       
   473         flags = KUsbcScShortPacket;
       
   474 
       
   475     UpdateBufferList(byteCount, flags, aStartNextRead);
       
   476 }
       
   477 
       
   478 
       
   479 // This method "submits" the current transfer, and starts off the next read.
       
   480 
       
   481 void TUsbcScBuffer::UpdateBufferList(TInt aByteCount,TUint aFlags, TBool aStartNextRead)
       
   482     {
       
   483 
       
   484     __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst aByteCount %d, flags 0x%x iHead 0x%x", aByteCount, aFlags, iHead));
       
   485 
       
   486     TInt headerSize =  sizeof(TUsbcScTransferHeader)-4; // TransferHeader includes 4 bytes of data.
       
   487     TLinAddr dummy;
       
   488     __KTRACE_OPT(KUSB, Kern::Printf("iHead 0x%x headerSize 0x%x",iHead, headerSize));
       
   489 
       
   490     // Find iNext
       
   491 
       
   492     TInt next =  iHead +  headerSize + aByteCount; // next unused byte in buffer.
       
   493     TInt maxLength; 
       
   494 
       
   495     // This may take a few loops before we settle on a value.
       
   496     do 
       
   497         {
       
   498         // round up.
       
   499         next = (next + headerSize + ~iAlignMask) & iAlignMask;
       
   500         maxLength = iChunkInfo->GetPhysical(next, &dummy);
       
   501 
       
   502         __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst  next %x  buffer end %x min-read: %x  maxRun %x", next, iBufferEnd, iMinReadSize, maxLength));
       
   503         // At the end of the buffer - wrap it if needbe.
       
   504         if ((TUint)(next + iMinReadSize) > iBufferEnd)
       
   505             {
       
   506             next = iFirstPacket;
       
   507             continue;
       
   508             }
       
   509         // Not enough space, move onto next block.
       
   510         if (maxLength<iMinReadSize) 
       
   511             {
       
   512             next+=maxLength;
       
   513             __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst Skip exhausted block. next %x max %d", next, maxLength));
       
   514             continue;
       
   515             }
       
   516         }
       
   517     while (EFalse);
       
   518 
       
   519     __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst next (pre deduct): %x, Fill in header at head: 0x%x,  BuffStart: 0x%x.", next, iHead, iBufferStart));
       
   520     
       
   521     next -=  headerSize;  // Move next back from the data start position, to the header start.
       
   522 
       
   523     TUsbcScTransferHeader* header = (TUsbcScTransferHeader*) (iHead + iChunkAddr);
       
   524     
       
   525 // Create Header
       
   526 #ifdef _DEBUG
       
   527     header->iHashId=59*(iLdd->iAlternateSetting+1)+iCallback->iRealEpNum; // Alt setting realated....
       
   528     header->iSequence=iSequence;
       
   529     iSequence++;
       
   530 #endif
       
   531     header->iBytes=aByteCount;
       
   532     header->iNext=next;
       
   533     header->iAltSettingSeq=iLdd->iAsSeq;
       
   534     header->iAltSetting=iLdd->iAlternateSetting;
       
   535     header->iFlags=aFlags;
       
   536     __KTRACE_OPT(KUSB, Kern::Printf("We set next to 0x%x", next));
       
   537 
       
   538     iStatusList.iState=ENotRunning;
       
   539     if (next==iBufferStart->iTail) //or (othwise is as good as full)
       
   540         {
       
   541             iStalled=next;
       
   542         }
       
   543     else
       
   544         {
       
   545 
       
   546         __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst StartRead?? "));
       
   547         TInt oldHead=iHead;
       
   548         iHead = next;
       
   549 
       
   550         if ((aStartNextRead) && (StartDataRead() == KErrOverflow))
       
   551             { // Oh crumbs, set state as slalled.
       
   552             if (oldHead != iBufferStart->iBilTail) 
       
   553                 // If user has not read everything in the buffer
       
   554                 // then set up a stall, so that ldd get to be woken early
       
   555                 {
       
   556                 iStalled=next;
       
   557                 iHead=oldHead;
       
   558                 }
       
   559             else // otherwise if everything is read
       
   560                 // no choice but to return what we have
       
   561                 {
       
   562                 iBufferStart->iHead = iHead;
       
   563                 }
       
   564             }
       
   565         else
       
   566             {
       
   567             iBufferStart->iHead = next;
       
   568             __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst Compleating\n"));
       
   569             }
       
   570         // Complete userside
       
   571         iStatusList.Complete();
       
   572         }  
       
   573     }
       
   574 
       
   575 void TUsbcScBuffer::PopStall()
       
   576     {
       
   577     if (iStalled==iBufferStart->iTail)
       
   578         return;  // Still stalled.
       
   579 
       
   580     if (iStalled!=-1) // If not Alt packet only stall
       
   581     {
       
   582         // pop off packet    
       
   583         iHead = iStalled;
       
   584      }
       
   585     iStalled=0;
       
   586     // If Alt setting of the popped packet is different to now
       
   587     // Add alt setting change packet.
       
   588 
       
   589 
       
   590     if (StartDataRead() == KErrOverflow)
       
   591     {
       
   592         __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::PopStall Warning: Transfer was freed, but still no space!\n"));
       
   593     }
       
   594 
       
   595     iBufferStart->iHead = iHead;
       
   596     }
       
   597 
       
   598 
       
   599 
       
   600 void TUsbcScBuffer::StartDataWrite()
       
   601     {
       
   602     
       
   603     __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataWrite()"));
       
   604     TUsbcScStatusElement* nextJob = iStatusList.Next();
       
   605     TBool zlpReqd;
       
   606     TInt length;
       
   607     TUint start;
       
   608     TUint8* startAddr;
       
   609     TInt maxLength;
       
   610     TPhysAddr physAddr;
       
   611     TInt r;
       
   612     if (!iMaxPacketSize)
       
   613     {
       
   614         __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataWrite() - Not Configured"));
       
   615         return;
       
   616     }
       
   617 
       
   618     if (nextJob == NULL)
       
   619         {
       
   620         __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataWrite() - No more jobs d=%d", iDirection));
       
   621         if (iDirection==KUsbcScBiIn) // assume this is EP0, if this is true.
       
   622             {
       
   623             __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataWrite() Queue Read on EP0."));    
       
   624             // Start other read again.
       
   625             iLdd->iBuffers[iLdd->iEP0OutBuff].StartDataRead();
       
   626             }
       
   627         }
       
   628     else
       
   629         {
       
   630         if (iStatusList.iState==ENotRunning)
       
   631             iSent=0;
       
   632         iStatusList.iState=EInProgress;
       
   633 
       
   634         start = nextJob->iStart;
       
   635         startAddr = (TUint8*) (start + ((TUint) (iChunkInfo->iChunkMem)));
       
   636 
       
   637         length = nextJob->iLength;
       
   638         zlpReqd = (nextJob->iFlags & KUsbcScWriteFlagsZlp) !=0;
       
   639         // get max read length
       
   640         maxLength = iChunkInfo->GetPhysical( start, &physAddr); 
       
   641 
       
   642         if (maxLength < length)
       
   643             {
       
   644                 // modify request.
       
   645                 nextJob->iStart += maxLength;
       
   646                 nextJob->iLength -= maxLength;
       
   647                 // start this request.
       
   648                 iStatusList.iState=EFramgementInProgress;
       
   649                 zlpReqd=EFalse;
       
   650                 length =  maxLength;
       
   651             }
       
   652 
       
   653         if (iDirection==KUsbcScBiIn) // this is for EP0
       
   654             {
       
   655             iLdd->iController->CancelReadBuffer(iLdd, iCallback->iRealEpNum);
       
   656             iLdd->iBuffers[iLdd->iEP0OutBuff].iStatusList.iState=ENotRunning;
       
   657             }
       
   658         
       
   659         iCallback->SetTxBufferInfo(startAddr, physAddr, length);
       
   660         iCallback->iZlpReqd = zlpReqd;
       
   661         r = iLdd->iController->SetupWriteBuffer(*iCallback);
       
   662         if (r!=KErrNone)
       
   663             {
       
   664             __KTRACE_OPT(KUSB, Kern::Printf("SetupWriteBUffer Error: %d",r));
       
   665             iStatusList.Complete(r);
       
   666             }
       
   667         }
       
   668 
       
   669     }
       
   670 
       
   671 void TUsbcScBuffer::CompleteWrite()
       
   672     {
       
   673     TInt error = iCallback->iError;
       
   674     __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::CompleteWrite buff=%x, err=%d",this, error));
       
   675     iSent+= iCallback->iTxBytes;
       
   676 
       
   677     // More to send?
       
   678     if (error || iStatusList.iState!=EFramgementInProgress)
       
   679         {
       
   680         // complete request with error (if one).
       
   681         // Some data could have been transmitted, even with an error. 
       
   682         iStatusList.Complete(error);
       
   683         }
       
   684 
       
   685     // Start next request, or next part of this one.
       
   686     StartDataWrite();
       
   687     
       
   688     }
       
   689 
       
   690 // Cancels the current request's callback.
       
   691 // This is not to say it will cancel the actual operation,
       
   692 // However it will cancel any further sections of the user perceived operation
       
   693 // that are not yet started.
       
   694 void TUsbcScBuffer::Cancel(TInt aErrorCode)
       
   695     {
       
   696     iStatusList.CancelQueued();
       
   697     if (iLdd->iController && ((iDirection&1)==KUsbcScIn))
       
   698         {
       
   699         iLdd->iController->CancelWriteBuffer(iLdd, iCallback->iRealEpNum);
       
   700         }
       
   701 
       
   702     iStatusList.Complete(aErrorCode);
       
   703     }
       
   704 
       
   705 void TUsbcScBuffer::Ep0CancelLddRead()
       
   706     {
       
   707     // Stopping a read isn't as easy as one might think.
       
   708     // We cancel the callback, but then check if any data was received (but not returned to us).
       
   709     // If so, we must de-queue the request, and call the completion code.
       
   710     
       
   711     iLdd->iController->CancelReadBuffer(iLdd, iCallback->iRealEpNum);
       
   712     if (iCallback->iRxPackets) // received data?
       
   713         {
       
   714         // remove DFC (if infact sent)
       
   715         iCallback->iDfc.Cancel();
       
   716 
       
   717         // process the callback now, but dont start another
       
   718         CompleteRead(EFalse);
       
   719         }
       
   720     }
       
   721 
       
   722 void TUsbcScBuffer::SendEp0StatusPacket(TInt aState)
       
   723 {
       
   724     __KTRACE_OPT(KUSB, Kern::Printf(" TUsbcScBuffer::SendEp0StatusPacket(%d)", aState));
       
   725 
       
   726     // We need to add a packet to the buffer, so we must stop the pending read, and start
       
   727     // another after we have added out packet.  
       
   728     Ep0CancelLddRead();
       
   729 
       
   730     TUint* state = ((TUsbcScTransferHeader *) (iHead + iChunkAddr))->iData.i;
       
   731     *state = aState;
       
   732     UpdateBufferList(4,KUsbcScStateChange);
       
   733 }
       
   734 
       
   735 // End TUsbcScBuffer
       
   736 
       
   737 /*****************************************************************************\
       
   738 *    TUsbcScStatusList                                                        *
       
   739 *                                                                             *
       
   740 *    This is a list of read or write requests, containing user status         *
       
   741 *    requests, that should later be completed.                                *
       
   742 *                                                                             *
       
   743 \*****************************************************************************/
       
   744 
       
   745 /**
       
   746 Constructor for TUsbcScStatusList.
       
   747 
       
   748 @param aSize    is the number of requests to allow at any one time.  This value
       
   749                 must be a power of two, for correct operation.
       
   750 
       
   751 @returns KErrNoMemory if memory allocation failure, otherwise KErrNone.
       
   752 */
       
   753 
       
   754 TInt TUsbcScStatusList::Construct(TInt aSize, DThread* aClient)
       
   755     {
       
   756     iSize=aSize;
       
   757     iHead = 0;
       
   758     iLength = 0;
       
   759     iClient = aClient;
       
   760     iElements=(TUsbcScStatusElement *) Kern::AllocZ(sizeof(TUsbcScStatusElement)*aSize);
       
   761     return (iElements==NULL)?KErrNoMemory:KErrNone;    
       
   762     };
       
   763 
       
   764 
       
   765 // StatusList must be inactive before destroying.
       
   766 void TUsbcScStatusList::Destroy()
       
   767     {
       
   768     if (iState!=ENotRunning)
       
   769         Kern::Fault("TUsbcScStatusList::Destroy", __LINE__);
       
   770     if (iElements)
       
   771         {
       
   772         Kern::Free(iElements);    
       
   773         iElements=NULL;
       
   774         }
       
   775     iClient=NULL;
       
   776 }
       
   777 
       
   778 void TUsbcScStatusList::Pop()
       
   779     {
       
   780     if (iLength>0)
       
   781         {
       
   782         iLength--;
       
   783         iHead = ((iHead+1) & (iSize-1));
       
   784         }
       
   785     }
       
   786 
       
   787 TUsbcScStatusElement* TUsbcScStatusList::Next()
       
   788     {
       
   789     return (iLength==0)?NULL:&(iElements[iHead]);
       
   790     }
       
   791 
       
   792 TInt TUsbcScStatusList ::Add(TRequestStatus* aStatus, TInt aLength, TUint aStart, TUint aFlags)
       
   793     {
       
   794     __KTRACE_OPT(KUSB,Kern::Printf("Adding request.  iLength %d  iSize %d", iLength, iSize));
       
   795     if (iLength<iSize)
       
   796         {
       
   797         TUsbcScStatusElement& e = iElements[((iHead+iLength) & (iSize-1))];
       
   798         e.iStatus = aStatus;
       
   799         e.iLength = aLength;
       
   800         e.iStart = aStart;
       
   801         e.iFlags = aFlags;
       
   802         iLength++;
       
   803         __KTRACE_OPT(KUSB,Kern::Printf("Adding request.  new iLength %d", iLength));
       
   804 
       
   805         return KErrNone;
       
   806         }
       
   807     else
       
   808         return KErrInUse;
       
   809     }
       
   810 
       
   811 
       
   812 
       
   813 // This method cancels any requests that have yet to be started.
       
   814 
       
   815 void TUsbcScStatusList::CancelQueued(TInt aError)
       
   816 {
       
   817     if ((iLength==0) || ((iState!=ENotRunning) && (iLength==1)))  // Nothing to do.
       
   818         return;  
       
   819     TInt elements2Complete = iLength - (iState?1:0);
       
   820     TInt head = iHead;
       
   821     iLength = 0;
       
   822     if (iState)    // If (iState != ENotRunning), complete all elements excepting the one at head
       
   823         {
       
   824         head = ((head+1) & (iSize-1)); // To iterate through the queue
       
   825         iLength = 1;
       
   826         }
       
   827     // complete them all.
       
   828     for (; elements2Complete>0; elements2Complete--)
       
   829           {
       
   830         Kern::RequestComplete(iClient, iElements[head].iStatus, aError);
       
   831         head = ((head+1) & (iSize-1)); 
       
   832           }
       
   833     
       
   834 }
       
   835 
       
   836 
       
   837 /* This method Completes the head status request, and pops it from its list.
       
   838 This version of Complete is to be used in cases where the next request is not
       
   839 chained - usually because of an error.
       
   840 
       
   841 @Param aError - the code to complete with.
       
   842 
       
   843 returns KErrNotFound if there was no request to complete
       
   844 */
       
   845 
       
   846 
       
   847 TInt TUsbcScStatusList::Complete(TInt aError)
       
   848     {
       
   849     if (iState==ENotRunning)
       
   850         {
       
   851         __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScStatusList::Complete() - iState == ENotRunning!"));
       
   852         }
       
   853      else
       
   854         {
       
   855         iState=ENotRunning;
       
   856         if (iLength==0)
       
   857             return KErrNotFound;
       
   858 
       
   859         Kern::RequestComplete(iClient, iElements[iHead].iStatus, aError);
       
   860 
       
   861         iLength--;
       
   862         iHead = ((iHead+1) & (iSize-1));
       
   863         }
       
   864     return KErrNone;
       
   865     }
       
   866 
       
   867 
       
   868 /* This method Completes the head status request, and pops it from its list. (If found.)
       
   869 This version of Complete is to be used in cases where the request is successful, and
       
   870  next request after this has (if present) been chained.
       
   871 */
       
   872 
       
   873 void TUsbcScStatusList::Complete()
       
   874     {
       
   875     if (iLength==0)
       
   876         return;
       
   877     __KTRACE_OPT(KUSB, Kern::Printf("Completing request.  iLength %d", iLength));
       
   878 
       
   879     Kern::RequestComplete(iClient, iElements[iHead].iStatus, KErrNone);
       
   880 
       
   881     iLength--;
       
   882     iHead = ((iHead+1) & (iSize-1));
       
   883     }
       
   884 
       
   885 // End TUsbcScStatusList
       
   886 
       
   887 /*****************************************************************************\
       
   888 *   TRealizeInfo                                                              *
       
   889 *                                                                             *
       
   890 *   Used by DLddUsbcScChannel::RealizeInterface to set up the chunk           *
       
   891 *                                                                             *
       
   892 \*****************************************************************************/
       
   893 
       
   894 // Init
       
   895 //
       
   896 // This method works out the number potential maximum number of endpoints
       
   897 // and the number of alt settings.  With this information it allocs
       
   898 // the necessary space for the given stucture to store information about
       
   899 // the endpoints.  
       
   900 // This is intended to be called by RealizeInterface.  This stucture is
       
   901 // intended to be only temporary, and the space will be freed with Free()
       
   902 // before RealizeInteface has finished.
       
   903 
       
   904 void TRealizeInfo::Init(TUsbcScAlternateSettingList* aAlternateSettingList)
       
   905 {
       
   906     iAlternateSettingList = aAlternateSettingList;
       
   907     iMaxEndpoints=0;
       
   908     iTotalSize   =0;
       
   909     iTotalBuffers=0;
       
   910     iAltSettings =0;
       
   911     __KTRACE_OPT(KUSB, Kern::Printf("Realize: work out max endpoint"));
       
   912     // Work out max endpoints and number of alternate settings.
       
   913 
       
   914     if (iAlternateSettingList)
       
   915         {
       
   916         TUsbcScAlternateSetting* alt = iAlternateSettingList->iHead;
       
   917         while (alt != NULL) 
       
   918             {
       
   919             iAltSettings++;
       
   920             if (alt->iNumberOfEndpoints>iMaxEndpoints)
       
   921                 iMaxEndpoints = alt->iNumberOfEndpoints;
       
   922             // could work out in/out specifics, but unnecessary.
       
   923             alt = alt->iNext;
       
   924             };
       
   925         }
       
   926     
       
   927     // Alloc some temporary working space for temp endpoint metadata 
       
   928     __KTRACE_OPT(KUSB, Kern::Printf("Realize: Alloc temp.  Maxendpoints %d", iMaxEndpoints));
       
   929     TInt inout;
       
   930     for (inout=KUsbcScIn; inout<KUsbcScDirections; inout++)
       
   931         {
       
   932         iBufs[inout].iEp = (TUsbcScEndpoint **) Kern::AllocZ(iAltSettings*iMaxEndpoints*sizeof(TUsbcScEndpoint *));
       
   933         iBufs[inout].iSizes = (TInt *) Kern::AllocZ(iMaxEndpoints*sizeof(TInt));
       
   934         }
       
   935 }
       
   936 
       
   937 // CopyAndSortEndpoints
       
   938 //
       
   939 // This method copies pointers to the endpoint records into TRealizeInfo
       
   940 // such that they are sorted in order of size per alt setting.
       
   941 // In and Out endpoints are separated, and kept separate.
       
   942 // The provided data structure is assumed to have been initialised with
       
   943 // Realize_InitRealizeInfo. 
       
   944 //
       
   945 // Return KErrArgument if the direction field is neither In or Out.
       
   946 //
       
   947 
       
   948 TInt TRealizeInfo::CopyAndSortEndpoints()
       
   949     {
       
   950     __KTRACE_OPT(KUSB, Kern::Printf("Realize: copy And sort"));
       
   951 
       
   952     TInt altSetting = 0;
       
   953     TInt endpointOffs;
       
   954     TInt endpoint;
       
   955     TInt altEp;
       
   956     TInt inout;
       
   957     TBool placed;
       
   958     TUsbcScAlternateSetting* alt;
       
   959     TEndpointSortBufs* bufsd;
       
   960 
       
   961     if (iAlternateSettingList)
       
   962         {
       
   963         for (alt = iAlternateSettingList->iHead;alt!=NULL;alt = alt->iNext )
       
   964             {        
       
   965             __KTRACE_OPT(KUSB, Kern::Printf("Realize:   AlternateSetting %x", alt));
       
   966 
       
   967             iBufs[KUsbcScIn].iEps =0;
       
   968             iBufs[KUsbcScOut].iEps =0;
       
   969 
       
   970             // For alt setting, iterate eps
       
   971             for (altEp=1; altEp <= alt->iNumberOfEndpoints; altEp++)
       
   972                 {
       
   973                 __KTRACE_OPT(KUSB, Kern::Printf("Realize:     Endpoint to add: %d",altEp));
       
   974 
       
   975                 TUsbcScEndpoint* nextEp = alt->iEndpoint[altEp];
       
   976 
       
   977                 __KTRACE_OPT(KUSB, Kern::Printf("Realize:      ep Buffer Size: %d",nextEp->EndpointInfo()->iBufferSize));
       
   978                 
       
   979                 inout = (nextEp->EndpointInfo()->iDir==UsbShai::KUsbEpDirIn)?KUsbcScIn:
       
   980                         (nextEp->EndpointInfo()->iDir==UsbShai::KUsbEpDirOut)?KUsbcScOut:KUsbcScUnknown;
       
   981                 if (inout==KUsbcScUnknown)
       
   982                     {
       
   983                     __KTRACE_OPT(KUSB, Kern::Printf("Realize:     KUsbcScUnknown %x",nextEp->EndpointInfo()->iDir));
       
   984                     return KErrArgument;
       
   985                     }
       
   986 
       
   987                 bufsd = &(iBufs[inout]);
       
   988                 __KTRACE_OPT(KUSB, Kern::Printf("Realize:      ep direction: %x # endpoints %d", inout, bufsd->iEps));
       
   989 
       
   990 
       
   991                 // find and position ep, and insert.
       
   992 
       
   993                 if (bufsd->iEps==0) // First entry.
       
   994                     {
       
   995                     __KTRACE_OPT(KUSB, Kern::Printf("Realize:       Add first endpoint"));
       
   996                     endpointOffs = altSetting*iMaxEndpoints;
       
   997                     bufsd->iEp[endpointOffs] = nextEp;
       
   998                     }
       
   999                 else
       
  1000                     {
       
  1001                     placed = EFalse;
       
  1002                     // Move down the list, until we find the right place.
       
  1003                     for (endpoint=bufsd->iEps-1; endpoint>-1; endpoint--)
       
  1004                         {
       
  1005                         endpointOffs = altSetting*iMaxEndpoints + endpoint;
       
  1006                         if (bufsd->iEp[endpointOffs]->EndpointInfo()->iBufferSize < nextEp->EndpointInfo()->iBufferSize)
       
  1007                             {
       
  1008                             __KTRACE_OPT(KUSB, Kern::Printf("Realize:       Shift Endpoint %d", endpoint));
       
  1009         
       
  1010                             bufsd->iEp[endpointOffs+1] = bufsd->iEp[endpointOffs];
       
  1011                             }
       
  1012                         else
       
  1013                             {
       
  1014                             __KTRACE_OPT(KUSB, Kern::Printf("Realize:       Insert After Endpoint %d", endpoint));
       
  1015 
       
  1016                             bufsd->iEp[endpointOffs+1] = nextEp;
       
  1017                             placed = ETrue;
       
  1018                             break;
       
  1019                             }
       
  1020                         } // end for endpoint
       
  1021                         if (!placed) // if we didn't place it, it must be the biggest so far, so goes at the top.
       
  1022                             bufsd->iEp[0] = nextEp;
       
  1023                     } // endif
       
  1024                 bufsd->iEps++;            
       
  1025                 } // for altEp
       
  1026                 altSetting++;
       
  1027             } // for alt
       
  1028         }// if iAltsettingList
       
  1029     return KErrNone;
       
  1030     }
       
  1031 
       
  1032 // CalcBuffSizes
       
  1033 //
       
  1034 // This works out the sizes of all the buffers, and stores the result in aBufInfo
       
  1035 // based on the buffer information provided in the same structure.
       
  1036 // Realize_CopyAndSortEndpoints is used to fill the structure with the informaition
       
  1037 // required.
       
  1038 
       
  1039 void TRealizeInfo::CalcBuffSizes()
       
  1040     {
       
  1041     __KTRACE_OPT(KUSB, Kern::Printf("Realize: Calculate Buffers"));
       
  1042 
       
  1043     TInt endpoint;
       
  1044     TInt inout;
       
  1045     TInt altSetting;
       
  1046     TUsbcScEndpoint* nextEp;
       
  1047     TInt bufferSize;
       
  1048     TEndpointSortBufs* bufsd;
       
  1049 
       
  1050     for (inout=KUsbcScIn; inout<KUsbcScDirections; inout++)
       
  1051         {
       
  1052         __KTRACE_OPT(KUSB, Kern::Printf("Realize:   Direction: %d", inout));
       
  1053 
       
  1054 
       
  1055         bufsd = &(iBufs[inout]);
       
  1056         // for each row, ie, buffer, find largest buffer need.
       
  1057         for (endpoint=0; endpoint<iMaxEndpoints; endpoint++)
       
  1058             {
       
  1059             __KTRACE_OPT(KUSB, Kern::Printf("Realize:     endpoint %d", endpoint));
       
  1060             TInt bufMaxSize=0;
       
  1061             for (altSetting=0; altSetting< iAltSettings; altSetting++)
       
  1062                 {
       
  1063                 __KTRACE_OPT(KUSB, Kern::Printf("Realize:       altSetting %d", altSetting));
       
  1064                 nextEp= bufsd->iEp[altSetting* iMaxEndpoints + endpoint];
       
  1065                 if (nextEp!=NULL)
       
  1066                     {
       
  1067                     bufferSize = nextEp->EndpointInfo()->iBufferSize;
       
  1068                     __KTRACE_OPT(KUSB, Kern::Printf("Realize:       comparing size %d", bufferSize));
       
  1069                     if (bufferSize> bufMaxSize)
       
  1070                          bufMaxSize = bufferSize;
       
  1071                     }
       
  1072                 } // for altsetting
       
  1073             __KTRACE_OPT(KUSB, Kern::Printf("Realize:     bufMaxSize %d", bufMaxSize));
       
  1074             bufsd->iSizes[endpoint] = bufMaxSize;
       
  1075             if (bufMaxSize>0) 
       
  1076                 {
       
  1077                 iTotalSize += bufsd->iSizes[endpoint];
       
  1078                 iTotalBuffers++;
       
  1079                 }
       
  1080             } // for endpoint
       
  1081         } // for in/out    
       
  1082 }
       
  1083 
       
  1084 // Free
       
  1085 //
       
  1086 // Cleans up after Init()
       
  1087 
       
  1088 void TRealizeInfo::Free()
       
  1089     {
       
  1090     TInt inout;
       
  1091     for (inout=KUsbcScIn; inout<KUsbcScDirections; inout++)
       
  1092         {
       
  1093         Kern::Free(iBufs[inout].iEp);
       
  1094         Kern::Free(iBufs[inout].iSizes);
       
  1095         }
       
  1096     }
       
  1097 
       
  1098 // End TRealizeInfo
       
  1099 
       
  1100 
       
  1101 // LayoutChunkHeader
       
  1102 //
       
  1103 // Sets up some geometry for the chunk;
       
  1104 
       
  1105 void TRealizeInfo::LayoutChunkHeader(TUsbcScChunkInfo* aChunkInfo)
       
  1106 { 
       
  1107     // First set up the indexes to the header structures.
       
  1108     TUsbcScChunkHdrOffs* chkHdr = (TUsbcScChunkHdrOffs*) aChunkInfo->iChunkMem;
       
  1109 
       
  1110     chkHdr->iBuffers = sizeof(TUsbcScChunkHdrOffs); // First struct just after this one.
       
  1111     iChunkStuct = (TUsbcScChunkBuffersHeader*) ( (TInt) aChunkInfo->iChunkMem + chkHdr->iBuffers);
       
  1112 
       
  1113     // Store number of buffers in chunk
       
  1114     iChunkStuct->iRecordSize = sizeof(TUsbcScBufferRecord);
       
  1115     iChunkStuct->iNumOfBufs=iTotalBuffers;
       
  1116 
       
  1117     iAltSettingsTbl = (TUsbcScChunkAltSettingHeader*) &(iChunkStuct->iBufferOffset[(iTotalBuffers+2)*sizeof(TUsbcScBufferRecord)]); // 2 extra for EP0 in and out.
       
  1118 
       
  1119     chkHdr->iAltSettings = (TUint) iAltSettingsTbl - (TUint) aChunkInfo->iChunkMem;
       
  1120 
       
  1121     iAltSettingsTbl->iEpRecordSize = sizeof(TUint);
       
  1122     iAltSettingsTbl->iNumOfAltSettings = iAltSettings;
       
  1123 
       
  1124 
       
  1125     TInt tableOffset  = (TUint) iAltSettingsTbl->iAltTableOffset - (TUint) aChunkInfo->iChunkMem + iAltSettings*sizeof(TInt);
       
  1126     __KTRACE_OPT(KUSB, Kern::Printf("Realize: table offset: 0x%x, altTble %x iChnkMem %x altSettings %x",tableOffset, iAltSettingsTbl, aChunkInfo->iChunkMem, iAltSettings ));
       
  1127 
       
  1128     __KTRACE_OPT(KUSB, Kern::Printf("Realize: populate chunk - create alt settings table"));
       
  1129 
       
  1130     // Create alt settings table.  Set each element of altsettings table, to each induivatual alt setting table.
       
  1131     // then fill in the number of endpoints for that alt setting, in the table.
       
  1132 
       
  1133     TInt* noEpForAlt;
       
  1134     TInt altSetting;
       
  1135     TUsbcScAlternateSetting* alt;
       
  1136     if (iAlternateSettingList)
       
  1137         {
       
  1138         alt = iAlternateSettingList->iHead;
       
  1139         for (altSetting=0; altSetting<iAltSettings; altSetting++) 
       
  1140             {
       
  1141                 __KTRACE_OPT(KUSB, Kern::Printf("Realize:   altSetting %d, tableOffset %d", altSetting, tableOffset));
       
  1142 
       
  1143                 iAltSettingsTbl->iAltTableOffset[altSetting] = tableOffset;
       
  1144                 noEpForAlt = (TInt*) &aChunkInfo->iChunkMem[tableOffset];
       
  1145              
       
  1146                 *noEpForAlt = alt->iNumberOfEndpoints;  // Set NumberofEndpoints field in Altsetting table
       
  1147                 tableOffset+= sizeof(TInt)+ alt->iNumberOfEndpoints*sizeof(TUsbcScHdrEndpointRecord);
       
  1148                 alt = alt->iNext;
       
  1149             }
       
  1150         }        
       
  1151 
       
  1152 } // end LayoutChunkHeader
       
  1153 
       
  1154 
       
  1155 
       
  1156 /*****************************************************************************\
       
  1157 *   DLddUsbcScChannel                                                         *
       
  1158 *                                                                             *
       
  1159 *   Inherits from DLogicalDevice, the USB Shared Chunk LDD factory class      *
       
  1160 *                                                                             *
       
  1161 \*****************************************************************************/
       
  1162 
       
  1163 //
       
  1164 // Constructor
       
  1165 //
       
  1166 DLddUsbcScChannel::DLddUsbcScChannel()
       
  1167     : iValidInterface(EFalse),
       
  1168       iAlternateSettingList(NULL),
       
  1169       iEndpoint(NULL),
       
  1170       iCompleteAllCallbackInfo(this, DLddUsbcScChannel::EmergencyCompleteDfc, KUsbRequestCallbackPriority),
       
  1171       iStatusChangePtr(NULL),
       
  1172       iStatusCallbackInfo(this, DLddUsbcScChannel::StatusChangeCallback, KUsbRequestCallbackPriority),
       
  1173       iEndpointStatusChangePtr(NULL),
       
  1174       iEndpointStatusCallbackInfo(this, DLddUsbcScChannel::EndpointStatusChangeCallback,
       
  1175                                   KUsbRequestCallbackPriority),
       
  1176       iOtgFeatureChangePtr(NULL),
       
  1177       iOtgFeatureCallbackInfo(this, DLddUsbcScChannel::OtgFeatureChangeCallback, KUsbRequestCallbackPriority),
       
  1178       iNumberOfEndpoints(0),
       
  1179       iDeviceState(UsbShai::EUsbPeripheralStateUndefined),
       
  1180       iOwnsDeviceControl(EFalse),
       
  1181       iAlternateSetting(0),
       
  1182       iAsSeq(0),
       
  1183       iStatusFifo(NULL),
       
  1184       iUserKnowsAltSetting(ETrue),
       
  1185       iDeviceStatusNeeded(EFalse),
       
  1186       iChannelClosing(EFalse),
       
  1187       iRealizeCalled(EFalse),
       
  1188       iChunkInfo(NULL),
       
  1189       iNumBuffers(-1),
       
  1190       iBuffers(NULL),
       
  1191       iEp0Endpoint(NULL)
       
  1192     {
       
  1193     __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DLddUsbcScChannel()"));
       
  1194     iClient = &Kern::CurrentThread();
       
  1195     iClient->Open();
       
  1196     for (TInt i = 1; i < KUsbcMaxRequests; i++)
       
  1197         {
       
  1198         iRequestStatus[i] = NULL;
       
  1199         }
       
  1200     }
       
  1201 
       
  1202 
       
  1203 //
       
  1204 // Destructor
       
  1205 //
       
  1206 
       
  1207 DLddUsbcScChannel::~DLddUsbcScChannel()
       
  1208     {
       
  1209     __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::~DLddUsbcScChannel()"));
       
  1210     if (iController)
       
  1211         {
       
  1212         iController->DeRegisterClient(this);
       
  1213         iStatusCallbackInfo.Cancel();
       
  1214         iEndpointStatusCallbackInfo.Cancel();
       
  1215         iOtgFeatureCallbackInfo.Cancel();
       
  1216         iCompleteAllCallbackInfo.Cancel();
       
  1217         DestroyAllInterfaces();
       
  1218         if (iOwnsDeviceControl)
       
  1219             {
       
  1220             iController->ReleaseDeviceControl(this);
       
  1221             iOwnsDeviceControl = EFalse;
       
  1222             }
       
  1223         iController=NULL;
       
  1224         DestroyEp0();
       
  1225         if (iStatusFifo!=NULL)
       
  1226             {
       
  1227             delete iStatusFifo;
       
  1228             }
       
  1229         }
       
  1230     __KTRACE_OPT(KUSB, Kern::Printf("Closing buffers"));
       
  1231     if (iBuffers)
       
  1232         {
       
  1233         TInt i;
       
  1234         for (i=0; i<(iNumBuffers+2); i++) 
       
  1235             {
       
  1236             iBuffers[i].Destroy();
       
  1237             }
       
  1238         Kern::Free(iBuffers);
       
  1239         }
       
  1240 
       
  1241     if (iRealizeCalled)
       
  1242         {
       
  1243         // Close Chunk
       
  1244         iChunkInfo->Close();
       
  1245         // ChunkInfo will delete itself with DFC, but the pointer here is no longer needed.        
       
  1246         iChunkInfo=NULL;
       
  1247         }
       
  1248     __KTRACE_OPT(KUSB, Kern::Printf("about to SafeClose"));
       
  1249     Kern::SafeClose((DObject*&)iClient, NULL);
       
  1250     }
       
  1251 
       
  1252 
       
  1253 //
       
  1254 // DoCreate - Create channel
       
  1255 //
       
  1256 
       
  1257 TInt DLddUsbcScChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& aVer)
       
  1258     {
       
  1259     __KTRACE_OPT(KUSB, Kern::Printf("LDD DoCreateL 1 Ver = %02d %02d %02d",
       
  1260                                     aVer.iMajor, aVer.iMinor, aVer.iBuild));
       
  1261     if (!Kern::CurrentThreadHasCapability(ECapabilityCommDD,
       
  1262                                           __PLATSEC_DIAGNOSTIC_STRING("Checked by USBCSC.LDD (USB Driver)")))
       
  1263         {
       
  1264         return KErrPermissionDenied;
       
  1265         }
       
  1266 
       
  1267     iController = DUsbClientController::UsbcControllerPointer();
       
  1268 
       
  1269     if (!iController)
       
  1270         {
       
  1271         return KErrGeneral;
       
  1272         }
       
  1273 
       
  1274     iStatusFifo = new TUsbcDeviceStatusQueue;
       
  1275     if (iStatusFifo == NULL)
       
  1276         {
       
  1277         return KErrNoMemory;
       
  1278         }
       
  1279 
       
  1280       if (!Kern::QueryVersionSupported(TVersion(KUsbcScMajorVersion, KUsbcScMinorVersion, KUsbcScBuildVersion), aVer))
       
  1281         {
       
  1282         return KErrNotSupported;
       
  1283         }
       
  1284 
       
  1285     // set up the correct DFC queue
       
  1286     SetDfcQ(iController->DfcQ(0));                            // sets the channel's dfc queue
       
  1287     iCompleteAllCallbackInfo.SetDfcQ(iDfcQ);
       
  1288     iStatusCallbackInfo.SetDfcQ(iDfcQ);                        // use the channel's dfcq for this dfc
       
  1289     iEndpointStatusCallbackInfo.SetDfcQ(iDfcQ);                // use the channel's dfcq for this dfc
       
  1290     iOtgFeatureCallbackInfo.SetDfcQ(iDfcQ);
       
  1291     iMsgQ.Receive();                                        //start up the message q
       
  1292     TInt r = iController->RegisterClientCallback(iCompleteAllCallbackInfo);
       
  1293     if (r != KErrNone)
       
  1294         return r;
       
  1295     r = iController->RegisterForStatusChange(iStatusCallbackInfo);
       
  1296     if (r != KErrNone)
       
  1297         return r;
       
  1298     r = iController->RegisterForEndpointStatusChange(iEndpointStatusCallbackInfo);
       
  1299     if (r != KErrNone)
       
  1300         return r;
       
  1301     r = iController->RegisterForOtgFeatureChange(iOtgFeatureCallbackInfo);
       
  1302     if (r != KErrNone)
       
  1303         return r;
       
  1304 
       
  1305     return r;
       
  1306     }
       
  1307 // end DoCreate.
       
  1308 
       
  1309 
       
  1310 //
       
  1311 // HandleMsg
       
  1312 //
       
  1313 // Events from userside arrive here, and delegated to either DoRequest, DoControl or DoCancel.
       
  1314 //
       
  1315 
       
  1316 void DLddUsbcScChannel::HandleMsg(TMessageBase* aMsg)
       
  1317     {
       
  1318     TThreadMessage& m = *(TThreadMessage*)aMsg;
       
  1319     TInt id = m.iValue;
       
  1320     __KTRACE_OPT(KUSB, Kern::Printf("HandleMsg 0x%x", id));
       
  1321 
       
  1322     if (id == (TInt) ECloseMsg)
       
  1323         {
       
  1324         iChannelClosing = ETrue;
       
  1325         m.Complete(KErrNone, EFalse);
       
  1326         return;
       
  1327         }
       
  1328 
       
  1329     TInt r;
       
  1330     if (id < 0)
       
  1331         {
       
  1332         // DoRequest
       
  1333         TRequestStatus* pS = (TRequestStatus*) m.Ptr0();
       
  1334         r = DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
       
  1335         m.Complete(r, ETrue);
       
  1336         }
       
  1337     else if (id & RDevUsbcScClient::ERequestCancel)
       
  1338         {
       
  1339         // DoCancel
       
  1340         r = DoCancel(id, (TUint) m.Ptr0(), (TUint) m.Ptr1());
       
  1341         m.Complete(r, ETrue);
       
  1342     }
       
  1343     else
       
  1344         {
       
  1345         // DoControl
       
  1346         r = DoControl(id, m.Ptr0(), m.Ptr1());
       
  1347         m.Complete(r, ETrue);
       
  1348         }
       
  1349     }
       
  1350 // end HandleMsg.
       
  1351 
       
  1352 
       
  1353 #define BREAK_IF_NULL_ARG(a,r) if (a==NULL) { r = KErrArgument; __KTRACE_OPT(KUSB,Kern::Printf("NULL Argument")); break; }
       
  1354 
       
  1355 //
       
  1356 // DoRequest - Asynchronous requests
       
  1357 //
       
  1358 // Overrides pure virtual, called by HandleMsg. (Above)
       
  1359 //
       
  1360 TInt DLddUsbcScChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
       
  1361     {
       
  1362     TInt reqNo = aReqNo & RDevUsbcScClient::KFieldIdMask;
       
  1363     TInt r = KErrNone;  // return via request notify
       
  1364     TBool needsCompletion =EFalse;
       
  1365 
       
  1366     __KTRACE_OPT(KUSB, Kern::Printf("DoRequest 0x%08x", aReqNo));
       
  1367 
       
  1368     if ((reqNo>RDevUsbcScClient::ERequestReadDataNotify) &&
       
  1369         (reqNo<RDevUsbcScClient::ERequestMaxRequests))
       
  1370         {
       
  1371         if (iRequestStatus[reqNo])
       
  1372             {
       
  1373             PanicClientThread(ERequestAlreadyPending);
       
  1374             return 0;
       
  1375             }
       
  1376         iRequestStatus[reqNo] = aStatus;
       
  1377         }
       
  1378 
       
  1379     switch (reqNo)
       
  1380         {
       
  1381     case RDevUsbcScClient::ERequestWriteData:
       
  1382         {
       
  1383         TInt buffer =  (aReqNo>>RDevUsbcScClient::KFieldBuffPos)&RDevUsbcScClient::KFieldBuffMask;
       
  1384         __KTRACE_OPT(KUSB, Kern::Printf("ERequestWriteData"));
       
  1385         BREAK_IF_NULL_ARG(a2,r);
       
  1386 
       
  1387         r = DoWriteData( aStatus, buffer, (TInt) a1 /*Start*/, (TInt) a2 /* Length */,
       
  1388                          aReqNo>>RDevUsbcScClient::KFieldFlagsPos ); // Flags
       
  1389         break;
       
  1390         }
       
  1391     case RDevUsbcScClient::ERequestReadDataNotify:
       
  1392         {
       
  1393         __KTRACE_OPT(KUSB, Kern::Printf("ERequestReadDataNotify"));
       
  1394         return DoReadDataNotify(aStatus, (TInt) a1, (TInt) a2); // a1 = aBufferNumber, a2 - aLength;
       
  1395         } 
       
  1396 
       
  1397     case RDevUsbcScClient::ERequestAlternateDeviceStatusNotify:
       
  1398         {
       
  1399         __KTRACE_OPT(KUSB, Kern::Printf("ERequestAlternateDeviceStatusNotify"));
       
  1400         BREAK_IF_NULL_ARG(a1,r);
       
  1401         iDeviceStatusNeeded = ETrue;
       
  1402         iStatusChangePtr = a1;
       
  1403         needsCompletion = AlternateDeviceStateTestComplete();
       
  1404         break;
       
  1405         }
       
  1406     case RDevUsbcScClient::ERequestReEnumerate:
       
  1407         {
       
  1408         __KTRACE_OPT(KUSB, Kern::Printf("ERequestReEnumerate"));
       
  1409         // If successful, this will complete via the status notification.
       
  1410         r = iController->ReEnumerate();
       
  1411         break;
       
  1412         }
       
  1413     case RDevUsbcScClient::ERequestEndpointStatusNotify:
       
  1414         {
       
  1415         __KTRACE_OPT(KUSB, Kern::Printf("ERequestEndpointStatusNotify"));
       
  1416         BREAK_IF_NULL_ARG(a1,r);
       
  1417         
       
  1418         iEndpointStatusChangePtr = a1;
       
  1419         break;
       
  1420         }
       
  1421     case RDevUsbcScClient::ERequestOtgFeaturesNotify:
       
  1422         {
       
  1423         __KTRACE_OPT(KUSB, Kern::Printf("ERequestOtgFeaturesNotify"));
       
  1424         BREAK_IF_NULL_ARG(a1,r);
       
  1425             
       
  1426         iOtgFeatureChangePtr = a1;
       
  1427         break;
       
  1428         }
       
  1429     default:
       
  1430         r = KErrNotSupported;
       
  1431         }
       
  1432 
       
  1433     if ((needsCompletion) || (r != KErrNone))
       
  1434         {
       
  1435         iRequestStatus[reqNo] = aStatus;
       
  1436         Kern::RequestComplete(iClient, iRequestStatus[reqNo], r);
       
  1437         }
       
  1438     return KErrNone;
       
  1439     }
       
  1440 // end DoRequest.
       
  1441 
       
  1442 
       
  1443 //
       
  1444 // DoReadDataNotify
       
  1445 //
       
  1446 // This method sets up the request to facilitate the userside being notifed when new data has been read.
       
  1447 //
       
  1448 TInt DLddUsbcScChannel::DoReadDataNotify(TRequestStatus* aStatus, TInt aBufferNum, TInt aLength)
       
  1449     {
       
  1450     __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoReadDataNotify(x, %d, 0x%x)", aBufferNum, aLength));
       
  1451     TInt r = KErrNone;
       
  1452     // check range
       
  1453     if ((aBufferNum<0) ||  (aBufferNum>=iNumBuffers))  // Indirectly checks that we are set up.
       
  1454         {
       
  1455         if (aBufferNum!=KUsbcScEndpointZero)
       
  1456             {
       
  1457             __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoReadDataNotify : Bad Buffer Number!"));
       
  1458             return KErrArgument;
       
  1459             }
       
  1460         else
       
  1461             {
       
  1462             aBufferNum = iEP0OutBuff;
       
  1463             }
       
  1464         }
       
  1465     else
       
  1466         {
       
  1467         // check direction
       
  1468         if (iBuffers[aBufferNum].iDirection!=KUsbcScOut)
       
  1469             {
       
  1470                 __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoReadDataNotify : Bad Buffer Direction!"));
       
  1471             return KErrNotSupported;
       
  1472             }
       
  1473         if (!Configured())
       
  1474             return KErrUsbInterfaceNotReady;
       
  1475         }
       
  1476     SUsbcScBufferHeader* scBuffer = (SUsbcScBufferHeader*) iBuffers[aBufferNum].iBufferStart;
       
  1477 
       
  1478     __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoReadDataNotify  head %x tail %x", iBuffers[aBufferNum].iHead , scBuffer->iTail ));
       
  1479 
       
  1480     if (iBuffers[aBufferNum].iHead != scBuffer->iBilTail)
       
  1481         r = KErrCompletion;
       
  1482     else
       
  1483         if (iBuffers[aBufferNum].iStalled)
       
  1484             {
       
  1485             iBuffers[aBufferNum].PopStall();
       
  1486             return KErrCompletion;
       
  1487             }
       
  1488         else
       
  1489             r = iBuffers[aBufferNum].iStatusList.Add(aStatus, aLength, 0,0);
       
  1490 
       
  1491     if (iBuffers[aBufferNum].iStatusList.iState==ENotRunning)
       
  1492         {
       
  1493         iBuffers[aBufferNum].StartDataRead();
       
  1494         }
       
  1495     else
       
  1496         {
       
  1497         __KTRACE_OPT(KUSB, Kern::Printf("Job in Progress!"));
       
  1498         }
       
  1499     return r;
       
  1500     }
       
  1501 // end DoReadDataNotify.
       
  1502 
       
  1503 
       
  1504 
       
  1505 //
       
  1506 // DoWriteData
       
  1507 //
       
  1508 // This method sets up the request to write data to USB from userside.
       
  1509 //
       
  1510 TInt DLddUsbcScChannel::DoWriteData(TRequestStatus* aStatus,TInt aBufferNum, TUint aStart, TUint aLength, TUint aFlags)
       
  1511     {
       
  1512     __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoWriteData(%d, 0x%x, 0x%x, 0x%x)",  aBufferNum, aStart, aLength, aFlags));
       
  1513     if (!iUserKnowsAltSetting)
       
  1514         return KErrEof;
       
  1515     // Check Buffer Number
       
  1516     if ((aBufferNum<0) ||  (aBufferNum>=iNumBuffers))
       
  1517         {
       
  1518         if ((TUint)aBufferNum!=RDevUsbcScClient::KFieldBuffMask)  // KUsbcScEndpointZero & KFieldBuffMas = KFieldBuffMas;
       
  1519             {
       
  1520             __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoWriteData : Bad Buffer Number!"));
       
  1521             return KErrArgument;
       
  1522             }
       
  1523         else
       
  1524             {
       
  1525             aBufferNum = iEP0InBuff;
       
  1526             }
       
  1527         }
       
  1528     else
       
  1529         {
       
  1530         // check direction
       
  1531         if (iBuffers[aBufferNum].iDirection!=KUsbcScIn)
       
  1532             {
       
  1533                 __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoWriteData Bad endpoint Direction"));
       
  1534                 return KErrArgument;
       
  1535             }
       
  1536         }
       
  1537 
       
  1538     TUsbcScBuffer& buf=iBuffers[aBufferNum];
       
  1539 
       
  1540     if ((aStart< (((TLinAddr) buf.iBufferStart)-buf.iChunkAddr)) || ((aStart+aLength)>iBuffers[aBufferNum].iBufferEnd))
       
  1541         {
       
  1542         __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoWriteData Bad Range aStart or aLength 0x%x > 0x%x + 0x%x < 0x%x", (((TLinAddr) buf.iBufferStart)-buf.iChunkAddr),aStart, aLength, iBuffers[aBufferNum].iBufferEnd ));
       
  1543         return KErrArgument;
       
  1544         }
       
  1545 
       
  1546     if ( (aBufferNum != iEP0InBuff) && !Configured())
       
  1547         return KErrUsbInterfaceNotReady;
       
  1548 
       
  1549     if (aStart & ~buf.iAlignMask)
       
  1550         {
       
  1551         __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::DoDataWrite: address 0x%x unaligned.",aStart));
       
  1552         return KErrArgument;
       
  1553         }
       
  1554             
       
  1555     TInt r = iBuffers[aBufferNum].iStatusList.Add(aStatus, aLength, aStart, aFlags); //update
       
  1556 
       
  1557     if (iBuffers[aBufferNum].iStatusList.iState==ENotRunning)
       
  1558         {
       
  1559             iBuffers[aBufferNum].StartDataWrite();
       
  1560         }
       
  1561     else
       
  1562         {    
       
  1563         __KTRACE_OPT(KUSB, Kern::Printf("Job in Progress!"));
       
  1564         }
       
  1565 
       
  1566 
       
  1567     return r;
       
  1568     }
       
  1569 // end DoWriteData.
       
  1570 
       
  1571 
       
  1572 //
       
  1573 // Cancel an outstanding request                        // Cancel need reworking.
       
  1574 //
       
  1575 TInt DLddUsbcScChannel::DoCancel(TInt aReqNo, TUint aBuff, TUint aSpair)
       
  1576     {
       
  1577     TInt r = KErrNone;
       
  1578     TInt direction=KUsbcScOut;
       
  1579 
       
  1580     __KTRACE_OPT(KUSB, Kern::Printf("DoCancel: 0x%x aBuff 0x%x", aReqNo, aBuff));
       
  1581     switch (aReqNo)
       
  1582         {
       
  1583     case RDevUsbcScClient::ERequestCancel:
       
  1584         TInt buffer;
       
  1585         TInt mask;
       
  1586 
       
  1587         for (buffer=1, mask=1; buffer<iNumBuffers; buffer++,mask<<=1)
       
  1588             if (aBuff&mask)
       
  1589                 iBuffers[buffer].Cancel(KErrCancel);
       
  1590 
       
  1591         return KErrNone;
       
  1592 
       
  1593     // coverity[missing_break]
       
  1594     case RDevUsbcScClient::ERequestWriteDataCancel:
       
  1595         direction = KUsbcScIn;
       
  1596     case RDevUsbcScClient::ERequestReadDataNotifyCancel:
       
  1597         __KTRACE_OPT(KUSB, Kern::Printf("DoCancel Direction %d endpoints: 0x%x",direction, aReqNo));
       
  1598 
       
  1599         if (((TInt)aBuff)==KUsbcScEndpointZero) // EP0 is bi-directional, so pick correct buffer for call type
       
  1600             {
       
  1601             __KTRACE_OPT(KUSB, Kern::Printf("DoCancel Cancel Endpoint 0/%d",direction));
       
  1602             iEp0Endpoint->AbortTransfer();
       
  1603             if (direction==KUsbcScIn)
       
  1604                 aBuff=iEP0InBuff;
       
  1605             else
       
  1606                 aBuff=iEP0OutBuff;
       
  1607             } 
       
  1608         else if ((TInt)aBuff >= iNumBuffers) // check buff no range.
       
  1609             {
       
  1610             __KTRACE_OPT(KUSB, Kern::Printf("DoCancel Error: Bad buffer number"));
       
  1611             return KErrArgument;
       
  1612             }
       
  1613 
       
  1614         if ((iBuffers[aBuff].iDirection&1)!=direction) // Does direction match call type?
       
  1615             {
       
  1616             __KTRACE_OPT(KUSB, Kern::Printf("DoCancel Error: Bad buffer direction"));
       
  1617             return KErrArgument;
       
  1618             }    
       
  1619         iBuffers[aBuff].iStatusList.CancelQueued();
       
  1620         iBuffers[aBuff].Cancel(KErrCancel);
       
  1621         
       
  1622         return KErrNone;
       
  1623 
       
  1624     case RDevUsbcScClient::ERequestAlternateDeviceStatusNotifyCancel:
       
  1625         __KTRACE_OPT(KUSB, Kern::Printf("DoCancel: ERequestAlternateDeviceStatusNotify 0x%x", aReqNo));
       
  1626         iDeviceStatusNeeded = EFalse;
       
  1627         iStatusFifo->FlushQueue();
       
  1628         if (iStatusChangePtr)
       
  1629             {
       
  1630             TInt deviceState = iController->GetDeviceStatus();
       
  1631             r = Kern::ThreadRawWrite(iClient, iStatusChangePtr, &deviceState, sizeof(deviceState), iClient);
       
  1632             if (r != KErrNone)
       
  1633                 PanicClientThread(r);
       
  1634             iStatusChangePtr = NULL; 
       
  1635             }
       
  1636     break;
       
  1637 
       
  1638     case RDevUsbcScClient::ERequestReEnumerateCancel:
       
  1639         __KTRACE_OPT(KUSB, Kern::Printf("DoCancel ERequestReEnumerate: 0x%x", aReqNo));
       
  1640     break;
       
  1641 
       
  1642     case RDevUsbcScClient::ERequestEndpointStatusNotifyCancel:
       
  1643         __KTRACE_OPT(KUSB, Kern::Printf("DoCancel ERequestEndpointStatusNotify: 0x%x", aReqNo));
       
  1644         CancelNotifyEndpointStatus();
       
  1645     break;
       
  1646 
       
  1647      case RDevUsbcScClient::ERequestOtgFeaturesNotifyCancel:
       
  1648         __KTRACE_OPT(KUSB, Kern::Printf("DoCancel ERequestOtgFeaturesNotify: 0x%x", aReqNo));
       
  1649         CancelNotifyOtgFeatures();
       
  1650     break;
       
  1651 
       
  1652     default:
       
  1653         __KTRACE_OPT(KUSB, Kern::Printf("DoCancel Unknown! 0x%x", aReqNo));
       
  1654         return KErrArgument;
       
  1655         }
       
  1656 
       
  1657     Kern::RequestComplete(iClient,iRequestStatus[aReqNo & ~RDevUsbcScClient::ERequestCancel], KErrCancel);
       
  1658     return r;
       
  1659     }
       
  1660 
       
  1661 
       
  1662 void DLddUsbcScChannel::CancelNotifyEndpointStatus()
       
  1663     {
       
  1664     if (iEndpointStatusChangePtr)
       
  1665         {
       
  1666         TUint epBitmap = 0;
       
  1667         for (TInt i = 1; i <= iNumberOfEndpoints; i++)
       
  1668             {
       
  1669             TInt v = iController->GetEndpointStatus(this, iEndpoint[i]->RealEpNumber());
       
  1670             TUint b;
       
  1671             (v == EEndpointStateStalled) ? b = 1 : b = 0;
       
  1672             epBitmap |= b << i;
       
  1673             }
       
  1674         TInt r=Kern::ThreadRawWrite(iClient, iEndpointStatusChangePtr, (TUint8*) &epBitmap, sizeof(epBitmap), iClient);
       
  1675         if (r != KErrNone)
       
  1676             PanicClientThread(r);
       
  1677         iEndpointStatusChangePtr = NULL;
       
  1678         }
       
  1679     }
       
  1680 
       
  1681 void DLddUsbcScChannel::CancelNotifyOtgFeatures()
       
  1682     {
       
  1683     if (iOtgFeatureChangePtr)
       
  1684         {
       
  1685         TUint8 features;
       
  1686         iController->GetCurrentOtgFeatures(features);
       
  1687         TInt r=Kern::ThreadRawWrite(iClient, iOtgFeatureChangePtr, (TUint8*)&features, sizeof(features), iClient);
       
  1688         if (r != KErrNone)
       
  1689             PanicClientThread(r);
       
  1690         iOtgFeatureChangePtr = NULL;
       
  1691         }
       
  1692     }
       
  1693 
       
  1694 
       
  1695 
       
  1696 //
       
  1697 // DoControl - Synchronous requests
       
  1698 //
       
  1699 // Called from HandleMsg.
       
  1700 
       
  1701 TInt DLddUsbcScChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
       
  1702     {
       
  1703     __KTRACE_OPT(KUSB, Kern::Printf("DoControl: %d", aFunction));
       
  1704 
       
  1705     TInt r = KErrNone;
       
  1706     TInt ep, param;
       
  1707     TUsbcScEndpoint* pEndpoint;
       
  1708     TPtrC8 pZeroDesc(NULL, 0);
       
  1709     TEndpointDescriptorInfo epInfo;
       
  1710     TUsbcScIfcInfo ifcInfo;
       
  1711     TCSDescriptorInfo desInfo;
       
  1712     TUsbcEndpointResource epRes;
       
  1713 
       
  1714     switch (aFunction)
       
  1715         {
       
  1716     case RDevUsbcScClient::EControlEndpointZeroRequestError:
       
  1717         __KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointZeroRequestError"));
       
  1718         r = KErrNone;
       
  1719         if (iOwnsDeviceControl || (iValidInterface && iDeviceState == UsbShai::EUsbPeripheralStateConfigured))
       
  1720             {
       
  1721             iController->Ep0Stall(this);
       
  1722             }
       
  1723         else
       
  1724             {
       
  1725             if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured)
       
  1726                 r = KErrUsbDeviceNotConfigured;
       
  1727             else
       
  1728                 r = KErrUsbInterfaceNotReady;
       
  1729             }
       
  1730         break;
       
  1731 
       
  1732     case RDevUsbcScClient::EControlGetAlternateSetting:
       
  1733         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetAlternateSetting"));
       
  1734         if (iValidInterface && iDeviceState == UsbShai::EUsbPeripheralStateConfigured)
       
  1735             {
       
  1736             r = iController->GetInterfaceNumber(this, param);
       
  1737             if (r == KErrNone)
       
  1738                 {
       
  1739                 r = Kern::ThreadRawWrite(iClient, a1, &param, sizeof(param), iClient);
       
  1740                 if (r != KErrNone)
       
  1741                     PanicClientThread(r);
       
  1742                 }
       
  1743             }
       
  1744         else
       
  1745             {
       
  1746             if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured)
       
  1747                 r = KErrUsbDeviceNotConfigured;
       
  1748             else
       
  1749                 r = KErrUsbInterfaceNotReady;
       
  1750             }
       
  1751         break;
       
  1752 
       
  1753     case RDevUsbcScClient::EControlDeviceStatus:
       
  1754         __KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceStatus"));
       
  1755         param = iController->GetDeviceStatus();
       
  1756         r = Kern::ThreadRawWrite(iClient, a1, &param, sizeof(param), iClient);
       
  1757         if (r != KErrNone)
       
  1758             PanicClientThread(r);
       
  1759         break;
       
  1760 
       
  1761     case RDevUsbcScClient::EControlEndpointStatus:
       
  1762         __KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointStatus"));
       
  1763         if (iValidInterface && ValidEndpoint((TInt) a1))
       
  1764             {
       
  1765             pEndpoint = iEndpoint[(TInt)a1];
       
  1766             if (pEndpoint == NULL)
       
  1767                 r = KErrNotSupported;
       
  1768             else
       
  1769                 {
       
  1770                 param = iController->GetEndpointStatus(this, iEndpoint[(TInt)a1]->RealEpNumber());
       
  1771                 r = Kern::ThreadRawWrite(iClient, a2, &param, sizeof(param), iClient);
       
  1772                 if (r != KErrNone)
       
  1773                     PanicClientThread(r);
       
  1774                 }
       
  1775             }
       
  1776         else
       
  1777             {
       
  1778             if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured)
       
  1779                 r = KErrUsbDeviceNotConfigured;
       
  1780             else
       
  1781                 r = KErrUsbInterfaceNotReady;
       
  1782             }
       
  1783         break;
       
  1784 
       
  1785     case RDevUsbcScClient::EControlEndpointCaps:
       
  1786         __KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointCaps"));
       
  1787         r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
       
  1788         if (r != KErrNone)
       
  1789             PanicClientThread(r);
       
  1790         iController->EndpointCaps(this, *((TDes8*) a1));
       
  1791         break;
       
  1792 
       
  1793     case RDevUsbcScClient::EControlDeviceCaps:
       
  1794         __KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceCaps"));
       
  1795         r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
       
  1796         if (r != KErrNone)
       
  1797             PanicClientThread(r);
       
  1798         iController->DeviceCaps(this, *((TDes8*) a1));
       
  1799         break;
       
  1800 
       
  1801     case RDevUsbcScClient::EControlSendEp0StatusPacket:
       
  1802         __KTRACE_OPT(KUSB, Kern::Printf("EControlSendEp0StatusPacket"));
       
  1803         iController->SendEp0StatusPacket(this);
       
  1804         break;
       
  1805 
       
  1806     case RDevUsbcScClient::EControlHaltEndpoint:
       
  1807         __KTRACE_OPT(KUSB, Kern::Printf("EControlHaltEndpoint"));
       
  1808         if (iValidInterface && ValidEndpoint((TInt) a1))
       
  1809             {
       
  1810             r = iController->HaltEndpoint(this, iEndpoint[(TInt)a1]->RealEpNumber());
       
  1811             }
       
  1812         else
       
  1813             {
       
  1814             if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured)
       
  1815                 r = KErrUsbDeviceNotConfigured;
       
  1816             else
       
  1817                 r = KErrUsbInterfaceNotReady;
       
  1818             }
       
  1819         break;
       
  1820 
       
  1821     case RDevUsbcScClient::EControlClearHaltEndpoint:
       
  1822         __KTRACE_OPT(KUSB, Kern::Printf("EControlClearHaltEndpoint"));
       
  1823         if (iValidInterface && ValidEndpoint((TInt) a1))
       
  1824             {
       
  1825             r = iController->ClearHaltEndpoint(this, iEndpoint[(TInt)a1]->RealEpNumber());
       
  1826             }
       
  1827         else
       
  1828             {
       
  1829             if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured)
       
  1830                 r = KErrUsbDeviceNotConfigured;
       
  1831             else
       
  1832                 r = KErrUsbInterfaceNotReady;
       
  1833             }
       
  1834         break;
       
  1835 
       
  1836     case RDevUsbcScClient::EControlDumpRegisters:
       
  1837         __KTRACE_OPT(KUSB, Kern::Printf("EControlDumpRegisters"));
       
  1838         iController->DumpRegisters();
       
  1839         break;
       
  1840 
       
  1841     case RDevUsbcScClient::EControlReleaseDeviceControl:
       
  1842         __KTRACE_OPT(KUSB, Kern::Printf("EControlReleaseDeviceControl"));
       
  1843         iController->ReleaseDeviceControl(this);
       
  1844         iOwnsDeviceControl = EFalse;
       
  1845         break;
       
  1846 
       
  1847     case RDevUsbcScClient::EControlEndpointZeroMaxPacketSizes:
       
  1848         __KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointZeroMaxPacketSizes"));
       
  1849         r = iController->EndpointZeroMaxPacketSizes();
       
  1850         break;
       
  1851 
       
  1852     case RDevUsbcScClient::EControlSetEndpointZeroMaxPacketSize:
       
  1853         __KTRACE_OPT(KUSB, Kern::Printf("EControlSetEndpointZeroMaxPacketSize"));
       
  1854         r = iController->SetEndpointZeroMaxPacketSize(reinterpret_cast<TInt>(a1));
       
  1855         break;
       
  1856 
       
  1857     case RDevUsbcScClient::EControlGetEndpointZeroMaxPacketSize:
       
  1858         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetEndpointZeroMaxPacketSize"));
       
  1859         r = iController->Ep0PacketSize();
       
  1860         break;
       
  1861 
       
  1862     case RDevUsbcScClient::EControlGetDeviceDescriptor:
       
  1863         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetDeviceDescriptor"));
       
  1864         r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
       
  1865         if (r != KErrNone)
       
  1866             PanicClientThread(r);
       
  1867         r = iController->GetDeviceDescriptor(iClient, *((TDes8*) a1));
       
  1868         break;
       
  1869 
       
  1870     case RDevUsbcScClient::EControlSetDeviceDescriptor:
       
  1871         __KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceDescriptor"));
       
  1872         BREAK_IF_NULL_ARG(a1,r);
       
  1873         r = iController->SetDeviceDescriptor(iClient, *((TDes8*) a1));
       
  1874         break;
       
  1875 
       
  1876     case RDevUsbcScClient::EControlGetDeviceDescriptorSize:
       
  1877         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetDeviceDescriptorSize"));
       
  1878         BREAK_IF_NULL_ARG(a1,r);
       
  1879         r = iController->GetDeviceDescriptorSize(iClient, *((TDes8*) a1));
       
  1880         break;
       
  1881 
       
  1882     case RDevUsbcScClient::EControlGetConfigurationDescriptor:
       
  1883         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetConfigurationDescriptor"));
       
  1884         r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0 , 0, iClient);
       
  1885         if (r != KErrNone)
       
  1886             PanicClientThread(r);
       
  1887         r = iController->GetConfigurationDescriptor(iClient, *((TDes8*) a1));
       
  1888         break;
       
  1889 
       
  1890     case RDevUsbcScClient::EControlGetConfigurationDescriptorSize:
       
  1891         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetConfigurationDescriptorSize"));
       
  1892         if (a1 != NULL)
       
  1893             {
       
  1894             r = iController->GetConfigurationDescriptorSize(iClient, *((TDes8*) a1));
       
  1895             }
       
  1896         else
       
  1897             r = KErrArgument;
       
  1898         break;
       
  1899 
       
  1900     case RDevUsbcScClient::EControlSetConfigurationDescriptor:
       
  1901         __KTRACE_OPT(KUSB, Kern::Printf("EControlSetConfigurationDescriptor"));
       
  1902         r = iController->SetConfigurationDescriptor(iClient, *((TDes8*) a1));
       
  1903         break;
       
  1904 
       
  1905     case RDevUsbcScClient::EControlGetInterfaceDescriptor:
       
  1906         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetInterfaceDescriptor"));
       
  1907         r = iController->GetInterfaceDescriptor(iClient, this, (TInt) a1, *((TDes8*) a2));
       
  1908         break;
       
  1909 
       
  1910     case RDevUsbcScClient::EControlGetInterfaceDescriptorSize:
       
  1911         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetInterfaceDescriptorSize"));
       
  1912         r = iController->GetInterfaceDescriptorSize(iClient, this, (TInt) a1, *(TDes8*) a2);
       
  1913         break;
       
  1914 
       
  1915     case RDevUsbcScClient::EControlSetInterfaceDescriptor:
       
  1916         __KTRACE_OPT(KUSB, Kern::Printf("EControlSetInterfaceDescriptor"));
       
  1917         r = iController->SetInterfaceDescriptor(iClient, this, (TInt) a1, *((TDes8*) a2));
       
  1918         break;
       
  1919 
       
  1920     case RDevUsbcScClient::EControlGetEndpointDescriptor:
       
  1921         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetEndpointDescriptor"));
       
  1922         r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
       
  1923         if (r != KErrNone)
       
  1924             PanicClientThread(r);
       
  1925         ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
       
  1926         r = (ep<0)?ep:iController->GetEndpointDescriptor(iClient, this, epInfo.iSetting,
       
  1927                                                ep, *(TDes8*) epInfo.iArg);
       
  1928         break;
       
  1929 
       
  1930     case RDevUsbcScClient::EControlGetEndpointDescriptorSize:
       
  1931         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetEndpointDescriptorSize"));
       
  1932         r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
       
  1933         if (r != KErrNone)
       
  1934             PanicClientThread(r);
       
  1935         ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
       
  1936         r = iController->GetEndpointDescriptorSize(iClient, this, epInfo.iSetting,
       
  1937                                                    ep, *(TDes8*) epInfo.iArg);
       
  1938         break;
       
  1939 
       
  1940     case RDevUsbcScClient::EControlSetEndpointDescriptor:
       
  1941         __KTRACE_OPT(KUSB, Kern::Printf("EControlSetEndpointDescriptor"));
       
  1942         r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
       
  1943         if (r != KErrNone)
       
  1944             PanicClientThread(r);
       
  1945         ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
       
  1946         r = iController->SetEndpointDescriptor(iClient, this, epInfo.iSetting,
       
  1947                                                ep, *(TDes8*)epInfo.iArg);
       
  1948         break;
       
  1949 
       
  1950     case RDevUsbcScClient::EControlGetDeviceQualifierDescriptor:
       
  1951         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetDeviceQualifierDescriptor"));
       
  1952         r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
       
  1953         if (r != KErrNone)
       
  1954             PanicClientThread(r);
       
  1955         r = iController->GetDeviceQualifierDescriptor(iClient, *((TDes8*) a1));
       
  1956         break;
       
  1957 
       
  1958     case RDevUsbcScClient::EControlSetDeviceQualifierDescriptor:
       
  1959         __KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceQualifierDescriptor"));
       
  1960         BREAK_IF_NULL_ARG(a1,r);
       
  1961         r = iController->SetDeviceQualifierDescriptor(iClient, *((TDes8*) a1));
       
  1962         break;
       
  1963 
       
  1964     case RDevUsbcScClient::EControlGetOtherSpeedConfigurationDescriptor:
       
  1965         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetOtherSpeedConfigurationDescriptor"));
       
  1966         r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0 , 0, iClient);
       
  1967         if (r != KErrNone)
       
  1968             PanicClientThread(r);
       
  1969         r = iController->GetOtherSpeedConfigurationDescriptor(iClient, *((TDes8*) a1));
       
  1970         break;
       
  1971 
       
  1972     case RDevUsbcScClient::EControlSetOtherSpeedConfigurationDescriptor:
       
  1973         __KTRACE_OPT(KUSB, Kern::Printf("EControlSetOtherSpeedConfigurationDescriptor"));
       
  1974         r = iController->SetOtherSpeedConfigurationDescriptor(iClient, *((TDes8*) a1));
       
  1975         break;
       
  1976 
       
  1977 
       
  1978     case RDevUsbcScClient::EControlGetCSInterfaceDescriptor:
       
  1979         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSInterfaceDescriptor"));
       
  1980         r = iController->GetCSInterfaceDescriptorBlock(iClient, this, (TInt) a1, *((TDes8*) a2));
       
  1981         break;
       
  1982 
       
  1983     case RDevUsbcScClient::EControlGetCSInterfaceDescriptorSize:
       
  1984         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSInterfaceDescriptorSize"));
       
  1985         r = iController->GetCSInterfaceDescriptorBlockSize(iClient, this, (TInt) a1, *(TDes8*) a2);
       
  1986         break;
       
  1987 
       
  1988     case RDevUsbcScClient::EControlGetCSEndpointDescriptor:
       
  1989         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSEndpointDescriptor"));
       
  1990         r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
       
  1991         if (r != KErrNone)
       
  1992             PanicClientThread(r);
       
  1993         ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
       
  1994         r = iController->GetCSEndpointDescriptorBlock(iClient, this, epInfo.iSetting,
       
  1995                                                       ep, *(TDes8*) epInfo.iArg);
       
  1996         break;
       
  1997 
       
  1998     case RDevUsbcScClient::EControlGetCSEndpointDescriptorSize:
       
  1999         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSEndpointDescriptorSize"));
       
  2000         r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
       
  2001         if (r != KErrNone)
       
  2002             PanicClientThread(r);
       
  2003         ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
       
  2004         r = iController->GetCSEndpointDescriptorBlockSize(iClient, this, epInfo.iSetting,
       
  2005                                                           ep, *(TDes8*) epInfo.iArg);
       
  2006         break;
       
  2007 
       
  2008     case RDevUsbcScClient::EControlSignalRemoteWakeup:
       
  2009         __KTRACE_OPT(KUSB, Kern::Printf("EControlSignalRemoteWakeup"));
       
  2010         r = iController->SignalRemoteWakeup();
       
  2011         break;
       
  2012 
       
  2013     case RDevUsbcScClient::EControlDeviceDisconnectFromHost:
       
  2014         __KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceDisconnectFromHost"));
       
  2015         r = iController->UsbDisconnect();
       
  2016         break;
       
  2017 
       
  2018     case RDevUsbcScClient::EControlDeviceConnectToHost:
       
  2019         __KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceConnectToHost"));
       
  2020         r = iController->UsbConnect();
       
  2021         break;
       
  2022 
       
  2023     case RDevUsbcScClient::EControlDevicePowerUpUdc:
       
  2024         __KTRACE_OPT(KUSB, Kern::Printf("EControlDevicePowerUpUdc"));
       
  2025         r = iController->PowerUpUdc();
       
  2026         break;
       
  2027 
       
  2028     case RDevUsbcScClient::EControlSetDeviceControl:
       
  2029         __KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceControl"));
       
  2030         r = iController->SetDeviceControl(this);
       
  2031         if (r == KErrNone)
       
  2032             {
       
  2033             iOwnsDeviceControl = ETrue;
       
  2034             if (iEp0Endpoint == NULL)
       
  2035                 {
       
  2036                 __KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceControl"));
       
  2037                 r = SetupEp0();
       
  2038                 if (r != KErrNone)
       
  2039                     {
       
  2040                     __KTRACE_OPT(KPANIC, Kern::Printf("  Error: SetupEp0() failed"));
       
  2041                     iController->ReleaseDeviceControl(this);
       
  2042                     iOwnsDeviceControl=EFalse;
       
  2043                     DestroyEp0();
       
  2044                     }
       
  2045                 }
       
  2046             }
       
  2047         else
       
  2048             r = KErrInUse;
       
  2049         break;
       
  2050 
       
  2051     case RDevUsbcScClient::EControlCurrentlyUsingHighSpeed:
       
  2052         __KTRACE_OPT(KUSB, Kern::Printf("EControlCurrentlyUsingHighSpeed"));
       
  2053         r = iController->CurrentlyUsingHighSpeed();
       
  2054         break;
       
  2055 
       
  2056     case RDevUsbcScClient::EControlSetInterface:
       
  2057         __KTRACE_OPT(KUSB, Kern::Printf("EControlSetInterface"));
       
  2058         r = Kern::ThreadRawRead(iClient, a2, &ifcInfo, sizeof(ifcInfo));
       
  2059         if (r != KErrNone)
       
  2060             PanicClientThread(r);
       
  2061         r = SetInterface((TInt) a1, &ifcInfo);
       
  2062         break;
       
  2063 
       
  2064     case RDevUsbcScClient::EControlReleaseInterface: 
       
  2065         __KTRACE_OPT(KUSB, Kern::Printf("EControlReleaseInterface"));
       
  2066         if (!iRealizeCalled)
       
  2067             {
       
  2068             r = iController->ReleaseInterface(this, (TInt) a1);
       
  2069             if (r == KErrNone)
       
  2070                 {
       
  2071                 DestroyInterface((TUint) a1);
       
  2072                 }
       
  2073             else
       
  2074                 {
       
  2075                 __KTRACE_OPT(KPANIC, Kern::Printf("  Error in PIL: LDD interface won't be released."));
       
  2076                 }
       
  2077             }
       
  2078         else
       
  2079             r = KErrUsbAlreadyRealized;
       
  2080         break;
       
  2081 
       
  2082     case RDevUsbcScClient::EControlSetCSInterfaceDescriptor:
       
  2083         __KTRACE_OPT(KUSB, Kern::Printf("EControlSetCSInterfaceDescriptor"));
       
  2084         r = Kern::ThreadRawRead(iClient, a1, &desInfo, sizeof(desInfo));
       
  2085         if (r != KErrNone)
       
  2086             PanicClientThread(r);
       
  2087         r = iController->SetCSInterfaceDescriptorBlock(iClient, this, desInfo.iSetting,
       
  2088                                                        *reinterpret_cast<const TDes8*>(desInfo.iArg),
       
  2089                                                        desInfo.iSize);
       
  2090         break;
       
  2091 
       
  2092     case RDevUsbcScClient::EControlSetCSEndpointDescriptor:
       
  2093         __KTRACE_OPT(KUSB, Kern::Printf("EControlSetCSEndpointDescriptor"));
       
  2094         r = Kern::ThreadRawRead(iClient, a1, &desInfo, sizeof(desInfo));
       
  2095         if (r != KErrNone)
       
  2096             PanicClientThread(r);
       
  2097         ep = EpFromAlternateSetting(desInfo.iSetting, desInfo.iEndpoint);
       
  2098         r = iController->SetCSEndpointDescriptorBlock(iClient, this, desInfo.iSetting, ep,
       
  2099                                                       *reinterpret_cast<const TDes8*>(desInfo.iArg),
       
  2100                                                       desInfo.iSize);
       
  2101         break;
       
  2102 
       
  2103     case RDevUsbcScClient::EControlGetStringDescriptorLangId:
       
  2104         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetStringDescriptorLangId"));
       
  2105         r = iController->GetStringDescriptorLangId(iClient, *((TDes8*) a1));
       
  2106         break;
       
  2107 
       
  2108     case RDevUsbcScClient::EControlSetStringDescriptorLangId:
       
  2109         __KTRACE_OPT(KUSB, Kern::Printf("EControlSetStringDescriptorLangId"));
       
  2110         r = iController->SetStringDescriptorLangId(reinterpret_cast<TUint>(a1));
       
  2111         break;
       
  2112 
       
  2113     case RDevUsbcScClient::EControlGetManufacturerStringDescriptor:
       
  2114         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetManufacturerStringDescriptor"));
       
  2115         r = iController->GetManufacturerStringDescriptor(iClient, *((TPtr8*) a1));
       
  2116         break;
       
  2117 
       
  2118     case RDevUsbcScClient::EControlSetManufacturerStringDescriptor:
       
  2119         __KTRACE_OPT(KUSB, Kern::Printf("EControlSetManufacturerStringDescriptor"));
       
  2120         r = iController->SetManufacturerStringDescriptor(iClient, *((TPtr8*) a1));
       
  2121         break;
       
  2122 
       
  2123     case RDevUsbcScClient::EControlRemoveManufacturerStringDescriptor:
       
  2124         __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveManufacturerStringDescriptor"));
       
  2125         r = iController->RemoveManufacturerStringDescriptor();
       
  2126         break;
       
  2127 
       
  2128     case RDevUsbcScClient::EControlGetProductStringDescriptor:
       
  2129         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetProductStringDescriptor"));
       
  2130         r = iController->GetProductStringDescriptor(iClient, *((TPtr8*) a1));
       
  2131         break;
       
  2132 
       
  2133     case RDevUsbcScClient::EControlSetProductStringDescriptor:
       
  2134         __KTRACE_OPT(KUSB, Kern::Printf("EControlSetProductStringDescriptor"));
       
  2135         r = iController->SetProductStringDescriptor(iClient, *((TPtr8*) a1));
       
  2136         break;
       
  2137 
       
  2138     case RDevUsbcScClient::EControlRemoveProductStringDescriptor:
       
  2139         __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveProductStringDescriptor"));
       
  2140         r = iController->RemoveProductStringDescriptor();
       
  2141         break;
       
  2142 
       
  2143     case RDevUsbcScClient::EControlGetSerialNumberStringDescriptor:
       
  2144         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetSerialNumberStringDescriptor"));
       
  2145         r = iController->GetSerialNumberStringDescriptor(iClient, *((TPtr8*) a1));
       
  2146         break;
       
  2147 
       
  2148     case RDevUsbcScClient::EControlSetSerialNumberStringDescriptor:
       
  2149         __KTRACE_OPT(KUSB, Kern::Printf("EControlSetSerialNumberStringDescriptor"));
       
  2150         r = iController->SetSerialNumberStringDescriptor(iClient, *((TPtr8*) a1));
       
  2151         break;
       
  2152 
       
  2153     case RDevUsbcScClient::EControlRemoveSerialNumberStringDescriptor:
       
  2154         __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveSerialNumberStringDescriptor"));
       
  2155         r = iController->RemoveSerialNumberStringDescriptor();
       
  2156         break;
       
  2157 
       
  2158     case RDevUsbcScClient::EControlGetConfigurationStringDescriptor:
       
  2159         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetConfigurationStringDescriptor"));
       
  2160         r = iController->GetConfigurationStringDescriptor(iClient, *((TPtr8*) a1));
       
  2161         break;
       
  2162 
       
  2163     case RDevUsbcScClient::EControlSetConfigurationStringDescriptor:
       
  2164         __KTRACE_OPT(KUSB, Kern::Printf("EControlSetConfigurationStringDescriptor"));
       
  2165         r = iController->SetConfigurationStringDescriptor(iClient, *((TPtr8*) a1));
       
  2166         break;
       
  2167 
       
  2168     case RDevUsbcScClient::EControlRemoveConfigurationStringDescriptor:
       
  2169         __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveConfigurationStringDescriptor"));
       
  2170         r = iController->RemoveConfigurationStringDescriptor();
       
  2171         break;
       
  2172 
       
  2173     case RDevUsbcScClient::EControlGetStringDescriptor:
       
  2174         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetStringDescriptor"));
       
  2175         r = iController->GetStringDescriptor(iClient, (TUint8) (TInt) a1, *((TPtr8*) a2));
       
  2176         break;
       
  2177 
       
  2178     case RDevUsbcScClient::EControlSetStringDescriptor:
       
  2179         __KTRACE_OPT(KUSB, Kern::Printf("EControlSetStringDescriptor"));
       
  2180         r = iController->SetStringDescriptor(iClient, (TUint8) (TInt) a1, *((TPtr8*) a2));
       
  2181         break;
       
  2182 
       
  2183     case RDevUsbcScClient::EControlRemoveStringDescriptor:
       
  2184         __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveStringDescriptor"));
       
  2185         r = iController->RemoveStringDescriptor((TUint8) (TInt) a1);
       
  2186         break;
       
  2187 
       
  2188     case RDevUsbcScClient::EControlQueryEndpointResourceUse:
       
  2189         {
       
  2190         __KTRACE_OPT(KUSB, Kern::Printf("EControlQueryEndpointResourceUse"));
       
  2191         epRes = (TUsbcEndpointResource)((TInt) a2);
       
  2192         TInt realEp=-1;
       
  2193         r = GetRealEpForEpResource((TInt)a1, realEp);
       
  2194         if (r==KErrNone)
       
  2195             r = iController->QueryEndpointResource(this, realEp, epRes);
       
  2196         break;
       
  2197         }
       
  2198     case RDevUsbcScClient::EControlSetOtgDescriptor:
       
  2199         __KTRACE_OPT(KUSB, Kern::Printf("EControlSetOtgDescriptor"));
       
  2200         r = iController->SetOtgDescriptor(iClient, *((const TDesC8*)a1));
       
  2201         break;
       
  2202 
       
  2203     case RDevUsbcScClient::EControlGetOtgDescriptor:
       
  2204         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetOtgDescriptor"));
       
  2205         r = iController->GetOtgDescriptor(iClient, *((TDes8*)a1));
       
  2206         break;
       
  2207 
       
  2208     case RDevUsbcScClient::EControlGetOtgFeatures:
       
  2209         __KTRACE_OPT(KUSB, Kern::Printf("EControlGetOtgFeatures"));
       
  2210         r = iController->GetOtgFeatures(iClient, *((TDes8*)a1));
       
  2211         break;
       
  2212 
       
  2213     case RDevUsbcScClient::EControlRealizeInterface:
       
  2214         __KTRACE_OPT(KUSB, Kern::Printf("EControlRealizeInterface"));
       
  2215         r = RealizeInterface();
       
  2216         break;
       
  2217     case RDevUsbcScClient::EControlStartNextInAlternateSetting:
       
  2218         __KTRACE_OPT(KUSB, Kern::Printf("EControlStartNextInAlternateSetting"));
       
  2219         r = StartNextInAlternateSetting();
       
  2220         break;
       
  2221 
       
  2222     default:
       
  2223         __KTRACE_OPT(KUSB, Kern::Printf("Function code not supported"));
       
  2224         r = KErrNotSupported;
       
  2225         }
       
  2226 
       
  2227     return r;
       
  2228     }
       
  2229 // end DoControl.
       
  2230 
       
  2231 
       
  2232 
       
  2233 //
       
  2234 // Overriding DObject virtual
       
  2235 //
       
  2236 TInt DLddUsbcScChannel::RequestUserHandle(DThread* aThread, TOwnerType /*aType*/)
       
  2237     {
       
  2238     __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::RequestUserHandle"));
       
  2239     // The USB client LDD is not designed for a channel to be shared between
       
  2240     // threads. It saves a pointer to the current thread when it is opened, and
       
  2241     // uses this to complete any asynchronous requests.
       
  2242     // It is therefore not acceptable for the handle to be duplicated and used
       
  2243     // by another thread:
       
  2244     if (aThread == iClient)
       
  2245         {
       
  2246         return KErrNone;
       
  2247         }
       
  2248     else
       
  2249         {
       
  2250         return KErrAccessDenied;
       
  2251         }
       
  2252     }
       
  2253 
       
  2254 inline TInt DLddUsbcScChannel::GetRealEpForEpResource(TInt aEndpoint, TInt& aRealEp)
       
  2255     {
       
  2256     if (iEndpoint) // if we've enumerated at least once, proceed as normal.
       
  2257         {
       
  2258         if  (aEndpoint <= iNumberOfEndpoints && aEndpoint >= 0)
       
  2259             {
       
  2260             aRealEp=iEndpoint[aEndpoint]->RealEpNumber();
       
  2261             return KErrNone;
       
  2262             }
       
  2263         }
       
  2264     else // Assume alternate setting 0.
       
  2265         {
       
  2266         if (iAlternateSettingList)   // Check it has been set up.
       
  2267             {
       
  2268             TUsbcScAlternateSetting* alt = iAlternateSettingList->iHead;
       
  2269             if (alt &&  (aEndpoint <= alt->iNumberOfEndpoints && aEndpoint >= 0))
       
  2270                 {
       
  2271                 aRealEp= alt->iEndpoint[aEndpoint]->RealEpNumber();
       
  2272                 return KErrNone;
       
  2273                 }
       
  2274             }
       
  2275         }
       
  2276     return KErrUsbDeviceNotConfigured;
       
  2277     }
       
  2278 
       
  2279 
       
  2280 TUsbcEndpointInfoArray::TUsbcEndpointInfoArray(const TUsbcScEndpointInfo* aData, TInt aDataSize)
       
  2281     {
       
  2282     iType = EUsbcScEndpointInfo;
       
  2283     iData = (TUint8*) aData;    
       
  2284     if (aDataSize>0)
       
  2285         iDataSize = aDataSize;
       
  2286     else
       
  2287         iDataSize = sizeof(TUsbcScEndpointInfo);
       
  2288     }
       
  2289 
       
  2290 
       
  2291 //
       
  2292 // SetInterface
       
  2293 //
       
  2294 // Called from DoControl.  Sets the configuration of a given Interface.                    // Needs changing
       
  2295 // All interfaces must be configured before one can be used.  
       
  2296 //
       
  2297 
       
  2298 TInt DLddUsbcScChannel::SetInterface(TInt aInterfaceNumber, TUsbcScIfcInfo* aInfoBuf)
       
  2299     {
       
  2300     // Copy interface description.
       
  2301 
       
  2302     if (iRealizeCalled)
       
  2303         return KErrUsbAlreadyRealized;
       
  2304 
       
  2305     if (!iAlternateSettingList)
       
  2306         {
       
  2307         iAlternateSettingList = new TUsbcScAlternateSettingList;
       
  2308         if (iAlternateSettingList==NULL)
       
  2309             {
       
  2310             return KErrNoMemory;
       
  2311             }
       
  2312         }
       
  2313 
       
  2314     // Read descriptor in
       
  2315     TUsbcScInterfaceInfoBuf ifc_info_buf;
       
  2316     TUsbcScInterfaceInfoBuf* const ifc_info_buf_ptr = aInfoBuf->iInterfaceData;
       
  2317     const TInt srcLen = Kern::ThreadGetDesLength(iClient, ifc_info_buf_ptr);
       
  2318 
       
  2319     __KTRACE_OPT(KUSB, Kern::Printf("SetInterface srcLen = %d len = %d", srcLen, ifc_info_buf.Length() ));
       
  2320 
       
  2321     if (srcLen < ifc_info_buf.Length())
       
  2322         {
       
  2323         __KTRACE_OPT(KUSB, Kern::Printf("SetInterface can't copy"));
       
  2324         PanicClientThread(EDesOverflow);
       
  2325         }
       
  2326 
       
  2327     TInt r = Kern::ThreadDesRead(iClient, ifc_info_buf_ptr, ifc_info_buf, 0, KChunkShiftBy0);
       
  2328     if (r != KErrNone)
       
  2329         {
       
  2330         __KTRACE_OPT(KUSB, Kern::Printf("SetInterface Copy failed reason=%d", r));
       
  2331         PanicClientThread(r);
       
  2332         }
       
  2333 
       
  2334     // The list of endpoints is within the interface info.
       
  2335     TUsbcScEndpointInfo* pEndpointData = ifc_info_buf().iEndpointData;
       
  2336 
       
  2337     const TInt num_endpoints = ifc_info_buf().iTotalEndpointsUsed;
       
  2338     __KTRACE_OPT(KUSB, Kern::Printf("SetInterface num_endpoints=%d", num_endpoints));
       
  2339     if (num_endpoints>KMaxEndpointsPerClient)
       
  2340         return KErrOverflow;
       
  2341 
       
  2342 
       
  2343     // Initialize real ep numbers list.
       
  2344     TInt i;
       
  2345     TInt real_ep_numbers[KMaxEndpointsPerClient+1]; // range 1->KMaxEndpointsPerClient (0 not used)
       
  2346     for (i=0; i<=KMaxEndpointsPerClient; i++)
       
  2347         real_ep_numbers[i] = -1;
       
  2348 
       
  2349 
       
  2350     // See if PIL will accept this interface
       
  2351     __KTRACE_OPT(KUSB, Kern::Printf("SetInterface Calling controller"));
       
  2352     TUsbcEndpointInfoArray endpointData = TUsbcEndpointInfoArray(ifc_info_buf().iEndpointData);
       
  2353 
       
  2354     r = iController->SetInterface(this,
       
  2355                                   iClient,
       
  2356                                   aInterfaceNumber,
       
  2357                                   ifc_info_buf().iClass,
       
  2358                                   aInfoBuf->iString,
       
  2359                                   (TInt) ifc_info_buf().iTotalEndpointsUsed,
       
  2360                                   endpointData,
       
  2361                                   &real_ep_numbers[0],
       
  2362                                   ifc_info_buf().iFeatureWord);
       
  2363 
       
  2364     __KTRACE_OPT(KUSB, Kern::Printf("SetInterface controller returned %d", r));
       
  2365     if (r != KErrNone)
       
  2366         {
       
  2367         __KTRACE_OPT(KPANIC, Kern::Printf("SetInterface failed reason=%d", r));
       
  2368         return r;
       
  2369         }
       
  2370 
       
  2371     // create alternate setting record
       
  2372     TUsbcScAlternateSetting* alternateSettingListRec = new TUsbcScAlternateSetting;
       
  2373     if (!alternateSettingListRec)
       
  2374         {
       
  2375         r = KErrNoMemory;
       
  2376         goto ReleaseInterface;
       
  2377         }
       
  2378     
       
  2379     // other endpoints
       
  2380     for (TInt i = 1; i <= num_endpoints; i++, pEndpointData++)
       
  2381         {
       
  2382         __KTRACE_OPT(KUSB, Kern::Printf("SetInterface for ep=%d", i));
       
  2383 
       
  2384         if ((pEndpointData->iType==UsbShai::KUsbEpTypeControl)
       
  2385             || (pEndpointData->iDir != UsbShai::KUsbEpDirIn && pEndpointData->iDir != UsbShai::KUsbEpDirOut)
       
  2386             || (pEndpointData->iSize > 1024) || (pEndpointData->iSize<=0))
       
  2387             {
       
  2388             r = KErrUsbBadEndpoint;
       
  2389             goto CleanUp;
       
  2390             }
       
  2391         // Check data
       
  2392 
       
  2393         TUint* bufferSize = &(pEndpointData->iBufferSize);
       
  2394         if (*bufferSize==0)
       
  2395             *bufferSize= KUsbcScDefaultBufferSize;
       
  2396 
       
  2397         TInt pageSize = Kern::RoundToPageSize(1);
       
  2398         // Round buffersize up to nearest pagesize.
       
  2399         *bufferSize = (*bufferSize+pageSize-1) & ~(pageSize-1);
       
  2400 
       
  2401         TUsbcScEndpoint* ep = new TUsbcScEndpoint(this, iController, pEndpointData, i);
       
  2402         alternateSettingListRec->iEndpoint[i] = ep;
       
  2403         if (!ep)
       
  2404             {
       
  2405             r = KErrNoMemory;
       
  2406             goto CleanUp;
       
  2407             }
       
  2408         if (ep->Construct() != KErrNone)
       
  2409             {
       
  2410             r = KErrNoMemory;
       
  2411             goto CleanUp;
       
  2412             }
       
  2413 
       
  2414     
       
  2415         __KTRACE_OPT(KUSB, Kern::Printf("SetInterface for ep=%d rec=0x%08x ep==0x%08x",
       
  2416                                         i, alternateSettingListRec, ep));
       
  2417         }
       
  2418 
       
  2419     if (iAlternateSettingList->iHead)
       
  2420         {
       
  2421         iAlternateSettingList->iTail->iNext = alternateSettingListRec;
       
  2422         alternateSettingListRec->iPrevious = iAlternateSettingList->iTail;
       
  2423         iAlternateSettingList->iTail = alternateSettingListRec;    
       
  2424         }
       
  2425     else
       
  2426         {
       
  2427         iAlternateSettingList->iHead = alternateSettingListRec;    
       
  2428         iAlternateSettingList->iTail = alternateSettingListRec;    
       
  2429         }    
       
  2430     
       
  2431     alternateSettingListRec->iNext = NULL;
       
  2432     alternateSettingListRec->iSetting = aInterfaceNumber;
       
  2433     alternateSettingListRec->iNumberOfEndpoints = num_endpoints;
       
  2434 
       
  2435     // Record the 'real' endpoint number used by the PDD in both the Ep and
       
  2436     // the Req callback:
       
  2437     for (TInt i = 1; i <= num_endpoints; i++)
       
  2438         {
       
  2439         alternateSettingListRec->iEndpoint[i]->SetRealEpNumber(real_ep_numbers[i]);
       
  2440         }
       
  2441 
       
  2442     return KErrNone;
       
  2443 
       
  2444  CleanUp:
       
  2445     delete alternateSettingListRec;
       
  2446     //Fall Through
       
  2447 
       
  2448  ReleaseInterface:
       
  2449 #if _DEBUG
       
  2450     TInt r1 = iController->ReleaseInterface(this, aInterfaceNumber);
       
  2451     __KTRACE_OPT(KUSB, Kern::Printf("Release Interface controller returned %d", r1));
       
  2452 #else
       
  2453     (void)    iController->ReleaseInterface(this, aInterfaceNumber);
       
  2454 #endif
       
  2455     return r;
       
  2456     }
       
  2457 // end SetInterface
       
  2458 
       
  2459 
       
  2460 
       
  2461 #ifdef _DEBUG
       
  2462 void RealizeInterface_Dump(TUint* aMem)
       
  2463     {
       
  2464     TUint *mem= NULL;
       
  2465     __KTRACE_OPT(KUSB, mem = aMem);
       
  2466     if (mem!=NULL)
       
  2467         {
       
  2468         TInt j;
       
  2469          Kern::Printf("Final chunk header State:");
       
  2470         for (j=0; j<30; j+=8)
       
  2471              Kern::Printf("%2x: %8x %8x %8x %8x %8x %8x %8x %8x", j, mem[j], mem[j+1], mem[j+2], mem[j+3], mem[j+4], mem[j+5], mem[j+6], mem[j+7] );
       
  2472         };
       
  2473     };
       
  2474 #endif
       
  2475 
       
  2476 
       
  2477 /*
       
  2478 Chunk Created, filled with structure, and passed back to userside.
       
  2479 */
       
  2480 TInt DLddUsbcScChannel::RealizeInterface(void)
       
  2481 {
       
  2482     if (iRealizeCalled) 
       
  2483         return KErrUsbAlreadyRealized;
       
  2484 
       
  2485     TRealizeInfo bufInfo;
       
  2486     
       
  2487     TInt errorOrChunk = KErrNone;
       
  2488     TBool openedCS = EFalse;
       
  2489     TInt offset =0;
       
  2490         
       
  2491     // Start by creating a temporary scratchpad for endpoint calculations.
       
  2492     bufInfo.Init(iAlternateSettingList);
       
  2493 
       
  2494     // Fill in our scratchpad with all the required endpoints, sorting them
       
  2495     // in order of size required.
       
  2496     errorOrChunk = bufInfo.CopyAndSortEndpoints();
       
  2497     if (errorOrChunk!=KErrNone)
       
  2498         {
       
  2499         goto realize_end;
       
  2500         }
       
  2501 
       
  2502     // We now have endpoints sorted in order of size for each altsetting.
       
  2503     // The very largest for each endpoint will share the first buffer, and all of
       
  2504     // the second largest ends points will share the second buffer, and so on.
       
  2505     // Find the highest buffer size for each row, to determine the buffer size,
       
  2506     // and keep a total of total space needed. 
       
  2507     bufInfo.CalcBuffSizes();
       
  2508 
       
  2509     // We now have the max sizes wanted for each endpoint buffer.
       
  2510     // we also have to total size for all endpoints.
       
  2511     // and finally we have the total number of buffers.
       
  2512 
       
  2513     // Add on size for header, then add on size for guard pages.
       
  2514     bufInfo.iTotalSize+= KHeaderSize + bufInfo.iTotalBuffers * KGuardSize;
       
  2515 
       
  2516     // Create shared Chunk .  .  .  .  .  .  .  .  .  . 
       
  2517     if (iChunkInfo==NULL)
       
  2518         {
       
  2519             NKern::ThreadEnterCS();
       
  2520             openedCS = ETrue;
       
  2521             errorOrChunk = TUsbcScChunkInfo::New(iChunkInfo, bufInfo.iTotalSize, (DLogicalDevice*) iDevice);
       
  2522             if (errorOrChunk!=KErrNone)
       
  2523                 {
       
  2524                 goto realize_end;
       
  2525                 }
       
  2526         }
       
  2527     else
       
  2528         {
       
  2529         // As of writing, the was no way for iChunk to be anything other then NULL.  
       
  2530         // You cannot 'unrealise' and iChunk cannot be set any other way.
       
  2531         Kern::Fault("DLddUsbcScChannel::RealizeInterface", __LINE__);
       
  2532         }
       
  2533 
       
  2534     // Populate the shared chunk . .  . . . . . 
       
  2535 
       
  2536 
       
  2537     // First create chunk header.
       
  2538     errorOrChunk = iChunkInfo->ChunkAlloc(offset, KHeaderSize);
       
  2539     if (errorOrChunk!=KErrNone)
       
  2540         {
       
  2541         if (errorOrChunk==-KErrNoMemory)
       
  2542             errorOrChunk=KErrNoMemory;
       
  2543         goto realize_end;
       
  2544         } 
       
  2545 
       
  2546 
       
  2547     offset+=KHeaderSize + KGuardSize; // Also any more for EP0?
       
  2548 
       
  2549     // Next, lay out the geometry of the chunk header.
       
  2550 
       
  2551     bufInfo.LayoutChunkHeader(iChunkInfo);        
       
  2552 
       
  2553 
       
  2554     { // Scope ep0Size
       
  2555     TInt ep0Size=0;
       
  2556     
       
  2557     // Create K-side buffer table
       
  2558     if (!iBuffers)
       
  2559         iBuffers = (TUsbcScBuffer *) Kern::AllocZ(sizeof(TUsbcScBuffer) * (bufInfo.iTotalBuffers+2)); // +2 is for ep0.
       
  2560     if (!iBuffers)
       
  2561         {
       
  2562         __KTRACE_OPT(KUSB, Kern::Printf("Realize: Error: Alloc iBufers failed!"));
       
  2563         errorOrChunk = KErrNoMemory;
       
  2564         goto realize_end;
       
  2565         }
       
  2566 
       
  2567 
       
  2568     errorOrChunk = SetupEp0();
       
  2569     if (errorOrChunk)
       
  2570         {
       
  2571         __KTRACE_OPT(KUSB, Kern::Printf("Realize: SetupEp0 . ERROR %d",errorOrChunk));
       
  2572         goto realize_end;
       
  2573         }
       
  2574 
       
  2575     ep0Size = iEp0Endpoint->EndpointInfo()->iSize;
       
  2576     __KTRACE_OPT(KUSB, Kern::Printf("Realize: Setup EP0. max packet size %d", ep0Size));
       
  2577 
       
  2578     // Create EP0 buffers
       
  2579     iEP0OutBuff=bufInfo.iTotalBuffers;
       
  2580     errorOrChunk = iBuffers[iEP0OutBuff].Construct(KUsbcScBiOut,  this,   KUsbScEP0OutBufPos, KUsbScEP0OutBufEnd, ep0Size, ep0Size, ep0Size);
       
  2581     if (errorOrChunk)
       
  2582         {
       
  2583         __KTRACE_OPT(KUSB, Kern::Printf("Realize: Setup EP0 Out. ERROR %d",errorOrChunk));
       
  2584         goto realize_end;
       
  2585         }
       
  2586 
       
  2587     iBuffers[iEP0OutBuff].CreateChunkBufferHeader();
       
  2588     iBuffers[iEP0OutBuff].iCallback =  iEp0Endpoint->iRequestCallbackInfo;
       
  2589     ((TUsbcScBufferRecord*) &(
       
  2590                             bufInfo.iChunkStuct->iBufferOffset[KUsbcScEp0OutBuff*sizeof(TUsbcScBufferRecord)]
       
  2591                             )) ->Set(KUsbScEP0OutBufPos, KUsbScEP0OutBufEnd);
       
  2592 
       
  2593 
       
  2594     iEP0InBuff=bufInfo.iTotalBuffers+1;
       
  2595     errorOrChunk = iBuffers[iEP0InBuff].Construct( KUsbcScBiIn ,  this,   KUsbScEP0InBufPos , KUsbScEP0InBufEnd , ep0Size, ep0Size, ep0Size);    
       
  2596     if (errorOrChunk)
       
  2597         {
       
  2598         __KTRACE_OPT(KUSB, Kern::Printf("Realize: Setup EP0 In. ERROR %d",errorOrChunk));
       
  2599         goto realize_end;
       
  2600         }
       
  2601     
       
  2602     iBuffers[iEP0InBuff].iCallback =  iEp0Endpoint->iRequestCallbackInfo;
       
  2603 
       
  2604       ((TUsbcScBufferRecord*) &(
       
  2605                                   bufInfo.iChunkStuct->iBufferOffset[KUsbcScEp0InBuff*sizeof(TUsbcScBufferRecord)]
       
  2606                                 ))->Set(KUsbScEP0InBufPos, KUsbScEP0InBufEnd);
       
  2607 
       
  2608 
       
  2609     } // end ep0Size scope
       
  2610 
       
  2611     // Create resources and tables.  .   .   .   .   .
       
  2612     __KTRACE_OPT(KUSB, Kern::Printf("Realize: Create resources tables"));
       
  2613 
       
  2614     { // scope of bufNum
       
  2615     // For each EP buffer
       
  2616     TInt buffNum=0;
       
  2617     TInt buffMinSize;
       
  2618     TInt endpointNumber;
       
  2619     TUsbcScEndpoint* endpointRecord;
       
  2620     TInt endpoint;
       
  2621     TInt inout;
       
  2622     TEndpointSortBufs* bufsd;
       
  2623     TUsbcScHdrEndpointRecord* epRecord;
       
  2624     for (endpoint=0; endpoint<bufInfo.iMaxEndpoints; endpoint++)  // endpoint = buf row.
       
  2625         {
       
  2626         for (inout=KUsbcScIn; inout<KUsbcScDirections; inout++)
       
  2627             {
       
  2628             buffMinSize = KUsbSc_BigBuff_MinimumRamRun;
       
  2629 
       
  2630             TInt needed =  bufInfo.iBufs[inout].iSizes[endpoint];
       
  2631             if (needed) 
       
  2632                 {
       
  2633                 TInt bufStart = offset;
       
  2634 
       
  2635                 __KTRACE_OPT(KUSB, Kern::Printf("Realize:    buf row:%d inout %d, iBufferOffset[%d+2]=%x",endpoint, inout, buffNum, bufStart));
       
  2636 
       
  2637                 bufsd =  &(bufInfo.iBufs[inout]);
       
  2638                 // and then point all endpoints that use it, towards it.
       
  2639                 TInt altSetting;    
       
  2640                 TUint maxReadSize = ~0;
       
  2641                 for (altSetting=0; altSetting < bufInfo.iAltSettings; altSetting++)
       
  2642                     {
       
  2643                     endpointRecord =bufsd->iEp[altSetting*bufInfo.iMaxEndpoints + endpoint];
       
  2644                     if (endpointRecord)
       
  2645                         {
       
  2646                         endpointNumber = endpointRecord->EpNumber();
       
  2647                         endpointRecord->SetBuffer(&iBuffers[buffNum]);
       
  2648                 
       
  2649                         epRecord = (TUsbcScHdrEndpointRecord*) &iChunkInfo->iChunkMem[
       
  2650                                                                 (bufInfo.iAltSettingsTbl->iAltTableOffset[altSetting])     // i.e. Just after altSettingsTbl
       
  2651                                                                 +sizeof(TInt)                                    // after number of endpoints field
       
  2652                                                                 +(endpointNumber-1)*sizeof(TUsbcScHdrEndpointRecord)
       
  2653                                                                 ];
       
  2654                         epRecord->iBufferNo = (TUint8) buffNum;
       
  2655 
       
  2656                     TInt epType=(endpointRecord->EndpointInfo()->iType);
       
  2657                     epType= (epType& UsbShai::KUsbEpTypeControl)?KUsbScHdrEpTypeControl:
       
  2658                             (epType& UsbShai::KUsbEpTypeIsochronous)?KUsbScHdrEpTypeIsochronous:
       
  2659                             (epType& UsbShai::KUsbEpTypeBulk)?KUsbScHdrEpTypeBulk:
       
  2660                             (epType& UsbShai::KUsbEpTypeInterrupt)?KUsbScHdrEpTypeInterrupt:KUsbScHdrEpTypeUnknown;
       
  2661 
       
  2662                     epRecord->iType = (inout+1) | (epType<<2);
       
  2663 
       
  2664                     if (endpointRecord->EndpointInfo()->iReadSize)
       
  2665                         maxReadSize = (maxReadSize <= endpointRecord->EndpointInfo()->iReadSize) ? maxReadSize : endpointRecord->EndpointInfo()->iReadSize;
       
  2666                     
       
  2667                     __KTRACE_OPT(KUSB, Kern::Printf("Realize:      endpointNum %d in altSetting %d, alt table @ %d",
       
  2668                                                      endpointNumber, altSetting,bufInfo.iAltSettingsTbl->iAltTableOffset[altSetting]));
       
  2669                         }
       
  2670                     else
       
  2671                         {
       
  2672                         __KTRACE_OPT(KUSB, Kern::Printf("Realize:      endpointNum NA in altSetting %d", altSetting));
       
  2673                         }
       
  2674 
       
  2675                     } // end for
       
  2676 
       
  2677 
       
  2678                 // Alloc memory for buffer.
       
  2679                 TInt grabSize = needed;
       
  2680                 // Generally, a buffer fragmented into smaller memory regions will reduce the efficiency 
       
  2681                 // of reading or writing data, and so avoiding the allocation of very small sections
       
  2682                 // is advantageous.
       
  2683                 // However, if only a small amount is being allocated to start with, it is likely
       
  2684                 // smaller amounts of data are to be sent (reducing this advantage), and 1 memory page 
       
  2685                 // is a much bigger proportion of the buffer, and so more worth allocating individually.
       
  2686 
       
  2687                 TInt minimumGrab;
       
  2688                 if (needed<KUsbScBigBuffIs)
       
  2689                     {
       
  2690                     minimumGrab=Kern::RoundToPageSize(1);
       
  2691                     buffMinSize = KUsbSc_SmallBuff_MinimumRamRun; // 1k
       
  2692                     }
       
  2693                 else
       
  2694                     {
       
  2695                     minimumGrab = buffMinSize+Kern::RoundToPageSize(1);
       
  2696                     }
       
  2697 
       
  2698                 // Grab required memory, in bits as big as possible, down to the minimum size. 
       
  2699                 while (needed >= minimumGrab)
       
  2700                     {
       
  2701                     TInt r;
       
  2702                     r = iChunkInfo->ChunkAlloc(offset, grabSize);
       
  2703                     if (r==KErrNone)
       
  2704                         {
       
  2705                         offset+=grabSize;    
       
  2706                         needed-=grabSize;
       
  2707                         }
       
  2708                     else
       
  2709                         {
       
  2710                         if (r==-KErrNoMemory)
       
  2711                             {
       
  2712                             grabSize>>=1;
       
  2713                             }
       
  2714                         if ((grabSize<minimumGrab) || (r!=-KErrNoMemory))
       
  2715                             {
       
  2716                             errorOrChunk = r;
       
  2717                             goto realize_end;
       
  2718                             }
       
  2719                         }
       
  2720                     } // end while needed
       
  2721                 
       
  2722                 // Initialize buffer
       
  2723                 iBuffers[buffNum].Construct(inout,  this,   bufStart, offset, buffMinSize, 0, maxReadSize);
       
  2724                 iBuffers[buffNum].CreateChunkBufferHeader();
       
  2725                 ((TUsbcScBufferRecord*) &(
       
  2726                                         bufInfo.iChunkStuct->iBufferOffset[(buffNum+2)*sizeof(TUsbcScBufferRecord)]
       
  2727                                         ))->Set(bufStart, offset);
       
  2728 
       
  2729 
       
  2730                 // inc pointers for next buffer
       
  2731                 buffNum++;
       
  2732                 offset+=KGuardSize;
       
  2733                 } // end if needed
       
  2734 
       
  2735             } // end for inout
       
  2736         } // end for each buffer
       
  2737     } // scope of bufNum 
       
  2738 
       
  2739 #ifdef _DEBUG
       
  2740  RealizeInterface_Dump((TUint*) iChunkInfo->iChunkMem); // Debug only tracing
       
  2741 #endif
       
  2742 
       
  2743 realize_end:
       
  2744     __KTRACE_OPT(KUSB, Kern::Printf("Realize: cleanup.  Err=%d", errorOrChunk));
       
  2745     // Here we clean up after either success, or after bailing out early.
       
  2746 
       
  2747     bufInfo.Free();
       
  2748     
       
  2749     if (iChunkInfo)
       
  2750         {
       
  2751         if (errorOrChunk==KErrNone)
       
  2752             { 
       
  2753             // Everything is looking good - create RChunk for Userside.
       
  2754             errorOrChunk = Kern::MakeHandleAndOpen(iClient, iChunkInfo->iChunk);
       
  2755             iRealizeCalled = (errorOrChunk>=0);
       
  2756             } // endif errorOrChunk
       
  2757 
       
  2758         if (errorOrChunk<0)  // If error, destroy the chunk.
       
  2759             {
       
  2760             iChunkInfo->Close();
       
  2761             // ChunkInfo will delete itself with DFC, but the pointer here is no longer needed.
       
  2762             iChunkInfo=NULL;
       
  2763 
       
  2764             // Destroy iBuffers
       
  2765             if (iBuffers)
       
  2766                 {
       
  2767                 TInt i;
       
  2768                 for (i=0; i<(iNumBuffers+2); i++) 
       
  2769                     {
       
  2770                     iBuffers[i].iStatusList.Destroy();
       
  2771                     }
       
  2772                 Kern::Free(iBuffers);
       
  2773                 iBuffers=NULL;
       
  2774                 }
       
  2775 
       
  2776             }
       
  2777         else
       
  2778             {
       
  2779             iNumBuffers = bufInfo.iTotalBuffers;
       
  2780             iValidInterface = ETrue;  // Let the games commence!
       
  2781             }
       
  2782 
       
  2783         } // endif iChunkInfo
       
  2784     if (openedCS)
       
  2785         NKern::ThreadLeaveCS();
       
  2786 
       
  2787     __KTRACE_OPT(KUSB, Kern::Printf("Realize: returning %x (%d)", errorOrChunk, errorOrChunk));
       
  2788     return errorOrChunk;
       
  2789 } // End RealizeInterface
       
  2790 
       
  2791 
       
  2792 //
       
  2793 // DestroyAllInterfaces
       
  2794 //
       
  2795 
       
  2796 void DLddUsbcScChannel::DestroyAllInterfaces()
       
  2797     {
       
  2798     __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DestroyAllInterfaces"));
       
  2799     // Removes all interfaces
       
  2800     if (iAlternateSettingList)
       
  2801         {
       
  2802         if (iAlternateSettingList->iHead != NULL)
       
  2803             {
       
  2804             TUsbcScAlternateSetting* alternateSettingListRec = iAlternateSettingList->iTail;
       
  2805             while (alternateSettingListRec)
       
  2806                 {
       
  2807                 iAlternateSettingList->iTail = alternateSettingListRec->iPrevious; 
       
  2808                 // If this contains NULL now that is only possible if the record to be deleted was at the head
       
  2809                 __KTRACE_OPT(KUSB, Kern::Printf("Release interface %d \n", alternateSettingListRec->iSetting));
       
  2810                 iController->ReleaseInterface(this, alternateSettingListRec->iSetting);
       
  2811                 delete alternateSettingListRec;
       
  2812                 if (iAlternateSettingList->iTail == NULL) //No more interfaces left 
       
  2813                     break;
       
  2814                 else
       
  2815                     {
       
  2816                     iAlternateSettingList->iTail->iNext = NULL;
       
  2817                     alternateSettingListRec = iAlternateSettingList->iTail;
       
  2818                     }
       
  2819                 }
       
  2820             }
       
  2821         delete iAlternateSettingList;    
       
  2822         }
       
  2823 
       
  2824     iNumberOfEndpoints = 0;
       
  2825     iAlternateSettingList = NULL;
       
  2826     iValidInterface = EFalse;
       
  2827 
       
  2828     __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DestroyAllInterfaces done"));
       
  2829     }
       
  2830 
       
  2831 
       
  2832         
       
  2833 
       
  2834 
       
  2835 //
       
  2836 // DestroyInterface
       
  2837 //
       
  2838 
       
  2839 void DLddUsbcScChannel::DestroyInterface(TUint aInterfaceNumber)
       
  2840     {
       
  2841     __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DestroyInterface \n"));
       
  2842     
       
  2843     if (iAlternateSetting == aInterfaceNumber)
       
  2844         {
       
  2845         ResetInterface(KErrUsbInterfaceNotReady);
       
  2846         iValidInterface = EFalse;
       
  2847         iNumberOfEndpoints = 0;
       
  2848         }
       
  2849     if (iAlternateSettingList)
       
  2850         {
       
  2851         TUsbcScAlternateSetting* alternateSettingListRec = iAlternateSettingList->iTail;
       
  2852         TUsbcScAlternateSetting* alternateSettingListRecFound = NULL;
       
  2853         while (alternateSettingListRec)
       
  2854             {
       
  2855             if (alternateSettingListRec->iSetting == aInterfaceNumber)
       
  2856                 {
       
  2857                 alternateSettingListRecFound = alternateSettingListRec;
       
  2858                 if (alternateSettingListRec->iPrevious == NULL)    //Interface is at HEAD OF List, Should only be if Interface is also at Tail of list
       
  2859                     {
       
  2860                     iAlternateSettingList->iHead = alternateSettingListRec->iNext;    // Should be NULL
       
  2861                     if (alternateSettingListRec->iNext)
       
  2862                         iAlternateSettingList->iHead->iPrevious = NULL;
       
  2863                     }
       
  2864                 else if (alternateSettingListRec->iNext == NULL) //Interface is at TAIL OF List
       
  2865                     {
       
  2866                     iAlternateSettingList->iTail = alternateSettingListRecFound->iPrevious;
       
  2867                     iAlternateSettingList->iTail->iNext = NULL;
       
  2868                     }
       
  2869                 else    //Somewhere in the middle (would not expect this in normal operation, but here for completeness)
       
  2870                     {
       
  2871                     __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DestroyInterface Middle interface!\n"));
       
  2872                     alternateSettingListRec->iPrevious->iNext = alternateSettingListRec->iNext;
       
  2873                     alternateSettingListRec->iNext->iPrevious = alternateSettingListRec->iPrevious;
       
  2874                     }    
       
  2875 
       
  2876                 delete alternateSettingListRecFound;
       
  2877                 break;
       
  2878                 }
       
  2879              alternateSettingListRec = alternateSettingListRec->iPrevious;
       
  2880             }
       
  2881         }
       
  2882     }
       
  2883 
       
  2884 //
       
  2885 // SetupEp0
       
  2886 //
       
  2887 
       
  2888 TInt DLddUsbcScChannel::SetupEp0()
       
  2889     {
       
  2890     __ASSERT_ALWAYS(iEp0Endpoint==NULL, Kern::Fault("DLddUsbcScChannel::SetupEp0", __LINE__));
       
  2891 
       
  2892     TUsbcScEndpointInfo ep0Info = TUsbcScEndpointInfo(UsbShai::KUsbEpTypeControl, UsbShai::KUsbEpDirBidirect);
       
  2893     ep0Info.iSize =  iController->Ep0PacketSize();
       
  2894 
       
  2895     TUsbcScEndpoint* ep0 = new TUsbcScEndpoint(this, iController, &ep0Info, 0);
       
  2896     if (ep0 == NULL)
       
  2897         {
       
  2898         return KErrNoMemory;
       
  2899         }
       
  2900 
       
  2901     TInt r = ep0->Construct();
       
  2902     if (r != KErrNone)
       
  2903         {
       
  2904         delete ep0;
       
  2905         return KErrNoMemory;
       
  2906         }
       
  2907 
       
  2908     ep0->SetRealEpNumber(0);
       
  2909     ep0->SetBuffer(NULL); // Cannot find it this way.
       
  2910 
       
  2911     iEp0Endpoint = ep0;
       
  2912     return KErrNone;
       
  2913     }
       
  2914 
       
  2915 //
       
  2916 // DestroyEp0
       
  2917 //
       
  2918 
       
  2919 void DLddUsbcScChannel::DestroyEp0()
       
  2920     {
       
  2921     __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DestroyEp0"));
       
  2922     delete iEp0Endpoint;
       
  2923     iEp0Endpoint = NULL;
       
  2924     }
       
  2925 
       
  2926 
       
  2927 void DLddUsbcScChannel::RequestCallbackEp0(TAny* aDLddUsbcScChannel)
       
  2928     {
       
  2929     DLddUsbcScChannel* channel = (DLddUsbcScChannel*) aDLddUsbcScChannel;
       
  2930 
       
  2931     __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::RequestCallbackEp0"));
       
  2932 
       
  2933     if (channel->ChannelClosing())
       
  2934         {
       
  2935         __KTRACE_OPT(KUSB, Kern::Printf("Channel Closing: Completion not accepted!"));
       
  2936         return;
       
  2937         }
       
  2938 
       
  2939     switch (channel->iEp0Endpoint->iRequestCallbackInfo->iTransferDir)
       
  2940         {
       
  2941     case UsbShai::EControllerWrite:
       
  2942         channel->iBuffers[channel->iEP0InBuff].CompleteWrite();
       
  2943         return;
       
  2944     case UsbShai::EControllerRead:
       
  2945         channel->iBuffers[channel->iEP0OutBuff].CompleteRead();
       
  2946         return;
       
  2947     default:
       
  2948         Kern::Printf("DLddUsbcScChannel::RequestCallbackEp0 - Unexpected completion direction %d",channel->iEp0Endpoint->iRequestCallbackInfo->iTransferDir);
       
  2949         Kern::Fault("DLddUsbcScChannel::RequestCallbackEp0", __LINE__);
       
  2950         } 
       
  2951     }
       
  2952 
       
  2953 
       
  2954 
       
  2955 
       
  2956 
       
  2957 
       
  2958 //
       
  2959 // EndpointStatusChangeCallback
       
  2960 //
       
  2961 
       
  2962 void DLddUsbcScChannel::EndpointStatusChangeCallback(TAny* aDLddUsbcScChannel)
       
  2963     {
       
  2964     __KTRACE_OPT(KUSB, Kern::Printf("EndpointStatusChangeCallback"));
       
  2965     DLddUsbcScChannel* dUsbc = (DLddUsbcScChannel*) aDLddUsbcScChannel;
       
  2966     if (dUsbc->iChannelClosing)
       
  2967         return;
       
  2968     TUint endpointState = dUsbc->iEndpointStatusCallbackInfo.State();
       
  2969     const TInt reqNo = (TInt) RDevUsbcScClient::ERequestEndpointStatusNotify;
       
  2970     if (dUsbc->iRequestStatus[reqNo])
       
  2971         {
       
  2972         __KTRACE_OPT(KUSB, Kern::Printf("EndpointStatusChangeCallback Notify status"));
       
  2973         DThread* client = dUsbc->iClient;
       
  2974         // set client descriptor length to zero
       
  2975         TInt r = Kern::ThreadRawWrite(client, dUsbc->iEndpointStatusChangePtr, &endpointState,
       
  2976                                       sizeof(TUint), client);
       
  2977         if (r != KErrNone)
       
  2978             dUsbc->PanicClientThread(r);
       
  2979         Kern::RequestComplete(dUsbc->iClient, dUsbc->iRequestStatus[reqNo], r);
       
  2980         dUsbc->iEndpointStatusChangePtr = NULL;
       
  2981         }
       
  2982     }
       
  2983 
       
  2984 
       
  2985 //
       
  2986 // StatusChangeCallback
       
  2987 //
       
  2988 
       
  2989 void DLddUsbcScChannel::StatusChangeCallback(TAny* aDLddUsbcScChannel)
       
  2990     {
       
  2991     DLddUsbcScChannel* dUsbc = (DLddUsbcScChannel*) aDLddUsbcScChannel;
       
  2992     if (dUsbc->iChannelClosing)
       
  2993         return;
       
  2994 
       
  2995     TUsbcDeviceState deviceState;
       
  2996     TInt i;
       
  2997      for (i = 0;
       
  2998           (i < KUsbcDeviceStateRequests) && ((deviceState = dUsbc->iStatusCallbackInfo.State(i)) != UsbShai::EUsbPeripheralNoState);
       
  2999           ++i)
       
  3000         {
       
  3001          __KTRACE_OPT(KUSB, Kern::Printf("StatusChangeCallBack status=%d", deviceState));
       
  3002         if (deviceState & KUsbAlternateSetting)
       
  3003             {
       
  3004             dUsbc->ProcessAlternateSetting(deviceState);
       
  3005             }
       
  3006         else
       
  3007             {
       
  3008             dUsbc->ProcessDeviceState(deviceState);
       
  3009             // Send Status to EP0 buffer.        
       
  3010             // Before the client calls RDevUsbcScClient::FinalizeInterface(),
       
  3011             // this function might be called.
       
  3012             // So we add a guard for dUsbc->iBuffers
       
  3013             if( dUsbc->iBuffers )
       
  3014                 {
       
  3015                 dUsbc->iBuffers[dUsbc->iEP0OutBuff].SendEp0StatusPacket(deviceState);
       
  3016                 }
       
  3017             }
       
  3018 
       
  3019         // Only queue if userside is interested
       
  3020         if (dUsbc->iDeviceStatusNeeded)
       
  3021             {
       
  3022             dUsbc->iStatusFifo->AddStatusToQueue(deviceState);
       
  3023             const TInt reqNo = (TInt) RDevUsbcScClient::ERequestAlternateDeviceStatusNotify;
       
  3024             if (dUsbc->AlternateDeviceStateTestComplete())
       
  3025                 Kern::RequestComplete(dUsbc->iClient, dUsbc->iRequestStatus[reqNo], KErrNone);
       
  3026             }
       
  3027         }
       
  3028      // We don't want to be interrupted in the middle of this:
       
  3029     const TInt irqs = NKern::DisableInterrupts(2);
       
  3030      dUsbc->iStatusCallbackInfo.ResetState();
       
  3031     NKern::RestoreInterrupts(irqs);
       
  3032     }
       
  3033 
       
  3034 
       
  3035 void DLddUsbcScChannel::OtgFeatureChangeCallback(TAny* aDLddUsbcScChannel)
       
  3036     {
       
  3037     __KTRACE_OPT(KUSB, Kern::Printf("OtgFeatureChangeCallback"));
       
  3038     DLddUsbcScChannel* dUsbc = (DLddUsbcScChannel*) aDLddUsbcScChannel;
       
  3039     if (dUsbc->iChannelClosing)
       
  3040         return;
       
  3041 
       
  3042     TUint8 features;
       
  3043     // No return value check. Assume OTG always supported here
       
  3044     dUsbc->iController->GetCurrentOtgFeatures(features);
       
  3045 
       
  3046     const TInt reqNo = (TInt) RDevUsbcScClient::ERequestOtgFeaturesNotify;
       
  3047     if (dUsbc->iRequestStatus[reqNo])
       
  3048         {
       
  3049         __KTRACE_OPT(KUSB, Kern::Printf("OtgFeatureChangeCallback Notify status"));
       
  3050         TInt r = Kern::ThreadRawWrite(dUsbc->iClient, dUsbc->iOtgFeatureChangePtr,
       
  3051                                       &features, sizeof(TUint8), dUsbc->iClient);
       
  3052         if (r != KErrNone)
       
  3053             dUsbc->PanicClientThread(r);
       
  3054         Kern::RequestComplete(dUsbc->iClient, dUsbc->iRequestStatus[reqNo], r);
       
  3055         dUsbc->iOtgFeatureChangePtr = NULL;
       
  3056         }
       
  3057     }
       
  3058 
       
  3059 
       
  3060 //
       
  3061 // SelectAlternateSetting
       
  3062 //
       
  3063 
       
  3064 TInt DLddUsbcScChannel::SelectAlternateSetting(TUint aAlternateSetting)
       
  3065     {
       
  3066     TUsbcScEndpoint* ep;
       
  3067 
       
  3068     // First, find the alt setting record, which corresponds to the alt setting number.
       
  3069     TUsbcScAlternateSetting* alternateSettingListRec;
       
  3070     if(iAlternateSettingList)
       
  3071         {
       
  3072         for (alternateSettingListRec = iAlternateSettingList->iHead; alternateSettingListRec; alternateSettingListRec = alternateSettingListRec->iNext)
       
  3073             if (alternateSettingListRec->iSetting == aAlternateSetting)
       
  3074                 {
       
  3075                 // Record has been located.
       
  3076 
       
  3077                 // Update current ep setting vars 
       
  3078                 iEndpoint = alternateSettingListRec->iEndpoint;
       
  3079                 iNumberOfEndpoints = alternateSettingListRec->iNumberOfEndpoints;
       
  3080 
       
  3081 
       
  3082 
       
  3083                 // Reset buffers for new ep set
       
  3084                 for (TInt i = 1; i <= KMaxEndpointsPerClient; i++)
       
  3085                     {
       
  3086                     ep = alternateSettingListRec->iEndpoint[i];
       
  3087                     if (ep!=NULL)
       
  3088                         ep->StartBuffer(); // Buffer::StartEndpoint(...)   sets the necessary parameters to the buffer, for use for a perticular endpoint.
       
  3089                     }
       
  3090 
       
  3091                 return KErrNone;
       
  3092                 }
       
  3093         }
       
  3094     return KErrGeneral;
       
  3095     }
       
  3096 
       
  3097 /* The user calls this to move into the next alternate setting.  After this call, it is assumed the user wants to
       
  3098 Transmit using endpoints belonging to this alternate Setting.  Writes to the IN endpoints will be allowed until
       
  3099 the host changed the alternate setting again
       
  3100 Returns a 32 int with the top 16 bits represents the sequance, and the botten, the alternatre setting no.
       
  3101 */
       
  3102 TInt32 DLddUsbcScChannel::StartNextInAlternateSetting()
       
  3103     {
       
  3104     iUserKnowsAltSetting = ETrue;
       
  3105     return iAsSeq<<16 | iAlternateSetting;
       
  3106     } 
       
  3107 
       
  3108 
       
  3109 //
       
  3110 // EpFromAlternateSetting
       
  3111 //
       
  3112 
       
  3113 TInt DLddUsbcScChannel::EpFromAlternateSetting(TUint aAlternateSetting, TInt aEndpoint)
       
  3114     {
       
  3115     TUsbcScAlternateSetting* alternateSettingListRec = iAlternateSettingList->iHead;
       
  3116     while (alternateSettingListRec)
       
  3117         {
       
  3118         if (alternateSettingListRec->iSetting == aAlternateSetting)
       
  3119             {
       
  3120             if ((aEndpoint <= alternateSettingListRec->iNumberOfEndpoints) &&
       
  3121                 (aEndpoint > 0))
       
  3122                 {
       
  3123                 return alternateSettingListRec->iEndpoint[aEndpoint]->RealEpNumber();
       
  3124                 }
       
  3125             else
       
  3126                 {
       
  3127                 __KTRACE_OPT(KPANIC, Kern::Printf("  Error: aEndpoint %d wrong for aAlternateSetting %d",
       
  3128                                                   aEndpoint, aAlternateSetting));
       
  3129                 return KErrNotFound;
       
  3130                 }
       
  3131             }
       
  3132         alternateSettingListRec = alternateSettingListRec->iNext;
       
  3133         }
       
  3134     __KTRACE_OPT(KPANIC, Kern::Printf("  Error: no aAlternateSetting %d found", aAlternateSetting));
       
  3135     return KErrNotFound;
       
  3136     }
       
  3137 
       
  3138 //
       
  3139 // ProcessAlternateSetting
       
  3140 //
       
  3141 
       
  3142 TInt DLddUsbcScChannel::ProcessAlternateSetting(TUint aAlternateSetting)
       
  3143     {
       
  3144 
       
  3145     TUint newSetting = aAlternateSetting&(~KUsbAlternateSetting);
       
  3146     __KTRACE_OPT(KUSB, Kern::Printf("ProcessAlternateSetting 0x%08x selecting alternate setting 0x%08x", aAlternateSetting, newSetting));
       
  3147     iUserKnowsAltSetting=EFalse;
       
  3148     iAlternateSetting = newSetting;
       
  3149     iAsSeq++; 
       
  3150     
       
  3151     ResetInterface(KErrUsbInterfaceChange);                    // kill any outstanding IN transfers
       
  3152 
       
  3153     TInt r = SelectAlternateSetting(newSetting);
       
  3154     if (r != KErrNone)
       
  3155         return r;
       
  3156 
       
  3157 
       
  3158     StartEpReads();
       
  3159     return KErrNone;
       
  3160     }
       
  3161 
       
  3162 
       
  3163 //
       
  3164 //  ProcessDeviceState
       
  3165 //
       
  3166 // Called from StatusChangeCallback.
       
  3167 
       
  3168 TInt DLddUsbcScChannel::ProcessDeviceState(TUsbcDeviceState aDeviceState)
       
  3169     {
       
  3170     __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::ProcessDeviceState(%d -> %d)", iDeviceState, aDeviceState));
       
  3171     if (iDeviceState == aDeviceState)
       
  3172         {
       
  3173         __KTRACE_OPT(KUSB, Kern::Printf("  No state change => nothing to be done."));
       
  3174         return KErrNone;
       
  3175         }
       
  3176     if (iDeviceState == UsbShai::EUsbPeripheralStateSuspended)
       
  3177         {
       
  3178         __KTRACE_OPT(KUSB, Kern::Printf("  Coming out of Suspend: old state = %d", iOldDeviceState));
       
  3179         iDeviceState = iOldDeviceState;
       
  3180         if (iDeviceState == aDeviceState)
       
  3181             {
       
  3182             __KTRACE_OPT(KUSB, Kern::Printf("  New state same as before Suspend => nothing to be done."));
       
  3183             return KErrNone;
       
  3184             }
       
  3185         }
       
  3186     TBool renumerateState = (aDeviceState == UsbShai::EUsbPeripheralStateConfigured);
       
  3187     TBool deconfigured = EFalse;
       
  3188     TInt cancellationCode = KErrNone;
       
  3189     if (aDeviceState == UsbShai::EUsbPeripheralStateSuspended)
       
  3190         {
       
  3191         __KTRACE_OPT(KUSB, Kern::Printf("  Suspending..."));
       
  3192         iOldDeviceState = iDeviceState;
       
  3193         // Put PSL into low power mode here
       
  3194         }
       
  3195     else
       
  3196         {
       
  3197         deconfigured = (iDeviceState == UsbShai::EUsbPeripheralStateConfigured &&
       
  3198                         aDeviceState != UsbShai::EUsbPeripheralStateConfigured);
       
  3199         if (iDeviceState == UsbShai::EUsbPeripheralStateConfigured)
       
  3200             {
       
  3201             if (aDeviceState == UsbShai::EUsbPeripheralStateUndefined)
       
  3202                 cancellationCode = KErrUsbCableDetached;
       
  3203             else if (aDeviceState == UsbShai::EUsbPeripheralStateAddress)
       
  3204                 cancellationCode = KErrUsbDeviceNotConfigured;
       
  3205             else if (aDeviceState == UsbShai::EUsbPeripheralStateDefault)
       
  3206                 cancellationCode = KErrUsbDeviceBusReset;
       
  3207             else
       
  3208                 cancellationCode = KErrUsbDeviceNotConfigured;
       
  3209             }
       
  3210         }
       
  3211     iDeviceState = aDeviceState;
       
  3212     if (iValidInterface || iOwnsDeviceControl)
       
  3213         {
       
  3214 
       
  3215         // This LDD may not own an interface. It could be some manager reenumerating
       
  3216         // after its subordinate LDDs have setup their interfaces.
       
  3217         if (deconfigured)
       
  3218             {
       
  3219             DeConfigure(cancellationCode);
       
  3220             }
       
  3221         else if (renumerateState)
       
  3222             {
       
  3223              __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChannel:: Reumerated!"));
       
  3224             // Select main interface & latch in new endpoint set
       
  3225             SelectAlternateSetting(0);
       
  3226             __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChannel:: StartReads!"));
       
  3227             StartEpReads();
       
  3228             }
       
  3229         }
       
  3230 
       
  3231     const TInt reqNo = (TInt) RDevUsbcScClient::ERequestReEnumerate;
       
  3232     if (renumerateState && iRequestStatus[reqNo])
       
  3233         {
       
  3234         // This lot must be done if we are reenumerated
       
  3235         Kern::RequestComplete(iClient, iRequestStatus[reqNo], KErrNone);
       
  3236         }
       
  3237 
       
  3238     return KErrNone;
       
  3239     }
       
  3240 
       
  3241 
       
  3242 TBool DLddUsbcScChannel::AlternateDeviceStateTestComplete()
       
  3243     {
       
  3244     TBool completeNow = EFalse;
       
  3245     const TInt reqNo = (TInt) RDevUsbcScClient::ERequestAlternateDeviceStatusNotify;
       
  3246     if (iRequestStatus[reqNo])
       
  3247         {
       
  3248         // User req is outstanding
       
  3249         TUint32 deviceState;
       
  3250         if (iStatusFifo->GetDeviceQueuedStatus(deviceState) == KErrNone)
       
  3251             {
       
  3252             // Device state waiting to be sent userside
       
  3253             completeNow = ETrue;
       
  3254             __KTRACE_OPT(KUSB, Kern::Printf("StatusChangeCallback Notify status"));
       
  3255             // set client descriptor length to zero
       
  3256             TInt r = Kern::ThreadRawWrite(iClient, iStatusChangePtr, &deviceState,
       
  3257                                           sizeof(TUint32), iClient);
       
  3258             if (r != KErrNone)
       
  3259                 PanicClientThread(r);
       
  3260             iStatusChangePtr = NULL;
       
  3261             }
       
  3262         }
       
  3263     return completeNow;
       
  3264     }
       
  3265 
       
  3266 
       
  3267 void DLddUsbcScChannel::DeConfigure(TInt aErrorCode)
       
  3268     {
       
  3269     __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DeConfigure()"));
       
  3270     // Called after deconfiguration. Cancels transfers on all endpoints.
       
  3271     ResetInterface(aErrorCode);
       
  3272     // Cancel the endpoint status notify request if it is outstanding.
       
  3273     const TInt KEpNotReq = RDevUsbcScClient::ERequestEndpointStatusNotify;
       
  3274     if (iRequestStatus[KEpNotReq])
       
  3275         {
       
  3276         CancelNotifyEndpointStatus();
       
  3277         Kern::RequestComplete(iClient, iRequestStatus[KEpNotReq], aErrorCode);
       
  3278         }
       
  3279     // We have to reset the alternate setting number when the config goes away.
       
  3280      SelectAlternateSetting(0);
       
  3281     iAlternateSetting = 0;
       
  3282     }
       
  3283 
       
  3284 
       
  3285 void DLddUsbcScChannel::StartEpReads()
       
  3286     {
       
  3287     // Queued after enumeration. Starts reads on all endpoints.
       
  3288     // The endpoint itself decides if it can do a read
       
  3289     __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 1"));
       
  3290     
       
  3291     TInt i;
       
  3292     TInt8 needsPacket;
       
  3293 
       
  3294     for (i=0; i<iNumBuffers; i++)
       
  3295         {
       
  3296         __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 2 %d",i));
       
  3297 
       
  3298         needsPacket = iBuffers[i].iNeedsPacket;
       
  3299         if (needsPacket)
       
  3300             {
       
  3301             __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 3"));
       
  3302             iBuffers[i].UpdateBufferList(0,0,(needsPacket==TUsbcScBuffer::KEpIsStarting));
       
  3303             }
       
  3304         }
       
  3305 
       
  3306     __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 4"));
       
  3307 
       
  3308         // now update ep0
       
  3309         iBuffers[iEP0OutBuff].Ep0CancelLddRead();
       
  3310         iBuffers[iEP0OutBuff].UpdateBufferList(0,0);
       
  3311     __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 5"));
       
  3312 
       
  3313     }
       
  3314 
       
  3315 
       
  3316 void DLddUsbcScChannel::ResetInterface(TInt aErrorCode)
       
  3317     {
       
  3318     if (!iValidInterface && !iOwnsDeviceControl)
       
  3319             return;
       
  3320         
       
  3321     TInt i;
       
  3322     for (i=0; i<iNumBuffers; i++)
       
  3323         {
       
  3324         iBuffers[i].iNeedsPacket=TUsbcScBuffer::KNoEpAssigned;
       
  3325         }
       
  3326 
       
  3327     TUsbcScBuffer* buffer;
       
  3328 
       
  3329     for (i = 1; i <= iNumberOfEndpoints; i++)
       
  3330         {
       
  3331         // Firstly, cancel ('garbge collect') any stale reads/writes into PIL.
       
  3332 
       
  3333         __KTRACE_OPT(KUSB, Kern::Printf("Cancelling transfer ep=%d", i));
       
  3334         iEndpoint[i]->AbortTransfer();
       
  3335 
       
  3336         // All OUT endpoints need a packet sent, to indicate the termination of the current ep 'pipe'.
       
  3337         // This will complete any current read, or will be read later.
       
  3338         // All IN endpoints must be simply cancelled, including anything queued.
       
  3339         // Ep0 operates outside alt settings, and so we don't cancel anything.
       
  3340 
       
  3341         buffer=iEndpoint[i]->GetBuffer();
       
  3342         if (buffer->iDirection==KUsbcScIn)
       
  3343             {
       
  3344             buffer->iStatusList.Complete(KErrCancel);    //aErrorCode 
       
  3345             buffer->iStatusList.CancelQueued();            //aErrorCode
       
  3346             }
       
  3347         else
       
  3348             buffer->iNeedsPacket=TUsbcScBuffer::KEpIsEnding;    // We will send a packet on re-start, which doubles as a 'cancel'
       
  3349                                                                  // for the old alt setting.
       
  3350         }
       
  3351     }
       
  3352 
       
  3353 
       
  3354 
       
  3355 void DLddUsbcScChannel::EmergencyCompleteDfc(TAny* aDLddUsbcScChannel)
       
  3356     {
       
  3357     ((DLddUsbcScChannel*) aDLddUsbcScChannel)->DoEmergencyComplete();
       
  3358     }
       
  3359 
       
  3360 TInt DLddUsbcScChannel::DoEmergencyComplete()
       
  3361     {
       
  3362     __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DoEmergencyComplete"));
       
  3363     // cancel any pending DFCs
       
  3364     // complete all client requests
       
  3365 
       
  3366     TUsbcScBuffer* buffer;
       
  3367     TInt i;    
       
  3368     // Complete EP0 request
       
  3369 
       
  3370     TInt direction=iEp0Endpoint->iRequestCallbackInfo->iTransferDir;
       
  3371     if (direction==UsbShai::EControllerWrite)
       
  3372         {
       
  3373         iBuffers[iEP0InBuff].iStatusList.CancelQueued();
       
  3374         iBuffers[iEP0InBuff].iStatusList.Complete(KErrDisconnected);
       
  3375         }
       
  3376     else if (direction==UsbShai::EControllerRead)
       
  3377         {
       
  3378         iBuffers[iEP0OutBuff].iStatusList.CancelQueued();
       
  3379         iBuffers[iEP0OutBuff].iStatusList.Complete(KErrDisconnected);
       
  3380         }
       
  3381         
       
  3382     // Complete other Eps request
       
  3383     for (i = 1; i <= iNumberOfEndpoints; i++)
       
  3384         {
       
  3385         __KTRACE_OPT(KUSB, Kern::Printf("Cancelling transfer ep=%d", i));
       
  3386         buffer=iEndpoint[i]->GetBuffer();
       
  3387         buffer->iStatusList.CancelQueued();
       
  3388         buffer->iStatusList.Complete(KErrDisconnected);
       
  3389         }
       
  3390 
       
  3391     // Complete remaining requests
       
  3392 
       
  3393     for (TInt i = 0; i < KUsbcMaxRequests; i++)
       
  3394         {
       
  3395         if (iRequestStatus[i])
       
  3396             {
       
  3397             __KTRACE_OPT(KUSB, Kern::Printf("Complete request 0x%x", iRequestStatus[i]));
       
  3398             Kern::RequestComplete(iClient, iRequestStatus[i], KErrDisconnected);
       
  3399             }
       
  3400         }
       
  3401     iStatusCallbackInfo.Cancel();
       
  3402     iEndpointStatusCallbackInfo.Cancel();
       
  3403     iOtgFeatureCallbackInfo.Cancel();
       
  3404 
       
  3405     return KErrNone;
       
  3406     }
       
  3407 
       
  3408 
       
  3409 void DLddUsbcScChannel::PanicClientThread(TInt aReason)
       
  3410     {
       
  3411     Kern::ThreadKill(iClient, EExitPanic, aReason, KUsbLDDKillCat);
       
  3412     }
       
  3413 
       
  3414 // End DLddUsbcScChannel
       
  3415 
       
  3416 /*****************************************************************************\
       
  3417 *    TUsbcScEndpoint                                                          *
       
  3418 *                                                                             *
       
  3419 *                                                                             *
       
  3420 *                                                                             *
       
  3421 \*****************************************************************************/
       
  3422 
       
  3423 
       
  3424 // Constructor
       
  3425 TUsbcScEndpoint::TUsbcScEndpoint(DLddUsbcScChannel* aLDD, DUsbClientController* aController,
       
  3426                              const TUsbcScEndpointInfo* aEndpointInfo, TInt aEndpointNum
       
  3427                              )
       
  3428     : iRequestCallbackInfo(NULL),
       
  3429       iController(aController),
       
  3430       iEndpointInfo(*aEndpointInfo),
       
  3431       iClientReadPending(EFalse),
       
  3432       iClientWritePending(EFalse),
       
  3433       iEndpointNumber(aEndpointNum),
       
  3434       iRealEpNumber(-1),
       
  3435       iLdd(aLDD),
       
  3436       iError(KErrNone),
       
  3437       iBytesTransferred(0),
       
  3438       iBuffer(NULL)
       
  3439     {
       
  3440     __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::TUsbcScEndpoint"));
       
  3441     }
       
  3442 
       
  3443 
       
  3444 TInt TUsbcScEndpoint::Construct()
       
  3445     {
       
  3446     __KTRACE_OPT(KUSB,Kern::Printf("TUsbcScEndpoint::TUsbcScEndpoint iEndpointNumber %d\n",iEndpointNumber));
       
  3447 
       
  3448     iRequestCallbackInfo = new TUsbcRequestCallback(iLdd,
       
  3449                                                     iEndpointNumber,
       
  3450                                                     (iEndpointNumber==0)?DLddUsbcScChannel::RequestCallbackEp0:TUsbcScEndpoint::RequestCallback,
       
  3451                                                     (iEndpointNumber==0)?  (TAny*) iLdd:  (TAny*) this,
       
  3452                                                     iLdd->iDfcQ,
       
  3453                                                     KUsbRequestCallbackPriority);
       
  3454 
       
  3455     return (iRequestCallbackInfo == NULL)?KErrNoMemory:KErrNone;
       
  3456     }
       
  3457 
       
  3458 
       
  3459 TUsbcScEndpoint::~TUsbcScEndpoint()
       
  3460     {
       
  3461     __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::~TUsbcScEndpoint(%d)", iEndpointNumber));
       
  3462     AbortTransfer();
       
  3463     delete iRequestCallbackInfo;
       
  3464     }
       
  3465 
       
  3466 // This is called by the PIL, on return from a read or write.
       
  3467 // Inturn it calls either the read or write function for that buffer.
       
  3468 
       
  3469 void TUsbcScEndpoint::RequestCallback(TAny* aTUsbcScEndpoint)
       
  3470     {
       
  3471     __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::RequestCallback"));
       
  3472 
       
  3473     if (((TUsbcScEndpoint*)aTUsbcScEndpoint)->iLdd->ChannelClosing())
       
  3474         {
       
  3475         __KTRACE_OPT(KUSB, Kern::Printf("Channel Closing: Completion not accepted!"));
       
  3476         return;
       
  3477         }
       
  3478 
       
  3479     switch (((TUsbcScEndpoint*) aTUsbcScEndpoint)->iRequestCallbackInfo->iTransferDir)
       
  3480     {
       
  3481     case UsbShai::EControllerWrite:
       
  3482         ((TUsbcScEndpoint*) aTUsbcScEndpoint)->iBuffer->CompleteWrite();
       
  3483         return;
       
  3484     case UsbShai::EControllerRead:
       
  3485         ((TUsbcScEndpoint*) aTUsbcScEndpoint)->iBuffer->CompleteRead();
       
  3486         return;
       
  3487     default:
       
  3488         Kern::Printf("TUsbcScEndpoint::RequestCallback - Unexpected compleation direction %d",((TUsbcScEndpoint*) aTUsbcScEndpoint)->iRequestCallbackInfo->iTransferDir);
       
  3489         Kern::Fault("TUsbcScEndpoint::RequestCallback", __LINE__);
       
  3490     } 
       
  3491     }
       
  3492 
       
  3493 
       
  3494 /*
       
  3495 
       
  3496 This is used to tidy up cancel calls into the PIL, regardless of them being reads or writes
       
  3497 
       
  3498 */
       
  3499 
       
  3500 void TUsbcScEndpoint::AbortTransfer()
       
  3501     {
       
  3502     if (!iLdd->iRealizeCalled)
       
  3503         {
       
  3504         __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::AbortTransfer Ep# %d Real Ep # %d - N.R.",iEndpointNumber, iRealEpNumber));
       
  3505         return;
       
  3506         } 
       
  3507     else
       
  3508         {
       
  3509         __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::AbortTransfer Ep# %d Real Ep # %d",iEndpointNumber, iRealEpNumber));
       
  3510         }
       
  3511 
       
  3512     
       
  3513     if (iBuffer && (iBuffer->iStatusList.iState) || (!iRealEpNumber))
       
  3514         {
       
  3515         if (iRequestCallbackInfo->iTransferDir==UsbShai::EControllerWrite)
       
  3516             iController->CancelWriteBuffer(iLdd, iRealEpNumber);
       
  3517         else if (iRequestCallbackInfo->iTransferDir==UsbShai::EControllerRead)
       
  3518             iController->CancelReadBuffer(iLdd, iRealEpNumber);
       
  3519         else
       
  3520             {
       
  3521             if (iEndpointNumber!=0) // endpoint zero starts off not sent in any direction, then keeps changing.
       
  3522                 {
       
  3523                 __KTRACE_OPT(KUSB,Kern::Printf("\nTUsbcScEndpoint::AbortTransfer WARNING: Invalid Direction %d on (%d,%d)!\n",iRequestCallbackInfo->iTransferDir,iEndpointNumber, iRealEpNumber));
       
  3524                 }
       
  3525             else
       
  3526                 {
       
  3527                 __KTRACE_OPT(KUSB, Kern::Printf("\nTUsbcScEndpoint::AbortTransfer Can't stop direction %d on (%d,%d)!\n",iRequestCallbackInfo->iTransferDir,iEndpointNumber, iRealEpNumber));
       
  3528                 }
       
  3529             }
       
  3530         }
       
  3531     else if (!iBuffer)
       
  3532         {
       
  3533         __KTRACE_OPT(KUSB,Kern::Printf("\nTUsbcScEndpoint::AbortTransfer WARNING: iBuffer is NULL on (%d,%d)\n",iEndpointNumber, iRealEpNumber));
       
  3534         return;
       
  3535         }
       
  3536     
       
  3537     if (iRequestCallbackInfo)
       
  3538         iRequestCallbackInfo->iDfc.Cancel();
       
  3539     else
       
  3540         {
       
  3541         __KTRACE_OPT(KUSB,Kern::Printf("\nTUsbcScEndpoint::AbortTransfer WARNING: iRequestCallbackInfo is NULL\n"));
       
  3542         }
       
  3543         
       
  3544     __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint Done."));
       
  3545     }
       
  3546 
       
  3547 // End TUsbcScEndpoint
       
  3548 
       
  3549 
       
  3550 /*****************************************************************************\
       
  3551 *    TUsbcScAlternateSettingList                                              *
       
  3552 *                                                                             *
       
  3553 *                                                                             *
       
  3554 *                                                                             *
       
  3555 \*****************************************************************************/
       
  3556 
       
  3557 
       
  3558 TUsbcScAlternateSetting::TUsbcScAlternateSetting()
       
  3559     : iNext(NULL),
       
  3560       iPrevious(NULL),
       
  3561       iNumberOfEndpoints(0),
       
  3562       iSetting(0)
       
  3563     {
       
  3564     for (TInt i = 0; i <= KMaxEndpointsPerClient; i++)
       
  3565         {
       
  3566         iEndpoint[i] = NULL;
       
  3567         }
       
  3568     }
       
  3569 
       
  3570 
       
  3571 TUsbcScAlternateSetting::~TUsbcScAlternateSetting()
       
  3572     {
       
  3573     __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScAlternateSetting::~TUsbcScAlternateSetting()"));
       
  3574     for (TInt i = 0; i <= KMaxEndpointsPerClient; i++)
       
  3575         {
       
  3576         delete iEndpoint[i];
       
  3577         }
       
  3578     }
       
  3579 
       
  3580 // End TUsbcScAlternateSettingList
       
  3581 
       
  3582 
       
  3583 
       
  3584 TUsbcScAlternateSettingList::TUsbcScAlternateSettingList()
       
  3585     : iHead(NULL),
       
  3586       iTail(NULL)
       
  3587     {
       
  3588     }
       
  3589 
       
  3590 TUsbcScAlternateSettingList::~TUsbcScAlternateSettingList()
       
  3591     {
       
  3592     }
       
  3593 
       
  3594 
       
  3595 
       
  3596 /*****************************************************************************\
       
  3597 *   TUsbcDeviceStatusQueue                                                    *
       
  3598 *                                                                             *
       
  3599 *                                                                             *
       
  3600 *                                                                             *
       
  3601 \*****************************************************************************/
       
  3602 
       
  3603 
       
  3604 TUsbcDeviceStatusQueue::TUsbcDeviceStatusQueue()
       
  3605     {
       
  3606     FlushQueue();
       
  3607     }
       
  3608 
       
  3609 
       
  3610 void TUsbcDeviceStatusQueue::FlushQueue()
       
  3611     {
       
  3612     for (TInt i = 0; i < KUsbDeviceStatusQueueDepth; i++)
       
  3613         {
       
  3614         iDeviceStatusQueue[i] = KUsbDeviceStatusNull;
       
  3615         }
       
  3616     iStatusQueueHead = 0;
       
  3617     }
       
  3618 
       
  3619 
       
  3620 void TUsbcDeviceStatusQueue::AddStatusToQueue(TUint32 aDeviceStatus)
       
  3621     {
       
  3622     // Only add a new status if it is not a duplicate of the one at the head of the queue
       
  3623     if (!(iStatusQueueHead != 0 &&
       
  3624           iDeviceStatusQueue[iStatusQueueHead - 1] == aDeviceStatus))
       
  3625         {
       
  3626         if (iStatusQueueHead == KUsbDeviceStatusQueueDepth)
       
  3627             {
       
  3628             // Discard item at tail of queue
       
  3629             TUint32 status;
       
  3630             GetDeviceQueuedStatus(status);
       
  3631             }
       
  3632         iDeviceStatusQueue[iStatusQueueHead] = aDeviceStatus;
       
  3633         iStatusQueueHead++;
       
  3634         }
       
  3635     }
       
  3636 
       
  3637 
       
  3638 TInt TUsbcDeviceStatusQueue::GetDeviceQueuedStatus(TUint32& aDeviceStatus)
       
  3639     {
       
  3640     TInt r = KErrNone;
       
  3641     if (iStatusQueueHead <= 0)
       
  3642         {
       
  3643         r = KErrGeneral;
       
  3644         aDeviceStatus = KUsbDeviceStatusNull;
       
  3645         }
       
  3646     else
       
  3647         {
       
  3648         aDeviceStatus = iDeviceStatusQueue[0];
       
  3649         for(TInt i = 1; i < KUsbDeviceStatusQueueDepth; i++)
       
  3650             {
       
  3651             TUint32 s = iDeviceStatusQueue[i];
       
  3652             iDeviceStatusQueue[i - 1] = s;
       
  3653             }
       
  3654         iStatusQueueHead--;
       
  3655         iDeviceStatusQueue[KUsbDeviceStatusQueueDepth - 1] = KUsbDeviceStatusNull;
       
  3656         }
       
  3657     return r;
       
  3658     }
       
  3659 
       
  3660 // End TUsbcDeviceStatusQueue
       
  3661 
       
  3662 //---
       
  3663