usbdrv/peripheral/pdd/pil/src/ps_usbc.cpp
branchRCL_3
changeset 16 012cc2ee6408
parent 15 f92a4f87e424
equal deleted inserted replaced
15:f92a4f87e424 16:012cc2ee6408
     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/usbcc/ps_usbc.cpp
       
    15 // Platform independent layer (PIL) of the USB Device controller driver (PDD).
       
    16 // Interface to the USB LDD.
       
    17 // 
       
    18 //
       
    19 
       
    20 /**
       
    21  @file ps_usbc.cpp
       
    22  @internalTechnology
       
    23 */
       
    24 //#include <drivers/usbc.h>
       
    25 #include <usb/usbc.h>
       
    26 
       
    27 #include "controltransfersm.h"
       
    28 /**
       
    29     TUsbcInterfaceSet and TUsbcInterface
       
    30     ====================================
       
    31 
       
    32     TUsbcInterfaceSet represents a 'USB Interface' and TUsbcInterface
       
    33     represents an 'Alternate Setting of a USB Interface'.
       
    34 
       
    35     Since every LDD governs exactly one interface, the above distinction is
       
    36     made only within the USB implementation. At the LDD API, there is/are
       
    37     simply one or more settings for this single interface, numbered from '0'
       
    38     (the default) to 'n', and specified by the parameter 'TInt aInterfaceNum'.
       
    39 
       
    40     Within the PDD implementation, for a TUsbcInterfaceSet number the parameter
       
    41     'TInt aIfcSet' is used (local variable ifcset); for a TUsbcInterface number
       
    42     the parameter 'TInt aIfc' is used (local variable ifc).
       
    43 
       
    44 
       
    45     iConfigs[0] and CurrentConfig()
       
    46     ===============================
       
    47 
       
    48     One problem with this file is that it always uses iConfigs[0] and not
       
    49     CurrentConfig(). This is mainly because the API to the LDD doesn't know
       
    50     about the concept of multiple configurations, and thus always assumes one
       
    51     single configuration (which is also always active: a further problem).
       
    52 
       
    53     In the file chapter9.cpp this issue doesn't exist, since there we always
       
    54     have to obey the USB protocol, and in this way will use the configuration
       
    55     which is selected by the host (which will then again currently always be
       
    56     iConfigs[0].)
       
    57 
       
    58     iEp0ClientId
       
    59     ==================================
       
    60 
       
    61     The purpose of these two members of class DUsbClientController is the
       
    62     following.
       
    63 
       
    64     They are used only during Ep0 control transactions which have an OUT (Rx)
       
    65     data stage. We cannot deduce from the received data itself to whom
       
    66     it is addressed (that's because of the shared nature of Ep0).
       
    67 
       
    68     In order to be able to tell whether received Ep0 data is to be processed by
       
    69     the PIL or a LDD, we use iEp0ClientId. iEp0ClientId is usually NULL, which
       
    70     means it is our data. However it is set to the client ID of an LDD in case
       
    71     2) above. That way we can subsequently hand over received data to the
       
    72     correct client LDD.
       
    73 
       
    74     iEp0DataReceived tracks the amount of data already received - it is used to
       
    75     determine the end of the DATA_OUT phase, irrespective of the owner of the
       
    76     data. The total amount that is to be received can be obtained via
       
    77     iConTransferMgr->PktParser().Length(). (iConTransferMgr->PktParser() holds in 
       
    78     that case the Setup packet of the current Control transfer.)
       
    79 
       
    80     iEp0ClientDataTransmitting is only set to TRUE if a client sets up an Ep0
       
    81     write. After that transmission has completed we use this value to decide
       
    82     whether we have to report the completion to a client or not. (If this
       
    83     variable is FALSE, we did set up the write and thus no client notification
       
    84     is necessary.)
       
    85 
       
    86 */
       
    87 
       
    88 //
       
    89 // === Global and Local Variables ==================================================================
       
    90 //
       
    91 
       
    92 // Currently we support at most 2 peripheral stack
       
    93 GLDEF_D DUsbClientController* DUsbClientController::UsbClientController[] = {NULL, NULL};
       
    94 
       
    95 static const TInt KUsbReconnectDelay   = 500;                // milliseconds
       
    96 
       
    97 // Charger detector is the guy(PSL) who can detect the charger type and report 
       
    98 // it via a charger type observer
       
    99 static UsbShai::MChargerDetectorIf* gChargerDetector = NULL;
       
   100 
       
   101 // Charger observer is the guy who want to monitor the chager type event.
       
   102 static UsbShai::MChargerDetectorObserverIf* gChargerObsever = NULL;
       
   103 
       
   104 
       
   105 // Those const variables are used to construct the default 
       
   106 // Usb descriptors, Upper layer can change them later.
       
   107 /** Default vendor ID to set in device descriptor */
       
   108 static const TUint16 KUsbVendorId   = KUsbVendorId_Symbian;
       
   109 /** Default product ID to set in device descriptor */
       
   110 static const TUint16 KUsbProductId  = 0x1111;
       
   111 /** Default language ID (US English) to set in device descriptor */
       
   112 static const TUint16 KUsbLangId     = 0x0409;
       
   113 static const TUint8 KUsbNumberOfConfiguration = 0x01;
       
   114 /** Default manufacturer string */
       
   115 static const wchar_t KStringManufacturer[] = L"Nokia Corporation";
       
   116 /** Default product name string */
       
   117 static const wchar_t KStringProduct[]      = L"Nokia USB Driver";
       
   118 /** Default configuration name string */
       
   119 static const wchar_t KStringConfig[]       = L"Bulk transfer method configuration";
       
   120 /** Default configuration name string */
       
   121 static const wchar_t KStringSerial[]       = L"Serial Not defined";
       
   122 
       
   123 
       
   124 //
       
   125 // === USB Controller member function implementations - LDD API (public) ===========================
       
   126 //
       
   127 
       
   128 DECLARE_STANDARD_EXTENSION()//lint !e1717 !e960 defined by symbian
       
   129     {
       
   130     __KTRACE_OPT(KUSB, Kern::Printf("> Peripheral PIL Extension entry"));
       
   131     // Don't need to do anything here, using extension just to make sure
       
   132     // we're loaded when peripheral PSL trying to register itself to us.
       
   133     __KTRACE_OPT(KUSB, Kern::Printf("< Peripheral PIL Extension exit"));
       
   134     return KErrNone;
       
   135     }
       
   136     
       
   137 /** The class destructor.
       
   138 
       
   139     This rarely gets called, except, for example when something goes
       
   140     wrong during construction.
       
   141 
       
   142     It's not exported because it is virtual.
       
   143 */
       
   144 DUsbClientController::~DUsbClientController()
       
   145     {
       
   146     __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::~DUsbClientController()"));
       
   147     if (iPowerHandler)
       
   148         {
       
   149         iPowerHandler->Remove();
       
   150         delete iPowerHandler;
       
   151         }
       
   152 
       
   153     // ResetAndDestroy() will call for every array element the destructor of the pointed-to object,
       
   154     // before deleting the element itself, and closing the array.
       
   155     iConfigs.ResetAndDestroy();
       
   156     __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::~DUsbClientController(): Done."));
       
   157     }
       
   158 
       
   159 EXPORT_C DUsbClientController* DUsbClientController::Create(UsbShai::MPeripheralControllerIf&               aPeripheralControllerIf, 
       
   160                                                             const UsbShai::TPeripheralControllerProperties& aProperties,
       
   161                                                             TBool                                  aIsOtgPort)
       
   162     {
       
   163     __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::Create"));
       
   164         // Attempt to create the object
       
   165     DUsbClientController* usbcc = new DUsbClientController(aPeripheralControllerIf, 
       
   166                                                            aProperties,
       
   167                                                            aIsOtgPort);
       
   168     
       
   169     __ASSERT_DEBUG( (usbcc != NULL), Kern::Fault( "  USB PSL Out of memory, DUsbClientController", __LINE__ ) );
       
   170     
       
   171     if (usbcc != NULL)
       
   172         {
       
   173         // Second phase constructor
       
   174         TInt err = usbcc->Construct();
       
   175         __ASSERT_DEBUG( (err == KErrNone), Kern::Fault( "DUsbClientController::Construct failed", err) );
       
   176         
       
   177         if (err != KErrNone)
       
   178             {
       
   179             delete usbcc;
       
   180             usbcc = NULL;
       
   181             }
       
   182         }
       
   183     
       
   184     __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::Create instance = %d",usbcc));
       
   185     
       
   186     return usbcc;
       
   187     }
       
   188 
       
   189 /**
       
   190  * FIXME: This function used to be called by the dummy DCD to disable
       
   191  * the peripheral stack. It has been deprecated and we currently use
       
   192  * DisablePeripheralStack() to achieve the same effect.
       
   193  */
       
   194 EXPORT_C void DUsbClientController::DisableClientStack()
       
   195     {
       
   196     __KTRACE_OPT(KUSB, Kern::Printf("CALL TO OBSOLETE FUNCTION: DUsbClientController::DisableClientStack()"));
       
   197     }
       
   198 
       
   199 
       
   200 /**
       
   201  * FIXME: This function used to be called by the dummy DCD to enable
       
   202  * the peripheral stack. It has been deprecated and we currently use
       
   203  * EnablePeripheralStack() to achieve the same effect.
       
   204  */
       
   205 EXPORT_C void DUsbClientController::EnableClientStack()
       
   206     {
       
   207     __KTRACE_OPT(KUSB, Kern::Printf("CALL TO OBSOLETE FUNCTION: DUsbClientController::EnableClientStack()"));
       
   208     }
       
   209 
       
   210 
       
   211 /** Called by LDD to see if controller is usable.
       
   212 
       
   213     @return ETrue if controller is in normal state, EFalse if it is disabled.
       
   214 */
       
   215 EXPORT_C TBool DUsbClientController::IsActive()
       
   216     {
       
   217     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::IsActive = %d",iStackIsActive));
       
   218     return iStackIsActive;
       
   219     }
       
   220 
       
   221 
       
   222 /** Called by LDD to register client callbacks.
       
   223 
       
   224     @return KErrNone if successful, KErrAlreadyExists callback exists.
       
   225 */
       
   226 EXPORT_C TInt DUsbClientController::RegisterClientCallback(TUsbcClientCallback& aCallback)
       
   227     {
       
   228     __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::RegisterClientCallback()"));
       
   229     if (iClientCallbacks.Elements() == KUsbcMaxListLength)
       
   230         {
       
   231         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Maximum list length reached: %d",
       
   232                                           KUsbcMaxListLength));
       
   233         return KErrGeneral;
       
   234         }
       
   235     TSglQueIter<TUsbcClientCallback> iter(iClientCallbacks);
       
   236     TUsbcClientCallback* p;
       
   237     while ((p = iter++) != NULL)
       
   238         if (p == &aCallback)
       
   239             {
       
   240             __KTRACE_OPT(KUSB, Kern::Printf("     Error: ClientCallback @ 0x%x already registered", &aCallback));
       
   241             return KErrAlreadyExists;
       
   242             }
       
   243     iClientCallbacks.AddLast(aCallback);
       
   244     __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::RegisterClientCallback()"));
       
   245     return KErrNone;
       
   246     }
       
   247 
       
   248 
       
   249 /** Returns a pointer to the USB client controller object.
       
   250 
       
   251     This function is static.
       
   252 
       
   253     @param aUdc The number of the UDC (0..n) for which the pointer is to be returned.
       
   254 
       
   255     @return A pointer to the USB client controller object.
       
   256 */
       
   257 EXPORT_C DUsbClientController* DUsbClientController::UsbcControllerPointer(TInt aUdc)
       
   258     {
       
   259     __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::UsbcControllerPointer()"));
       
   260     
       
   261     if (aUdc < 0 || aUdc > 1)
       
   262         {
       
   263         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: aUdc out of range (%d)", aUdc));
       
   264         return NULL;
       
   265         }
       
   266         
       
   267     __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::UsbcControllerPointer()"));
       
   268     
       
   269     return UsbClientController[aUdc];
       
   270     }
       
   271 
       
   272 
       
   273 /** Fills the buffer passed in as an argument with endpoint capability information.
       
   274 
       
   275      @see DUsbClientController::DeviceCaps()
       
   276     @see TUsbcEndpointData
       
   277     @see TUsbDeviceCaps
       
   278 
       
   279     @param aClientId A pointer to the LDD making the enquiry.
       
   280     @param aCapsBuf A reference to a descriptor buffer, which, on return, contains an array of
       
   281     TUsbcEndpointData elements; there are TUsbDeviceCaps::iTotalEndpoints elements in the array;
       
   282     call DeviceCaps() to get the number of elements required.
       
   283 */
       
   284 EXPORT_C void DUsbClientController::EndpointCaps(const DBase* aClientId, TDes8& aCapsBuf) const
       
   285     {
       
   286     __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::EndpointCaps()"));
       
   287     // Here we do not simply call DUsbClientController::DeviceEndpointCaps(),
       
   288     // because that function fills an array which comprises of _all_ endpoints,
       
   289     // whereas this function omits ep0 and all unusable endpoints.
       
   290     // Apart from that, we have to fill an array of TUsbcEndpointData, not TUsbcEndpointCaps.
       
   291     TUsbcEndpointData data[KUsbcMaxEndpoints];
       
   292     const TInt ifcset_num = ClientId2InterfaceNumber(aClientId);
       
   293     for (TInt i = 2, j = 0; i < iDeviceTotalEndpoints; ++i)
       
   294         {
       
   295         __KTRACE_OPT(KUSB, Kern::Printf("  DUsbClientController::Caps: RealEndpoint #%d", i));
       
   296         if (iRealEndpoints[i].iCaps.iTypesAndDir != UsbShai::KUsbEpNotAvailable)
       
   297             {
       
   298             __KTRACE_OPT(KUSB, Kern::Printf("  DUsbClientController::Caps: --> UsableEndpoint #%d", j));
       
   299 
       
   300             data[j].iCaps.iSizes = iRealEndpoints[i].iCaps.iSizes;
       
   301             data[j].iCaps.iTypesAndDir = iRealEndpoints[i].iCaps.iTypesAndDir;
       
   302             data[j].iCaps.iHighBandwidth = iRealEndpoints[i].iCaps.iHighBandwidth;
       
   303             data[j].iCaps.iReserved[0] = iRealEndpoints[i].iCaps.iReserved[0];
       
   304             data[j].iCaps.iReserved[1] = iRealEndpoints[i].iCaps.iReserved[1];
       
   305             
       
   306             if (ifcset_num < 0)
       
   307                 {
       
   308                 // If this LDD doesn't own an interface, but the Ep points to one,
       
   309                 // then that must be the interface of a different LDD. Hence the Ep
       
   310                 // is not available for this LDD.
       
   311                 data[j].iInUse = (iRealEndpoints[i].iIfcNumber != NULL);
       
   312                 }
       
   313             else
       
   314                 {
       
   315                 // If this LDD does already own an interface, and the Ep also points to one,
       
   316                 // then the Ep is not available for this LDD only if that interface is owned
       
   317                 // by a different LDD (i.e. if the interface number is different).
       
   318                 // Reason: Even though the endpoint might already be part of an interface setting,
       
   319                 // it is still available for a different alternate setting of the same interface.
       
   320                 data[j].iInUse = ((iRealEndpoints[i].iIfcNumber != NULL) &&
       
   321                                   (*(iRealEndpoints[i].iIfcNumber) != ifcset_num));
       
   322                 }
       
   323 
       
   324             j++;
       
   325             }
       
   326         }
       
   327     // aCapsBuf resides in userland
       
   328     TPtrC8 des((TUint8*)data, sizeof(data));
       
   329     const TInt r = Kern::ThreadDesWrite((reinterpret_cast<const DLddUsbcChannel*>(aClientId))->Client(),
       
   330                                         &aCapsBuf, des, 0, KChunkShiftBy0, NULL);
       
   331     if (r != KErrNone)
       
   332         {
       
   333         Kern::ThreadKill((reinterpret_cast<const DLddUsbcChannel*>(aClientId))->Client(),
       
   334                          EExitPanic, r, KUsbPILKillCat);
       
   335         }
       
   336         
       
   337     __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::EndpointCaps()"));
       
   338     }
       
   339 
       
   340 
       
   341 /** Fills the buffer passed in as an argument with device capability information.
       
   342 
       
   343     @see TUsbDeviceCaps
       
   344     @see TUsbDeviceCapsV01
       
   345 
       
   346     @param aClientId A pointer to the LDD making the enquiry.
       
   347     @param aCapsBuf A reference to a descriptor buffer which, on return, contains
       
   348     a TUsbDeviceCaps structure.
       
   349 */
       
   350 EXPORT_C void DUsbClientController::DeviceCaps(const DBase* aClientId, TDes8& aCapsBuf) const
       
   351     {
       
   352     __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::DeviceCaps()"));
       
   353     TUsbDeviceCaps caps;
       
   354     caps().iTotalEndpoints = iDeviceUsableEndpoints;        // not DeviceTotalEndpoints()!
       
   355     
       
   356     caps().iSelfPowered = iSelfPowered;
       
   357     caps().iRemoteWakeup = iRemoteWakeup;
       
   358     caps().iHighSpeed = (iControllerProperties.iControllerCaps & UsbShai::KDevCapHighSpeed)?ETrue:EFalse;
       
   359     
       
   360     // PIL always assume controller support this caps, see explaination in peripheral shai header
       
   361     caps().iFeatureWord1 = caps().iFeatureWord1 | KUsbDevCapsFeatureWord1_CableDetectWithoutPower;
       
   362     
       
   363     caps().iFeatureWord1 = caps().iFeatureWord1 | KUsbDevCapsFeatureWord1_EndpointResourceAllocV2;
       
   364     caps().iReserved = 0;
       
   365 
       
   366     // aCapsBuf resides in userland
       
   367     const TInt r = Kern::ThreadDesWrite((reinterpret_cast<const DLddUsbcChannel*>(aClientId))->Client(),
       
   368                                         &aCapsBuf, caps, 0, KChunkShiftBy0, NULL);
       
   369     if (r != KErrNone)
       
   370         {
       
   371         Kern::ThreadKill((reinterpret_cast<const DLddUsbcChannel*>(aClientId))->Client(),
       
   372                          EExitPanic, r, KUsbPILKillCat);
       
   373         }
       
   374     __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::DeviceCaps()"));
       
   375     }
       
   376 
       
   377 
       
   378 TUsbcEndpointInfoArray::TUsbcEndpointInfoArray(const TUsbcEndpointInfo* aData, TInt aDataSize)
       
   379     {
       
   380     iType = EUsbcEndpointInfo;
       
   381     iData = (TUint8*) aData;
       
   382     if (aDataSize > 0)
       
   383         iDataSize = aDataSize;
       
   384     else
       
   385         iDataSize = sizeof(TUsbcEndpointInfo);
       
   386     }
       
   387 
       
   388 
       
   389 inline TUsbcEndpointInfo& TUsbcEndpointInfoArray::operator[](TInt aIndex) const
       
   390     {
       
   391     return *(TUsbcEndpointInfo*) &iData[aIndex * iDataSize];
       
   392     }
       
   393 
       
   394 
       
   395 EXPORT_C TInt DUsbClientController::SetInterface(const DBase* aClientId, DThread* aThread,
       
   396                                                  TInt aInterfaceNum, TUsbcClassInfo& aClass,
       
   397                                                  TDesC8* aString, TInt aTotalEndpointsUsed,
       
   398                                                  const TUsbcEndpointInfo aEndpointData[],
       
   399                                                  TInt (*aRealEpNumbers)[6], TUint32 aFeatureWord)
       
   400     {
       
   401     TUsbcEndpointInfoArray endpointData = TUsbcEndpointInfoArray(aEndpointData);
       
   402     return SetInterface(aClientId, aThread, aInterfaceNum, aClass, aString, aTotalEndpointsUsed,
       
   403                         endpointData, (TInt*) aRealEpNumbers, aFeatureWord);
       
   404     }
       
   405 
       
   406 
       
   407 /** Creates a new USB interface (one setting), complete with endpoints, descriptors, etc.,
       
   408     and chains it into the internal device configuration tree.
       
   409 
       
   410     @param aClientId A pointer to the LDD owning the new interface.
       
   411     @param aThread A pointer to the thread the owning LDD is running in.
       
   412     @param aInterfaceNum The interface setting number of the new interface setting. This must be 0
       
   413     if it is the first setting of the interface that gets created, or 1 more than the last setting
       
   414     that was created for this interface.
       
   415     @param aClass Contains information about the device class this interface might belong to.
       
   416     @param aString A pointer to a string that is used for the string descriptor of this interface.
       
   417     @param aTotalEndpointsUsed The number of endpoints used by this interface (and also the number of
       
   418     elements of the following array).
       
   419     @param aEndpointData An array with aTotalEndpointsUsed elements, containing information about the
       
   420     endpoints of this interface.
       
   421 
       
   422     @return KErrNotSupported if Control endpoints are requested by the LDD but aren't supported by the PIL,
       
   423     KErrInUse if at least one requested endpoint is - temporarily or permanently - not available for use,
       
   424     KErrNoMemory if (endpoint, interface, string) descriptor allocation fails, KErrGeneral if something else
       
   425     goes wrong during endpoint or interface or descriptor creation, KErrNone if interface successfully set up.
       
   426 */
       
   427 EXPORT_C TInt DUsbClientController::SetInterface(const DBase* aClientId, DThread* aThread,
       
   428                                                  TInt aInterfaceNum, TUsbcClassInfo& aClass,
       
   429                                                  TDesC8* aString, TInt aTotalEndpointsUsed,
       
   430                                                  const TUsbcEndpointInfoArray aEndpointData,
       
   431                                                  TInt aRealEpNumbers[], TUint32 aFeatureWord)
       
   432     {
       
   433     __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::SetInterface()"));
       
   434     if (aInterfaceNum != 0)
       
   435         {
       
   436         __KTRACE_OPT(KUSB, Kern::Printf("  alternate interface setting request: #%d", aInterfaceNum));
       
   437         }
       
   438 
       
   439 #ifndef USB_SUPPORTS_CONTROLENDPOINTS
       
   440     for (TInt i = 0; i < aTotalEndpointsUsed; ++i)
       
   441         {
       
   442         if (aEndpointData[i].iType == UsbShai::KUsbEpTypeControl)
       
   443             {
       
   444             __KTRACE_OPT(KPANIC, Kern::Printf("  Error: control endpoints not supported"));
       
   445             return KErrNotSupported;
       
   446             }
       
   447         }
       
   448 #endif
       
   449 
       
   450     // Check for endpoint availability & check those endpoint's capabilities
       
   451     const TInt ifcset_num = ClientId2InterfaceNumber(aClientId);
       
   452     
       
   453     // The passed-in ifcset_num may be -1 now, but that's intended.
       
   454     if (!CheckEpAvailability(aTotalEndpointsUsed, aEndpointData, ifcset_num))
       
   455         {
       
   456         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: endpoints not (all) available"));
       
   457         return KErrInUse;
       
   458         }
       
   459     
       
   460     // Create & setup new interface
       
   461     TUsbcInterface* ifc = CreateInterface(aClientId, aInterfaceNum, aFeatureWord);
       
   462     if (ifc == NULL)
       
   463         {
       
   464         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: ifc == NULL"));
       
   465         return KErrGeneral;
       
   466         }
       
   467     
       
   468     // Create logical endpoints
       
   469     TInt r = CreateEndpoints(ifc, aTotalEndpointsUsed, aEndpointData, aRealEpNumbers);
       
   470     if (r != KErrNone)
       
   471         {
       
   472         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: CreateEndpoints() err = %d ",r));
       
   473         DeleteInterface(ifc->iInterfaceSet->iInterfaceNumber, aInterfaceNum);
       
   474         return r;
       
   475         }
       
   476     
       
   477     // Create & setup interface, string, and endpoint descriptors
       
   478     r = SetupIfcDescriptor(ifc, aClass, aThread, aString, aEndpointData);
       
   479     if (r != KErrNone)
       
   480         {
       
   481         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: SetupIfcDescriptor() err = %d",r));
       
   482         return r;
       
   483         }
       
   484     
       
   485     __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::SetInterface()"));
       
   486     return KErrNone;
       
   487     }
       
   488 
       
   489 
       
   490 /** Releases an existing USB interface (one setting), complete with endpoints, descriptors, etc.,
       
   491     and removes it from the internal device configuration tree.
       
   492 
       
   493     @param aClientId A pointer to the LDD owning the interface.
       
   494     @param aInterfaceNum The setting number of the interface setting to be deleted. This must be
       
   495     the highest numbered (or 'last') setting for this interface.
       
   496 
       
   497     @return KErrNotFound if interface (not setting) for some reason cannot be found, KErrArgument if an
       
   498     invalid interface setting number is specified (not existing or existing but too small), KErrNone if
       
   499     interface successfully released or if this client doesn't own any interface.
       
   500 */
       
   501 EXPORT_C TInt DUsbClientController::ReleaseInterface(const DBase* aClientId, TInt aInterfaceNum)
       
   502     {
       
   503     __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::ReleaseInterface(..., %d)", aInterfaceNum));
       
   504     const TInt ifcset = ClientId2InterfaceNumber(aClientId);
       
   505     if (ifcset < 0)
       
   506         {
       
   507         __KTRACE_OPT(KUSB, Kern::Printf("  interface not found")); // no error
       
   508         return KErrNone;
       
   509         }
       
   510     TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(ifcset);
       
   511     if (!ifcset_ptr)
       
   512         {
       
   513         __KTRACE_OPT(KUSB, Kern::Printf("  Error: interface number %d doesn't exist", ifcset));
       
   514         return KErrNotFound;
       
   515         }
       
   516     const TInt setting_count = ifcset_ptr->iInterfaces.Count();
       
   517     if ((setting_count - 1) != aInterfaceNum)
       
   518         {
       
   519         __KTRACE_OPT(KUSB,
       
   520                      Kern::Printf("  Error: interface settings must be released in descending order:\n\r"
       
   521                                   "   %d setting(s) exist, #%d was requested to be released.\n\r"
       
   522                                   "   (#%d has to be released first)",
       
   523                                   setting_count, aInterfaceNum, setting_count - 1));
       
   524         return KErrArgument;
       
   525         }
       
   526     // Tear down current setting (invalidate configured state)
       
   527     __KTRACE_OPT(KUSB, Kern::Printf("  tearing down InterfaceSet %d", ifcset));
       
   528     // Cancel all transfers on the current setting of this interface and deconfigure all its endpoints.
       
   529     InterfaceSetTeardown(ifcset_ptr);
       
   530     // 'Setting 0' means: delete all existing settings.
       
   531     if (aInterfaceNum == 0)
       
   532         {
       
   533         TInt m = ifcset_ptr->iInterfaces.Count();
       
   534         while (m > 0)
       
   535             {
       
   536             m--;
       
   537             // Ground the physical endpoints' logical_endpoint_pointers
       
   538             const TInt n = ifcset_ptr->iInterfaces[m]->iEndpoints.Count();
       
   539             for (TInt i = 0; i < n; ++i)
       
   540                 {
       
   541                 TUsbcPhysicalEndpoint* ptr = const_cast<TUsbcPhysicalEndpoint*>
       
   542                     (ifcset_ptr->iInterfaces[m]->iEndpoints[i]->iPEndpoint);
       
   543                 ptr->iLEndpoint = NULL;
       
   544                 }
       
   545             // Delete the setting itself + its ifc & ep descriptors
       
   546             DeleteInterface(ifcset, m);
       
   547             iDescriptors.DeleteIfcDescriptor(ifcset, m);
       
   548             }
       
   549         }
       
   550     else
       
   551         {
       
   552         // Ground the physical endpoints' logical_endpoint_pointers
       
   553         const TInt n = ifcset_ptr->iInterfaces[aInterfaceNum]->iEndpoints.Count();
       
   554         for (TInt i = 0; i < n; ++i)
       
   555             {
       
   556             TUsbcPhysicalEndpoint* ptr = const_cast<TUsbcPhysicalEndpoint*>
       
   557                 (ifcset_ptr->iInterfaces[aInterfaceNum]->iEndpoints[i]->iPEndpoint);
       
   558             ptr->iLEndpoint = NULL;
       
   559             }
       
   560         // Delete the setting itself + its ifc & ep descriptors
       
   561         DeleteInterface(ifcset, aInterfaceNum);
       
   562         iDescriptors.DeleteIfcDescriptor(ifcset, aInterfaceNum);
       
   563         }
       
   564     // Delete the whole interface if all settings are gone
       
   565     if (ifcset_ptr->iInterfaces.Count() == 0)
       
   566         {
       
   567         DeleteInterfaceSet(ifcset);
       
   568         }
       
   569     // We now no longer have a valid current configuration
       
   570     iCurrentConfig = 0;
       
   571     if (iDeviceState == UsbShai::EUsbPeripheralStateConfigured)
       
   572         {
       
   573         NextDeviceState(UsbShai::EUsbPeripheralStateAddress);
       
   574         }
       
   575     // If it was the last interface(set)...
       
   576     if (iConfigs[0]->iInterfaceSets.Count() == 0)
       
   577         {
       
   578         __KTRACE_OPT(KUSB, Kern::Printf("  No ifc left -> turning off UDC"));
       
   579         // First disconnect the device from the bus
       
   580         UsbDisconnect();
       
   581         DeActivateHardwareController();
       
   582         // (this also disables endpoint zero; we cannot have a USB device w/o interface, see 9.6.3)
       
   583         }
       
   584     __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::ReleaseInterface"));
       
   585     return KErrNone;
       
   586     }
       
   587 
       
   588 
       
   589 /** Enforces a USB re-enumeration by disconnecting the UDC from the bus (if it is currently connected) and
       
   590     re-connecting it.
       
   591 
       
   592     This only works if the PSL supports it, i.e. if SoftConnectCaps() returns ETrue.
       
   593 */
       
   594 EXPORT_C TInt DUsbClientController::ReEnumerate()
       
   595     {
       
   596     __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::ReEnumerate()"));
       
   597     
       
   598     // ReEnumerate is possible only when stack is enabled
       
   599     if (!iStackIsActive)
       
   600         {
       
   601         __KTRACE_OPT(KUSB, Kern::Printf("  Client stack disabled -> returning here"));
       
   602         return KErrNotReady;
       
   603         }
       
   604     
       
   605     // If no interfaces setup, there is no point to reenumerate
       
   606     if (iConfigs[0]->iInterfaceSets.Count() == 0)
       
   607         {
       
   608         __KTRACE_OPT(KUSB, Kern::Printf("  > No interface registered -> no need to re-enumerate"));
       
   609         return KErrNone;;
       
   610         }
       
   611     
       
   612     if (!iHardwareActivated)
       
   613         {
       
   614         // If the UDC is still off, we switch it on here.
       
   615         const TInt r = ActivateHardwareController();
       
   616         if (r != KErrNone)
       
   617                 {
       
   618                 __KTRACE_OPT(KPANIC, Kern::Printf("  Error: ActivateHardwareController() failed: %d", r));
       
   619                 return r;
       
   620                 }
       
   621         
       
   622         // Finally connect the device to the bus
       
   623         UsbConnect();
       
   624         }
       
   625     else
       
   626         {
       
   627         UsbDisconnect();
       
   628         
       
   629         // Now we have to wait a certain amount of time, in order to give the host the opportunity
       
   630         // to come to terms with the new situation.
       
   631         // (The ETrue parameter makes the callback get called in DFC instead of in ISR context.)
       
   632         iReconnectTimer.OneShot(KUsbReconnectDelay, ETrue);
       
   633         }
       
   634         
       
   635     __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::ReEnumerate()"));
       
   636     return KErrNone;;
       
   637     }
       
   638 
       
   639 
       
   640 /** Powers up the UDC if one or more interfaces exist.
       
   641 
       
   642     @return KErrNone if UDC successfully powered up, KErrNotReady if no
       
   643     interfaces have been registered yet, KErrHardwareNotAvailable if UDC
       
   644     couldn't be activated.
       
   645 */
       
   646 EXPORT_C TInt DUsbClientController::PowerUpUdc()
       
   647     {
       
   648     __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::PowerUpUdc()"));
       
   649     
       
   650     // we need to check whether Stack is activate or not(can be done by otg sw in otg setup
       
   651     // or by vBus risen/fallen event in a non-otg env)
       
   652     if (!iStackIsActive)
       
   653         {
       
   654         __KTRACE_OPT(KUSB, Kern::Printf("  Client stack disabled -> returning here"));
       
   655         return KErrNotReady;
       
   656         }
       
   657     
       
   658     if (iConfigs[0]->iInterfaceSets.Count() == 0)
       
   659         {
       
   660         __KTRACE_OPT(KUSB, Kern::Printf("  No interface registered -> won't power up UDC"));
       
   661         return KErrNotReady;
       
   662         }
       
   663     
       
   664     // If the UDC is still off, we switch it on here.
       
   665     const TInt r = ActivateHardwareController();
       
   666     if (r != KErrNone)
       
   667         {
       
   668         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: ActivateHardwareController() failed: %d", r));
       
   669         }
       
   670     
       
   671     __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::PowerUpUdc() returns %d",r));
       
   672     return r;
       
   673     }
       
   674 
       
   675 
       
   676 /** Connects the UDC to the bus.
       
   677 
       
   678     @return KErrNone if UDC successfully connected, 
       
   679             KErrNotSupported if KDevCapSoftConnect not supported
       
   680             KErrGeneral if there was an error.
       
   681             
       
   682 */
       
   683 EXPORT_C TInt DUsbClientController::UsbConnect()
       
   684     {
       
   685     __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::UsbConnect()"));
       
   686     iClientSupportReady = ETrue;
       
   687     
       
   688     // If a deferred reset is pending, service it now
       
   689     const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
       
   690     if (iUsbResetDeferred)
       
   691         {
       
   692         __KTRACE_OPT(KUSB, Kern::Printf("  Resetting USB Reset 'defer' flag"));
       
   693         iUsbResetDeferred = EFalse;
       
   694         (void) ProcessResetEvent(EFalse);
       
   695         }
       
   696     __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
       
   697 
       
   698     // Indicate readiness to connect to the PSL
       
   699     const TInt r = iController.PeripheralConnect();
       
   700     
       
   701     // Check whether Stack is activated by OTG controller
       
   702     // or Vbus Risen had been detected.
       
   703     // If either of them is true and HW is not activated yet, do it here.
       
   704     if (iStackIsActive &&  !iHardwareActivated )
       
   705         {
       
   706         // PowerUpUdc only do Activating Hardware when there are at least 1
       
   707         // Iterface registered            
       
   708         PowerUpUdc();
       
   709         }
       
   710     
       
   711     __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::UsbConnect()"));
       
   712     return r;
       
   713     }
       
   714 
       
   715 
       
   716 /** Disconnects the UDC from the bus.
       
   717 
       
   718     This only works if the PSL supports it, i.e. if SoftConnectCaps() returns ETrue.
       
   719 
       
   720     @return KErrNone if UDC successfully disconnected, KErrGeneral if there was an error.
       
   721 */
       
   722 EXPORT_C TInt DUsbClientController::UsbDisconnect()
       
   723     {
       
   724     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::UsbDisconnect()"));
       
   725     iClientSupportReady = EFalse;
       
   726 
       
   727     // Indicate to PSL that we are no longer ready to connect
       
   728     const TInt r = iController.PeripheralDisconnect();
       
   729 
       
   730     // There won't be any notification by the PSL about this,
       
   731     // so we have to notify the LDD/user ourselves:
       
   732     if ((r == KErrNone) && (iDeviceState != UsbShai::EUsbPeripheralStateUndefined))
       
   733         {
       
   734         // Not being in state UNDEFINED implies that the cable is inserted.
       
   735         if (iHardwareActivated)
       
   736             {
       
   737             NextDeviceState(UsbShai::EUsbPeripheralStatePowered);
       
   738             }
       
   739         // (If the hardware is NOT activated at this point, we can only be in
       
   740         //    state UsbShai::EUsbPeripheralStateAttached, so we don't have to move to it.)
       
   741         }
       
   742     return r;
       
   743     }
       
   744 
       
   745 
       
   746 /** Registers a notification callback for changes of the USB device state.
       
   747 
       
   748     In the event of a device state change, the callback's state member gets updated (using SetState) with a
       
   749     new UsbShai::TUsbPeripheralState value, and then the callback is executed (DoCallback). 'USB device state' here refers
       
   750     to the Visible Device States as defined in chapter 9 of the USB specification.
       
   751 
       
   752     @param aCallback A reference to a properly filled in status callback structure.
       
   753 
       
   754     @return KErrNone if callback successfully registered, KErrGeneral if this callback is already registered
       
   755     (it won't be registered twice).
       
   756 */
       
   757 EXPORT_C TInt DUsbClientController::RegisterForStatusChange(TUsbcStatusCallback& aCallback)
       
   758     {
       
   759     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RegisterForStatusChange()"));
       
   760     if (iStatusCallbacks.Elements() == KUsbcMaxListLength)
       
   761         {
       
   762         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Maximum list length reached: %d",
       
   763                                           KUsbcMaxListLength));
       
   764         return KErrGeneral;
       
   765         }
       
   766     if (IsInTheStatusList(aCallback))
       
   767         {
       
   768         __KTRACE_OPT(KUSB, Kern::Printf("  Error: StatusCallback @ 0x%x already registered", &aCallback));
       
   769         return KErrGeneral;
       
   770         }
       
   771     const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
       
   772     iStatusCallbacks.AddLast(aCallback);
       
   773     __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
       
   774     return KErrNone;
       
   775     }
       
   776 
       
   777 
       
   778 /** De-registers (removes from the list of pending requests) a notification callback for the USB device
       
   779     status.
       
   780 
       
   781     @param aClientId A pointer to the LDD owning the status change callback.
       
   782 
       
   783     @return KErrNone if callback successfully unregistered, KErrNotFound if the callback couldn't be found.
       
   784 */
       
   785 EXPORT_C TInt DUsbClientController::DeRegisterForStatusChange(const DBase* aClientId)
       
   786     {
       
   787     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForStatusChange()"));
       
   788     __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
       
   789     const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
       
   790     TSglQueIter<TUsbcStatusCallback> iter(iStatusCallbacks);
       
   791     TUsbcStatusCallback* p;
       
   792     while ((p = iter++) != NULL)
       
   793         {
       
   794         if (p->Owner() == aClientId)
       
   795             {
       
   796             __KTRACE_OPT(KUSB, Kern::Printf("  removing StatusCallback @ 0x%x", p));
       
   797             iStatusCallbacks.Remove(*p);
       
   798             __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
       
   799             return KErrNone;
       
   800             }
       
   801         }
       
   802     __KTRACE_OPT(KUSB, Kern::Printf("  client not found"));
       
   803     __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
       
   804     return KErrNotFound;
       
   805     }
       
   806 
       
   807 
       
   808 /** Registers a notification callback for changes of the state of endpoints.
       
   809 
       
   810     In the event of a state change of an endpoint that is spart of an interface which is owned by the LDD
       
   811     specified in the callback structure, the callback's state member gets updated (using SetState) with a new
       
   812     value, and the callback is executed (DoCallback). 'Endpoint state' here refers to the state of the
       
   813     ENDPOINT_HALT feature of an endpoint as described in chapter 9 of the USB specification. The contents of
       
   814     the state variable reflects the state of the halt features for all endpoints of the current interface
       
   815     setting: bit 0 represents endpoint 1, bit 1 endpoint 2, etc. A set bit means 'endpoint halted', a cleared
       
   816     bit 'endpoint not halted'.
       
   817 
       
   818     @param aCallback A reference to a properly filled in endpoint status callback structure.
       
   819 
       
   820     @return KErrNone if callback successfully registered, KErrGeneral if this callback is already registered
       
   821     (it won't be registered twice).
       
   822 */
       
   823 EXPORT_C TInt DUsbClientController::RegisterForEndpointStatusChange(TUsbcEndpointStatusCallback& aCallback)
       
   824     {
       
   825     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RegisterForEndpointStatusChange()"));
       
   826     if (iEpStatusCallbacks.Elements() == KUsbcMaxListLength)
       
   827         {
       
   828         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Maximum list length reached: %d",
       
   829                                           KUsbcMaxListLength));
       
   830         return KErrGeneral;
       
   831         }
       
   832     if (IsInTheEpStatusList(aCallback))
       
   833         {
       
   834         __KTRACE_OPT(KUSB, Kern::Printf("  Error: EpStatusCallback @ 0x%x already registered", &aCallback));
       
   835         return KErrGeneral;
       
   836         }
       
   837     const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
       
   838     iEpStatusCallbacks.AddLast(aCallback);
       
   839     __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
       
   840     return KErrNone;
       
   841     }
       
   842 
       
   843 
       
   844 /** De-registers (removes from the list of pending requests) a notification callback for changes of the state
       
   845     of endpoints.
       
   846 
       
   847     @param aClientId A pointer to the LDD owning the endpoint status change callback.
       
   848 
       
   849     @return KErrNone if callback successfully unregistered, KErrNotFound if the callback couldn't be found.
       
   850 */
       
   851 EXPORT_C TInt DUsbClientController::DeRegisterForEndpointStatusChange(const DBase* aClientId)
       
   852     {
       
   853     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForEndpointStatusChange()"));
       
   854     __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
       
   855     const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
       
   856     TSglQueIter<TUsbcEndpointStatusCallback> iter(iEpStatusCallbacks);
       
   857     TUsbcEndpointStatusCallback* p;
       
   858     while ((p = iter++) != NULL)
       
   859         {
       
   860         if (p->Owner() == aClientId)
       
   861             {
       
   862             __KTRACE_OPT(KUSB, Kern::Printf("  removing EpStatusCallback @ 0x%x", p));
       
   863             iEpStatusCallbacks.Remove(*p);
       
   864             __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
       
   865             return KErrNone;
       
   866             }
       
   867         }
       
   868     __KTRACE_OPT(KUSB, Kern::Printf("  client not found"));
       
   869     __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
       
   870     return KErrNotFound;
       
   871     }
       
   872 
       
   873 
       
   874 /** Returns the number of the currently active alternate interface setting for this interface.
       
   875 
       
   876     @param aClientId A pointer to the LDD owning the interface.
       
   877     @param aInterfaceNum Here the interface gets written to.
       
   878 
       
   879     @return KErrNotFound if an interface for this client couldn't be found, KErrNone if setting value was
       
   880     successfully written.
       
   881 */
       
   882 EXPORT_C TInt DUsbClientController::GetInterfaceNumber(const DBase* aClientId, TInt& aInterfaceNum) const
       
   883     {
       
   884     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetInterfaceNumber()"));
       
   885     const TInt ifcset = ClientId2InterfaceNumber(aClientId);
       
   886     if (ifcset < 0)
       
   887         {
       
   888         __KTRACE_OPT(KPANIC, Kern::Printf("  Error (ifc < 0)"));
       
   889         return KErrNotFound;
       
   890         }
       
   891     const TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(ifcset);
       
   892     if (!ifcset_ptr)
       
   893         {
       
   894         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: interface number %d doesn't exist", ifcset));
       
   895         return KErrNotFound;
       
   896         }
       
   897     aInterfaceNum = ifcset_ptr->iCurrentInterface;
       
   898     return KErrNone;
       
   899     }
       
   900 
       
   901 
       
   902 /** This is normally called once by an LDD's destructor, either after a Close() on the user side,
       
   903     or during general cleanup.
       
   904 
       
   905     It might also be called by the LDD when some internal unrecoverable error occurs.
       
   906 
       
   907     This function
       
   908     - de-registers a possibly pending device state change notification request,
       
   909     - de-registers a possibly pending endpoint state change notification request,
       
   910     - releases all interfaces + settings owned by this LDD,
       
   911     - cancels all remaining (if any) read/write requests.
       
   912 
       
   913     @param aClientId A pointer to the LDD to be unregistered.
       
   914 
       
   915     @return KErrNone.
       
   916 */
       
   917 EXPORT_C TInt DUsbClientController::DeRegisterClient(const DBase* aClientId)
       
   918     {
       
   919     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterClient(0x%x)", aClientId));
       
   920     // Cancel all device state notification requests
       
   921     DeRegisterForStatusChange(aClientId);
       
   922     // Cancel all endpoint state notification requests
       
   923     DeRegisterForEndpointStatusChange(aClientId);
       
   924     DeRegisterForOtgFeatureChange(aClientId);
       
   925     DeRegisterClientCallback(aClientId);
       
   926     // Delete the interface including all its alternate settings which might exist.
       
   927     // (If we release the default setting (0), all alternate settings are deleted as well.)
       
   928     const TInt r = ReleaseInterface(aClientId, 0);
       
   929     // Cancel all remaining (if any) read/write requests
       
   930     DeleteRequestCallbacks(aClientId);
       
   931     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterClient: Done."));
       
   932     return r;
       
   933     }
       
   934 
       
   935 
       
   936 /** Returns the currently used Ep0 max packet size.
       
   937 
       
   938     @return The currently used Ep0 max packet size.
       
   939 */
       
   940 EXPORT_C TInt DUsbClientController::Ep0PacketSize() const
       
   941     {
       
   942     const TUsbcLogicalEndpoint* const ep = iRealEndpoints[0].iLEndpoint;
       
   943     if (iHighSpeed)
       
   944         {
       
   945         __KTRACE_OPT(KUSB, Kern::Printf("  Ep0 size = %d (HS)", ep->iEpSize_Hs));
       
   946         return ep->iEpSize_Hs;
       
   947         }
       
   948     else
       
   949         {
       
   950         __KTRACE_OPT(KUSB, Kern::Printf("  Ep0 size = %d (FS)", ep->iEpSize_Fs));
       
   951         return ep->iEpSize_Fs;
       
   952         }
       
   953     }
       
   954 
       
   955 
       
   956 /** Stalls Ep0.
       
   957 
       
   958     @param aClientId A pointer to the LDD wishing to stall Ep0 (this is for PIL internal purposes only).
       
   959 
       
   960     @return KErrNone if endpoint zero successfully stalled, KErrGeneral otherwise.
       
   961 */
       
   962 EXPORT_C TInt DUsbClientController::Ep0Stall(const DBase* aClientId)
       
   963     {
       
   964     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::Ep0Stall()"));
       
   965     if (aClientId == iEp0ClientId)
       
   966         {
       
   967         ResetEp0DataOutVars();
       
   968         }
       
   969     const TInt err = iConTransferMgr->StallEndpoint(KEp0_Out);
       
   970     if (err < 0)
       
   971         {
       
   972         return err;
       
   973         }
       
   974     else
       
   975         return iConTransferMgr->StallEndpoint(KEp0_In);
       
   976     }
       
   977 
       
   978 
       
   979 /** Sends a zero-byte status packet on Ep0.
       
   980 
       
   981     @param aClientId A pointer to the LDD wishing to send the status packet (not used at present).
       
   982 */
       
   983 EXPORT_C void DUsbClientController::SendEp0StatusPacket(const DBase* /* aClientId */)
       
   984     {
       
   985     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SendEp0StatusPacket()"));
       
   986     iConTransferMgr->SendEp0ZeroByteStatusPacket();
       
   987     }
       
   988 
       
   989 
       
   990 /** Returns the current USB device state.
       
   991 
       
   992     'USB device state' here refers to the Visible Device States as defined in chapter 9 of the USB
       
   993     specification.
       
   994 
       
   995     @return The current USB device state, or UsbShai::EUsbPeripheralStateUndefined
       
   996 */
       
   997 EXPORT_C UsbShai::TUsbPeripheralState DUsbClientController::GetDeviceStatus() const
       
   998     {
       
   999     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetDeviceStatus()"));
       
  1000     return iDeviceState;
       
  1001     }
       
  1002 
       
  1003 
       
  1004 /** Returns the state of an endpoint.
       
  1005 
       
  1006     'Endpoint state' here refers to the state of the ENDPOINT_HALT feature of
       
  1007     an endpoint as described in chapter 9 of the USB specification.
       
  1008 
       
  1009     @param aClientId A pointer to the LDD owning the interface which contains the endpoint to be queried.
       
  1010     @param aEndpointNum The number of the endpoint to be queried.
       
  1011 
       
  1012     @return The current endpoint state, or EEndpointStateUnknown if the endpoint couldn't be found.
       
  1013 */
       
  1014 EXPORT_C TEndpointState DUsbClientController::GetEndpointStatus(const DBase* aClientId, TInt aEndpointNum) const
       
  1015     {
       
  1016     __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::GetEndpointStatus()"));
       
  1017     
       
  1018     TEndpointState ret = (iRealEndpoints[aEndpointNum].iHalt)?EEndpointStateStalled : EEndpointStateNotStalled;
       
  1019     
       
  1020     __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::GetEndpointStatus() %d",ret));
       
  1021     
       
  1022     return  ret;
       
  1023     }
       
  1024 
       
  1025 
       
  1026 /** Sets up a data read request for an endpoint.
       
  1027 
       
  1028     @param aCallback A reference to a properly filled in data transfer request callback structure.
       
  1029 
       
  1030     @return KErrNone if callback successfully registered or if this callback is already registered
       
  1031     (but it won't be registered twice), KErrNotFound if the endpoint couldn't be found, KErrArgument if
       
  1032     endpoint number invalid (PSL), KErrGeneral if something else goes wrong.
       
  1033 */
       
  1034 EXPORT_C TInt DUsbClientController::SetupReadBuffer(TUsbcRequestCallback& aCallback)
       
  1035     {
       
  1036     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetupReadBuffer()"));
       
  1037     const TInt ep = aCallback.iRealEpNum;
       
  1038     __KTRACE_OPT(KUSB, Kern::Printf("  logical ep: #%d", aCallback.iEndpointNum));
       
  1039     __KTRACE_OPT(KUSB, Kern::Printf("  real ep:    #%d", ep));
       
  1040     TInt err = KErrGeneral;
       
  1041     if (ep != 0)
       
  1042         {
       
  1043         if (iRequestCallbacks[ep])
       
  1044             {
       
  1045             __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: RequestCallback already registered for that ep"));
       
  1046             if (iRequestCallbacks[ep] == &aCallback)
       
  1047                 {
       
  1048                 __KTRACE_OPT(KPANIC, Kern::Printf("  (this same RequestCallback @ 0x%x)", &aCallback));
       
  1049                 }
       
  1050             else
       
  1051                 {
       
  1052                 __KTRACE_OPT(KPANIC, Kern::Printf("  (a different RequestCallback @ 0x%x)", &aCallback));
       
  1053                 }
       
  1054             return KErrNone;
       
  1055             }
       
  1056         // This may seem awkward:
       
  1057         // First we add a callback, and then, in case of an error, we remove it again.
       
  1058         // However this is necessary because the transfer request might complete (through
       
  1059         // an ISR) _before_ the SetupEndpointRead function returns. Since we don't know the
       
  1060         // outcome, we have to provide the callback before making the setup call.
       
  1061         //
       
  1062         __KTRACE_OPT(KUSB, Kern::Printf("  adding RequestCallback[%d] @ 0x%x", ep, &aCallback));
       
  1063         iRequestCallbacks[ep] = &aCallback;
       
  1064         if ((err = iController.SetupEndpointRead(ep, aCallback)) != KErrNone)
       
  1065             {
       
  1066             __KTRACE_OPT(KPANIC, Kern::Printf("  removing RequestCallback @ 0x%x (due to error)",
       
  1067                                               &aCallback));
       
  1068             iRequestCallbacks[ep] = NULL;
       
  1069             }
       
  1070         }
       
  1071     else                                                    // (ep == 0)
       
  1072         {
       
  1073         if (iEp0ReadRequestCallbacks.Elements() == KUsbcMaxListLength)
       
  1074             {
       
  1075             __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Maximum list length reached: %d",
       
  1076                                               KUsbcMaxListLength));
       
  1077             return KErrGeneral;
       
  1078             }
       
  1079         if (IsInTheRequestList(aCallback))
       
  1080             {       
       
  1081             __KTRACE_OPT(KUSB, Kern::Printf("  RequestCallback @ 0x%x already registered", &aCallback));
       
  1082             return KErrNone;
       
  1083             }
       
  1084         // Ep0 reads don't need to be prepared - there's always one pending
       
  1085         __KTRACE_OPT(KUSB, Kern::Printf("  adding RequestCallback @ 0x%x (ep0)", &aCallback));
       
  1086         const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
       
  1087         iEp0ReadRequestCallbacks.AddLast(aCallback);
       
  1088         __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
       
  1089         err = KErrNone;
       
  1090         if (iEp0_RxExtraCount != 0)
       
  1091             {
       
  1092             __KTRACE_OPT(KUSB, Kern::Printf("  iEp0_RxExtraData: trying again..."));
       
  1093             
       
  1094             const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
       
  1095             
       
  1096             // Extra data is either a setup packet or a data packet
       
  1097             // They are not possible to be both
       
  1098             // And, the error code must be KErrNone, otherwise, we can not arrive here
       
  1099             if( iSetupPacketPending )
       
  1100                 {
       
  1101                 ProcessSetupPacket(iEp0_RxExtraCount,KErrNone);
       
  1102                 }
       
  1103             else
       
  1104                 {
       
  1105                 ProcessDataOutPacket(iEp0_RxExtraCount,KErrNone);
       
  1106                 }
       
  1107             
       
  1108             // clear it since already completed to client
       
  1109             iEp0_RxExtraCount = 0;
       
  1110             
       
  1111             err = iLastError;
       
  1112             
       
  1113             __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
       
  1114             if (err == KErrNone)
       
  1115                 {
       
  1116                 //iEp0_RxExtraData = EFalse;
       
  1117                 // Queue a new Ep0 read (because xxxProceed only re-enables the interrupt)
       
  1118                 iConTransferMgr->SetupEndpointZeroRead();
       
  1119                 if (iSetupPacketPending)
       
  1120                     {
       
  1121                     iConTransferMgr->Ep0SetupPacketProceed();
       
  1122                     iSetupPacketPending = EFalse;
       
  1123                     }
       
  1124                 else
       
  1125                     {
       
  1126                     iConTransferMgr->Ep0DataPacketProceed();
       
  1127                     }
       
  1128                 
       
  1129                 __KTRACE_OPT(KUSB, Kern::Printf("  :-)"));
       
  1130                 }
       
  1131             else
       
  1132                 {
       
  1133                 __KTRACE_OPT(KPANIC, Kern::Printf("  Error: :-("));
       
  1134                 err = KErrGeneral;
       
  1135                 }
       
  1136             return err;
       
  1137             }
       
  1138         }
       
  1139     return err;
       
  1140     }
       
  1141 
       
  1142 
       
  1143 /** Sets up a data write request for an endpoint.
       
  1144 
       
  1145     @param aCallback A reference to a properly filled in data transfer request callback structure.
       
  1146 
       
  1147     @return KErrNone if callback successfully registered or if this callback is already registered
       
  1148     (but it won't be registered twice), KErrNotFound if the endpoint couldn't be found, KErrArgument if
       
  1149     endpoint number invalid (PSL), KErrGeneral if something else goes wrong.
       
  1150 */
       
  1151 EXPORT_C TInt DUsbClientController::SetupWriteBuffer(TUsbcRequestCallback& aCallback)
       
  1152     {
       
  1153     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetupWriteBuffer()"));
       
  1154     TInt ep = aCallback.iRealEpNum;
       
  1155     __KTRACE_OPT(KUSB, Kern::Printf("  logical ep: #%d", aCallback.iEndpointNum));
       
  1156     __KTRACE_OPT(KUSB, Kern::Printf("  real ep:       #%d", ep));
       
  1157     if (iRequestCallbacks[ep])
       
  1158         {
       
  1159         __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: RequestCallback already registered for that ep"));
       
  1160         if (iRequestCallbacks[ep] == &aCallback)
       
  1161             {
       
  1162             __KTRACE_OPT(KPANIC, Kern::Printf("  (this same RequestCallback @ 0x%x)", &aCallback));
       
  1163             return KErrNone;
       
  1164             }
       
  1165         else
       
  1166             {
       
  1167             __KTRACE_OPT(KPANIC, Kern::Printf("  (a different RequestCallback @ 0x%x - poss. error)",
       
  1168                                               &aCallback));
       
  1169             return KErrGeneral;
       
  1170             }
       
  1171         }
       
  1172     if (ep == 0)
       
  1173         {
       
  1174         if (iEp0_TxNonStdCount)
       
  1175             {
       
  1176             if (iEp0_TxNonStdCount > aCallback.iLength)
       
  1177                 {
       
  1178                 __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Ep0 is sending less data than requested"));
       
  1179                 if ((aCallback.iLength % iEp0MaxPacketSize == 0) && !aCallback.iZlpReqd)
       
  1180                     {
       
  1181                     __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Zlp should probably be requested"));
       
  1182                     }
       
  1183                 }
       
  1184             else if (iEp0_TxNonStdCount < aCallback.iLength)
       
  1185                 {
       
  1186                 __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Ep0 is sending more data than requested"));
       
  1187                 }
       
  1188             iEp0_TxNonStdCount = 0;
       
  1189             }
       
  1190         // Ep0 IN needs to be adjusted: the LDD uses 0 for both Ep0 directions.
       
  1191         ep = KEp0_Tx;
       
  1192         }
       
  1193     // This may seem awkward:
       
  1194     // First we add a callback, and then, in case of an error, we remove it again.
       
  1195     // However this is necessary because the transfer request might complete (through
       
  1196     // an ISR) _before_ the SetupEndpointWrite function returns. Since we don't know the
       
  1197     // outcome, we have to provide the callback before making the setup call.
       
  1198     //
       
  1199     __KTRACE_OPT(KUSB, Kern::Printf("  adding RequestCallback[%d] @ 0x%x", ep, &aCallback));
       
  1200     iRequestCallbacks[ep] = &aCallback;
       
  1201     if (ep == KEp0_Tx)
       
  1202         {
       
  1203         iEp0ClientDataTransmitting = ETrue;             // this must be set before calling SetupEndpointZeroWrite
       
  1204         TInt ret = iConTransferMgr->SetupEndpointZeroWrite(aCallback.iBufferStart, aCallback.iLength, aCallback.iZlpReqd);
       
  1205         if (ret != KErrNone)
       
  1206             {
       
  1207             __KTRACE_OPT(KPANIC, Kern::Printf("  removing RequestCallback @ 0x%x (due to error)", &aCallback));
       
  1208             iRequestCallbacks[ep] = NULL;
       
  1209             iEp0ClientDataTransmitting = EFalse;
       
  1210             return ret;
       
  1211             }
       
  1212         }
       
  1213     else if (iController.SetupEndpointWrite(ep, aCallback) != KErrNone)
       
  1214         {
       
  1215         __KTRACE_OPT(KPANIC, Kern::Printf("  removing RequestCallback @ 0x%x (due to error)", &aCallback));
       
  1216         iRequestCallbacks[ep] = NULL;
       
  1217         }
       
  1218     return KErrNone;
       
  1219     }
       
  1220 
       
  1221 
       
  1222 /** Cancels a data read request for an endpoint.
       
  1223 
       
  1224     The request callback will be removed from the queue and the
       
  1225     callback function won't be executed.
       
  1226 
       
  1227     @param aClientId A pointer to the LDD owning the interface which contains the endpoint.
       
  1228     @param aRealEndpoint The number of the endpoint for which the transfer request is to be cancelled.
       
  1229 */
       
  1230 EXPORT_C void DUsbClientController::CancelReadBuffer(const DBase* aClientId, TInt aRealEndpoint)
       
  1231     {
       
  1232     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CancelReadBuffer(%d)", aRealEndpoint));
       
  1233     if (aRealEndpoint < 0)
       
  1234         {
       
  1235         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: ep # < 0: %d", aRealEndpoint));
       
  1236         return;
       
  1237         }
       
  1238     // Note that we here don't cancel Ep0 read requests at the PSL level!
       
  1239     if (aRealEndpoint > 0)
       
  1240         {
       
  1241         iController.CancelEndpointRead(aRealEndpoint);
       
  1242         }
       
  1243     DeleteRequestCallback(aClientId, aRealEndpoint, UsbShai::EControllerRead);
       
  1244     }
       
  1245 
       
  1246 
       
  1247 /** Cancels a data write request for an endpoint.
       
  1248 
       
  1249     It cannot be guaranteed that the data is not sent nonetheless, as some UDCs don't permit a flushing of a
       
  1250     TX FIFO once it has been filled. The request callback will be removed from the queue in any case and the
       
  1251     callback function won't be executed.
       
  1252 
       
  1253     @param aClientId A pointer to the LDD owning the interface which contains the endpoint.
       
  1254     @param aRealEndpoint The number of the endpoint for which the transfer request is to be cancelled.
       
  1255 */
       
  1256 EXPORT_C void DUsbClientController::CancelWriteBuffer(const DBase* aClientId, TInt aRealEndpoint)
       
  1257     {
       
  1258     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CancelWriteBuffer(%d)", aRealEndpoint));
       
  1259     if (aRealEndpoint < 0)
       
  1260         {
       
  1261         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: ep # < 0: %d", aRealEndpoint));
       
  1262         return;
       
  1263         }
       
  1264     if (aRealEndpoint == 0)
       
  1265         {
       
  1266         // Ep0 IN needs to be adjusted: the LDD uses 0 for both Ep0 directions.
       
  1267         aRealEndpoint = KEp0_Tx;
       
  1268         }
       
  1269     iController.CancelEndpointWrite(aRealEndpoint);
       
  1270     if (aRealEndpoint == KEp0_Tx)
       
  1271         {
       
  1272         // Since Ep0 is shared among clients, we don't have to care about the client id.
       
  1273         iEp0WritePending = EFalse;
       
  1274         }
       
  1275     DeleteRequestCallback(aClientId, aRealEndpoint, UsbShai::EControllerWrite);
       
  1276     }
       
  1277 
       
  1278 
       
  1279 /** Halts (stalls) an endpoint (but not Ep0).
       
  1280 
       
  1281     @param aClientId A pointer to the LDD owning the interface which contains the endpoint to be stalled.
       
  1282     @param aEndpointNum The number of the endpoint.
       
  1283 
       
  1284     @return KErrNotFound if endpoint couldn't be found (includes Ep0), KErrNone if endpoint successfully
       
  1285     stalled, KErrGeneral otherwise.
       
  1286 */
       
  1287 EXPORT_C TInt DUsbClientController::HaltEndpoint(const DBase* aClientId, TInt aEndpointNum)
       
  1288     {
       
  1289     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::HaltEndpoint(%d)", aEndpointNum));
       
  1290     const TInt r = iController.StallEndpoint(aEndpointNum);
       
  1291     if (r == KErrNone)
       
  1292         {
       
  1293         iRealEndpoints[aEndpointNum].iHalt = ETrue;
       
  1294         }
       
  1295     else if (r == KErrArgument)
       
  1296         {
       
  1297         return KErrNotFound;
       
  1298         }
       
  1299     return r;
       
  1300     }
       
  1301 
       
  1302 
       
  1303 /** Clears the halt condition of an endpoint (but not Ep0).
       
  1304 
       
  1305     @param aClientId A pointer to the LDD owning the interface which contains the endpoint to be un-stalled.
       
  1306     @param aEndpointNum The number of the endpoint.
       
  1307 
       
  1308     @return KErrNotFound if endpoint couldn't be found (includes Ep0), KErrNone if endpoint successfully
       
  1309     stalled, KErrGeneral otherwise.
       
  1310 */
       
  1311 EXPORT_C TInt DUsbClientController::ClearHaltEndpoint(const DBase* aClientId, TInt aEndpointNum)
       
  1312     {
       
  1313     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ClearHaltEndpoint(%d)", aEndpointNum));
       
  1314     const TInt r = iController.ClearStallEndpoint(aEndpointNum);
       
  1315     if (r == KErrNone)
       
  1316         {
       
  1317         iRealEndpoints[aEndpointNum].iHalt = EFalse;
       
  1318         }
       
  1319     else if (r == KErrArgument)
       
  1320         {
       
  1321         return KErrNotFound;
       
  1322         }
       
  1323     return r;
       
  1324     }
       
  1325 
       
  1326 
       
  1327 /** This function requests 'device control' for an LDD.
       
  1328 
       
  1329     Class or vendor specific Ep0 requests addressed to the USB device as a whole (Recipient field in
       
  1330     bmRequestType byte of a Setup packet set to zero) are delivered to the LDD that owns device control. For
       
  1331     obvious reasons only one USB LDD can have device control at any given time.
       
  1332 
       
  1333     @param aClientId A pointer to the LDD requesting device control.
       
  1334 
       
  1335     @return KErrNone if device control successfully claimed or if this LDD already owns it, KErrGeneral if
       
  1336     device control already owned by a different client.
       
  1337 */
       
  1338 EXPORT_C TInt DUsbClientController::SetDeviceControl(const DBase* aClientId)
       
  1339     {
       
  1340     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetDeviceControl()"));
       
  1341     if (iEp0DeviceControl)
       
  1342         {
       
  1343         if (iEp0DeviceControl == aClientId)
       
  1344             {
       
  1345             __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Device Control already owned by this client"));
       
  1346             return KErrNone;
       
  1347             }
       
  1348         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Device Control already claimed by a different client"));
       
  1349         return KErrGeneral;
       
  1350         }
       
  1351     iEp0DeviceControl = aClientId;
       
  1352     return KErrNone;
       
  1353     }
       
  1354 
       
  1355 
       
  1356 /** This function releases device control for an LDD.
       
  1357 
       
  1358     @see DUsbClientController::SetDeviceControl()
       
  1359 
       
  1360     @param aClientId A pointer to the LDD releasing device control.
       
  1361 
       
  1362     @return KErrNone if device control successfully released, KErrGeneral if device control owned by a
       
  1363     different client or by no client at all.
       
  1364 */
       
  1365 EXPORT_C TInt DUsbClientController::ReleaseDeviceControl(const DBase* aClientId)
       
  1366     {
       
  1367     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ReleaseDeviceControl()"));
       
  1368     if (iEp0DeviceControl)
       
  1369         {
       
  1370         if (iEp0DeviceControl == aClientId)
       
  1371             {
       
  1372             __KTRACE_OPT(KUSB, Kern::Printf("  Releasing Device Control"));
       
  1373             iEp0DeviceControl = NULL;
       
  1374             return KErrNone;
       
  1375             }
       
  1376         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Device Control owned by a different client"));
       
  1377         }
       
  1378     else
       
  1379         {
       
  1380         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Device Control not owned by any client"));
       
  1381         }
       
  1382     return KErrGeneral;
       
  1383     }
       
  1384 
       
  1385 
       
  1386 /** Returns all available (configurable) max packet sizes for Ep0.
       
  1387 
       
  1388     The information is coded as bitwise OR'ed values of KUsbEpSizeXXX constants (the bitmap format used for
       
  1389     TUsbcEndpointCaps.iSupportedSizes).
       
  1390 
       
  1391     @return All available (configurable) max packet sizes for Ep0.
       
  1392 */
       
  1393 EXPORT_C TUint DUsbClientController::EndpointZeroMaxPacketSizes() const
       
  1394     {
       
  1395     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EndpointZeroMaxPacketSizes()"));
       
  1396     return iRealEndpoints[0].iCaps.iSizes;
       
  1397     }
       
  1398 
       
  1399 
       
  1400 /** Sets (configures) the max packet size for Ep0.
       
  1401 
       
  1402     For available sizes as returned by DUsbClientController::EndpointZeroMaxPacketSizes()
       
  1403 
       
  1404     Note that for HS operation the Ep0 size cannot be chosen, but is fixed at 64 bytes.
       
  1405 
       
  1406     @return KErrNotSupported if invalid size specified, KErrNone if new max packet size successfully set or
       
  1407     requested size was already set.
       
  1408 */
       
  1409 EXPORT_C TInt DUsbClientController::SetEndpointZeroMaxPacketSize(TInt aMaxPacketSize)
       
  1410     {
       
  1411     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetEndpointZeroMaxPacketSize(%d)",
       
  1412                                     aMaxPacketSize));
       
  1413 
       
  1414     if (iControllerProperties.iControllerCaps & UsbShai::KDevCapHighSpeed)
       
  1415         {
       
  1416         // We're not going to mess with this on a HS device.
       
  1417         return KErrNone;
       
  1418         }
       
  1419 
       
  1420     if (!(iRealEndpoints[0].iCaps.iSizes & PacketSize2Mask(aMaxPacketSize)))
       
  1421         {
       
  1422         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: invalid size"));
       
  1423         return KErrNotSupported;
       
  1424         }
       
  1425     if (iRealEndpoints[0].iLEndpoint->iEpSize_Fs == aMaxPacketSize)
       
  1426         {
       
  1427         __KTRACE_OPT(KUSB, Kern::Printf("  this packet size already set -> returning"));
       
  1428         return KErrNone;
       
  1429         }
       
  1430     const TUsbcLogicalEndpoint* const ep0_0 = iRealEndpoints[0].iLEndpoint;
       
  1431     const TUsbcLogicalEndpoint* const ep0_1 = iRealEndpoints[1].iLEndpoint;
       
  1432     const_cast<TUsbcLogicalEndpoint*>(ep0_0)->iEpSize_Fs = aMaxPacketSize;
       
  1433     const_cast<TUsbcLogicalEndpoint*>(ep0_1)->iEpSize_Fs = aMaxPacketSize;
       
  1434 
       
  1435     // @@@ We should probably modify the device descriptor here as well...
       
  1436 
       
  1437     if (iHardwareActivated)
       
  1438         {
       
  1439         // De-configure endpoint zero
       
  1440         iController.DeConfigureEndpoint(KEp0_Out);
       
  1441         iController.DeConfigureEndpoint(KEp0_In);
       
  1442         // Re-configure endpoint zero
       
  1443         const_cast<TUsbcLogicalEndpoint*>(ep0_0)->iInfo.iSize = ep0_0->iEpSize_Fs;
       
  1444         const_cast<TUsbcLogicalEndpoint*>(ep0_1)->iInfo.iSize = ep0_1->iEpSize_Fs;
       
  1445         iController.ConfigureEndpoint(0, ep0_0->iInfo);
       
  1446         iController.ConfigureEndpoint(1, ep0_1->iInfo);
       
  1447         iEp0MaxPacketSize = ep0_0->iInfo.iSize;
       
  1448         }
       
  1449     return KErrNone;
       
  1450     }
       
  1451 
       
  1452 
       
  1453 /** Returns the current USB Device descriptor.
       
  1454 
       
  1455     @param aThread A pointer to the thread the LDD requesting the descriptor is running in.
       
  1456     @param aDeviceDescriptor A reference to a buffer into which the requested descriptor should be written
       
  1457     (most likely located user-side).
       
  1458 
       
  1459     @return The return value of the thread write operation, Kern::ThreadWrite(), when writing to the target
       
  1460     buffer.
       
  1461 */
       
  1462 EXPORT_C TInt DUsbClientController::GetDeviceDescriptor(DThread* aThread, TDes8& aDeviceDescriptor)
       
  1463     {
       
  1464     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetDeviceDescriptor()"));
       
  1465     return iDescriptors.GetDeviceDescriptorTC(aThread, aDeviceDescriptor);
       
  1466     }
       
  1467 
       
  1468 
       
  1469 /** Sets a new USB Device descriptor.
       
  1470 
       
  1471     @param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
       
  1472     @param aDeviceDescriptor A reference to a buffer which contains the descriptor to be set (most likely
       
  1473     located user-side).
       
  1474 
       
  1475     @return The return value of the thread read operation, Kern::ThreadRead(), when reading from the source
       
  1476     buffer in case of a failure, KErrNone if the new descriptor was successfully set.
       
  1477 */
       
  1478 EXPORT_C TInt DUsbClientController::SetDeviceDescriptor(DThread* aThread, const TDes8& aDeviceDescriptor)
       
  1479     {
       
  1480     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetDeviceDescriptor()"));
       
  1481     return iDescriptors.SetDeviceDescriptorTC(aThread, aDeviceDescriptor);
       
  1482     }
       
  1483 
       
  1484 
       
  1485 /** Returns the current USB Device descriptor size.
       
  1486 
       
  1487     @param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
       
  1488     @param aSize A reference to a buffer into which the requested descriptor size should be written
       
  1489     (most likely located user-side).
       
  1490 
       
  1491     @return The return value of the thread write operation, Kern::ThreadWrite(), when writing to the target
       
  1492     buffer.
       
  1493 */
       
  1494 EXPORT_C TInt DUsbClientController::GetDeviceDescriptorSize(DThread* aThread, TDes8& aSize)
       
  1495     {
       
  1496     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetDeviceDescriptorSize()"));
       
  1497     // We do not really enquire here....
       
  1498     const TPtrC8 size(reinterpret_cast<const TUint8*>(&KUsbDescSize_Device), sizeof(KUsbDescSize_Device));
       
  1499     return Kern::ThreadDesWrite(aThread, &aSize, size, 0);
       
  1500     }
       
  1501 
       
  1502 
       
  1503 /** Returns the current USB configuration descriptor.
       
  1504 
       
  1505     @param aThread A pointer to the thread the LDD requesting the descriptor is running in.
       
  1506     @param aConfigurationDescriptor A reference to a buffer into which the requested descriptor should be
       
  1507     written (most likely located user-side).
       
  1508 
       
  1509     @return The return value of the thread write operation, Kern::ThreadWrite(), when writing to the target
       
  1510     buffer.
       
  1511 */
       
  1512 EXPORT_C TInt DUsbClientController::GetConfigurationDescriptor(DThread* aThread, TDes8& aConfigurationDescriptor)
       
  1513     {
       
  1514     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetConfigurationDescriptor()"));
       
  1515     return iDescriptors.GetConfigurationDescriptorTC(aThread, aConfigurationDescriptor);
       
  1516     }
       
  1517 
       
  1518 
       
  1519 /** Sets a new USB configuration descriptor.
       
  1520 
       
  1521     @param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
       
  1522     @param aConfigurationDescriptor A reference to a buffer which contains the descriptor to be set (most
       
  1523     likely located user-side).
       
  1524 
       
  1525     @return The return value of the thread read operation, Kern::ThreadRead() when reading from the source
       
  1526     buffer in case of a failure, KErrNone if the new descriptor was successfully set.
       
  1527 */
       
  1528 EXPORT_C TInt DUsbClientController::SetConfigurationDescriptor(DThread* aThread,
       
  1529                                                                const TDes8& aConfigurationDescriptor)
       
  1530     {
       
  1531     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetConfigurationDescriptor()"));
       
  1532     return iDescriptors.SetConfigurationDescriptorTC(aThread, aConfigurationDescriptor);
       
  1533     }
       
  1534 
       
  1535 
       
  1536 /** Returns the current USB configuration descriptor size.
       
  1537 
       
  1538     @param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
       
  1539     @param aSize A reference to a buffer into which the requested descriptor size should be written
       
  1540     (most likely located user-side).
       
  1541 
       
  1542     @return The return value of the thread write operation, Kern::ThreadWrite(), when writing to the target
       
  1543     buffer.
       
  1544 */
       
  1545 EXPORT_C TInt DUsbClientController::GetConfigurationDescriptorSize(DThread* aThread, TDes8& aSize)
       
  1546     {
       
  1547     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetConfigurationDescriptorSize()"));
       
  1548     // We do not really enquire here....
       
  1549     const TPtrC8 size(reinterpret_cast<const TUint8*>(&KUsbDescSize_Config), sizeof(KUsbDescSize_Config));
       
  1550     return Kern::ThreadDesWrite(aThread, &aSize, size, 0);
       
  1551     }
       
  1552 
       
  1553 
       
  1554 /** Returns the current USB OTG descriptor.
       
  1555 
       
  1556     @param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
       
  1557     @param aOtgDesc A reference to a buffer into which the requested descriptor should be
       
  1558     written (most likely located user-side).
       
  1559 
       
  1560     @return KErrNotSupported or the return value of the thread write operation, Kern::ThreadDesWrite(),
       
  1561     when writing to the target buffer.
       
  1562 */
       
  1563 EXPORT_C TInt DUsbClientController::GetOtgDescriptor(DThread* aThread, TDes8& aOtgDesc) const
       
  1564     {
       
  1565     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetOtgDescriptor()"));
       
  1566     if (!iOtgSupport)
       
  1567         {
       
  1568         return KErrNotSupported;
       
  1569         }
       
  1570     return iDescriptors.GetOtgDescriptorTC(aThread, aOtgDesc);
       
  1571     }
       
  1572 
       
  1573 
       
  1574 /** Sets a new OTG descriptor.
       
  1575 
       
  1576     @param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
       
  1577     @param aOtgDesc A reference to a buffer which contains new OTG descriptor.
       
  1578 
       
  1579     @return KErrNotSupported or the return value of the thread read operation, Kern::ThreadDesRead().
       
  1580 */
       
  1581 EXPORT_C TInt DUsbClientController::SetOtgDescriptor(DThread* aThread, const TDesC8& aOtgDesc)
       
  1582     {
       
  1583     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetOtgDescriptor()"));
       
  1584     if (!iOtgSupport)
       
  1585         {
       
  1586         return KErrNotSupported;
       
  1587         }
       
  1588     TBuf8<KUsbDescSize_Otg> otg;
       
  1589     const TInt r = Kern::ThreadDesRead(aThread, &aOtgDesc, otg, 0);
       
  1590     if (r != KErrNone)
       
  1591         {
       
  1592         return r;
       
  1593         }
       
  1594     // Check descriptor validity
       
  1595     if (otg[0] != KUsbDescSize_Otg || otg[1] != KUsbDescType_Otg || otg[2] > 3)
       
  1596         {
       
  1597         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid OTG descriptor"));
       
  1598         return KErrGeneral;
       
  1599         }
       
  1600     __KTRACE_OPT(KUSB, Kern::Printf("  iOtgFuncMap before: 0x%x", iOtgFuncMap));
       
  1601     // Update value in controller as well
       
  1602     const TUint8 hnp = otg[2] & KUsbOtgAttr_HnpSupp;
       
  1603     const TUint8 srp = otg[2] & KUsbOtgAttr_SrpSupp;
       
  1604     if (hnp && !srp)
       
  1605         {
       
  1606         __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Invalid OTG attribute combination (HNP && !SRP"));
       
  1607         }
       
  1608     if (hnp && !(iOtgFuncMap & KUsbOtgAttr_HnpSupp))
       
  1609         {
       
  1610         __KTRACE_OPT(KUSB, Kern::Printf("  Setting attribute KUsbOtgAttr_HnpSupp"));
       
  1611         iOtgFuncMap |= KUsbOtgAttr_HnpSupp;
       
  1612         }
       
  1613     else if (!hnp && (iOtgFuncMap & KUsbOtgAttr_HnpSupp))
       
  1614         {
       
  1615         __KTRACE_OPT(KUSB, Kern::Printf("  Removing attribute KUsbOtgAttr_HnpSupp"));
       
  1616         iOtgFuncMap &= ~KUsbOtgAttr_HnpSupp;
       
  1617         }
       
  1618     if (srp && !(iOtgFuncMap & KUsbOtgAttr_SrpSupp))
       
  1619         {
       
  1620         __KTRACE_OPT(KUSB, Kern::Printf("  Setting attribute KUsbOtgAttr_SrpSupp"));
       
  1621         iOtgFuncMap |= KUsbOtgAttr_SrpSupp;
       
  1622         }
       
  1623     else if (!srp && (iOtgFuncMap & KUsbOtgAttr_SrpSupp))
       
  1624         {
       
  1625         __KTRACE_OPT(KUSB, Kern::Printf("  Removing attribute KUsbOtgAttr_SrpSupp"));
       
  1626         iOtgFuncMap &= ~KUsbOtgAttr_SrpSupp;
       
  1627         }
       
  1628     __KTRACE_OPT(KUSB, Kern::Printf("  iOtgFuncMap after:  0x%x", iOtgFuncMap));
       
  1629     return iDescriptors.SetOtgDescriptor(otg);
       
  1630     }
       
  1631 
       
  1632 
       
  1633 /** Returns current OTG features of USB device.
       
  1634 
       
  1635     @param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
       
  1636     @param aFeatures A reference to a buffer into which the requested OTG features should be written.
       
  1637 
       
  1638     @return KErrNotSupported or the return value of the thread write operation, Kern::ThreadDesWrite().
       
  1639 */
       
  1640 EXPORT_C TInt DUsbClientController::GetOtgFeatures(DThread* aThread, TDes8& aFeatures) const
       
  1641     {
       
  1642     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetOtgFeatures()"));
       
  1643     if (!iOtgSupport)
       
  1644         {
       
  1645         return KErrNotSupported;
       
  1646         }
       
  1647     TBuf8<1> features(1);
       
  1648     features[0] = iOtgFuncMap & 0x1C;
       
  1649     return Kern::ThreadDesWrite(aThread, &aFeatures, features, 0);
       
  1650     }
       
  1651 
       
  1652 
       
  1653 /** Returns current OTG features of USB device. This function is intended to be
       
  1654     called only from kernel side.
       
  1655 
       
  1656     @param aFeatures The reference to which the current features should be set at.
       
  1657     @return KErrNone if successful, KErrNotSupported if OTG is unavailable.
       
  1658 */
       
  1659 EXPORT_C TInt DUsbClientController::GetCurrentOtgFeatures(TUint8& aFeatures) const
       
  1660     {
       
  1661     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetCurrentOtgFeatures()"));
       
  1662     if (!iOtgSupport)
       
  1663         {
       
  1664         return KErrNotSupported;
       
  1665         }
       
  1666     aFeatures = iOtgFuncMap & 0x1C;
       
  1667     return KErrNone;
       
  1668     }
       
  1669 
       
  1670 
       
  1671 /** Registers client request for OTG feature change. Client is notified when any OTG
       
  1672     feature is changed.
       
  1673 
       
  1674     @see KUsbOtgAttr_B_HnpEnable, KUsbOtgAttr_A_HnpSupport, KUsbOtgAttr_A_AltHnpSupport
       
  1675 
       
  1676     @param aCallback Callback function. Gets called when OTG features change
       
  1677 
       
  1678     @return KErrNone if successful, KErrAlreadyExists if aCallback is already in the queue.
       
  1679 */
       
  1680 EXPORT_C TInt DUsbClientController::RegisterForOtgFeatureChange(TUsbcOtgFeatureCallback& aCallback)
       
  1681     {
       
  1682     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RegisterForOtgFeatureChange()"));
       
  1683     if (iOtgCallbacks.Elements() == KUsbcMaxListLength)
       
  1684         {
       
  1685         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Maximum list length reached: %d",
       
  1686                                           KUsbcMaxListLength));
       
  1687         return KErrGeneral;
       
  1688         }
       
  1689     if (IsInTheOtgFeatureList(aCallback))
       
  1690         {
       
  1691         __KTRACE_OPT(KUSB, Kern::Printf("  Error: OtgFeatureCallback @ 0x%x already registered", &aCallback));
       
  1692         return KErrAlreadyExists;
       
  1693         }
       
  1694     const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
       
  1695     iOtgCallbacks.AddLast(aCallback);
       
  1696     __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
       
  1697     return KErrNone;
       
  1698     }
       
  1699 
       
  1700 
       
  1701 /** De-registers (removes from the list of pending requests) a notification callback for
       
  1702     OTG feature change.
       
  1703 
       
  1704     @param aClientId A pointer to the LDD owning the endpoint status change callback.
       
  1705 
       
  1706     @return KErrNone if callback successfully unregistered, KErrNotFound if the callback couldn't be found.
       
  1707 */
       
  1708 EXPORT_C TInt DUsbClientController::DeRegisterForOtgFeatureChange(const DBase* aClientId)
       
  1709     {
       
  1710     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForOtgFeatureChange()"));
       
  1711     __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
       
  1712     const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
       
  1713     TSglQueIter<TUsbcOtgFeatureCallback> iter(iOtgCallbacks);
       
  1714     TUsbcOtgFeatureCallback* p;
       
  1715     while ((p = iter++) != NULL)
       
  1716         {
       
  1717         if (!aClientId || p->Owner() == aClientId)
       
  1718             {
       
  1719             __KTRACE_OPT(KUSB, Kern::Printf("  removing OtgFeatureCallback @ 0x%x", p));
       
  1720             iOtgCallbacks.Remove(*p);
       
  1721             __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
       
  1722             return KErrNone;
       
  1723             }
       
  1724         }
       
  1725     __KTRACE_OPT(KUSB, Kern::Printf("  client not found"));
       
  1726     __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
       
  1727     return KErrNotFound;
       
  1728     }
       
  1729 
       
  1730 
       
  1731 /** Returns a specific standard USB interface descriptor.
       
  1732 
       
  1733     @param aThread A pointer to the thread the LDD requesting the descriptor is running in.
       
  1734     @param aClientId A pointer to the LDD requesting the descriptor.
       
  1735     @param aSettingNum The setting number of the interface for which the descriptor is requested.
       
  1736     @param aInterfaceDescriptor A reference to a buffer into which the requested descriptor should be written
       
  1737     (most likely located user-side).
       
  1738 
       
  1739     @return KErrNotFound if the specified interface couldn't be found, otherwise the return value of the thread
       
  1740     write operation, Kern::ThreadWrite(), when writing to the target buffer.
       
  1741 */
       
  1742 EXPORT_C TInt DUsbClientController::GetInterfaceDescriptor(DThread* aThread, const DBase* aClientId,
       
  1743                                                            TInt aSettingNum, TDes8& aInterfaceDescriptor)
       
  1744     {
       
  1745     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetInterfaceDescriptor(x, 0x%08x, %d, y)",
       
  1746                                     aClientId, aSettingNum));
       
  1747     const TInt ifcset = ClientId2InterfaceNumber(aClientId);
       
  1748     if (ifcset < 0)
       
  1749         {
       
  1750         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
       
  1751         return KErrNotFound;
       
  1752         }
       
  1753     return iDescriptors.GetInterfaceDescriptorTC(aThread, aInterfaceDescriptor, ifcset, aSettingNum);
       
  1754     }
       
  1755 
       
  1756 
       
  1757 /** Sets a new standard USB interface descriptor.
       
  1758 
       
  1759     This function can also be used, by the user, and under certain conditions, to change an interface's number
       
  1760     (reported as bInterfaceNumber in the descriptor). The conditions are: 1) We cannot accept a number that is
       
  1761     already used by another interface, 2) We allow the interface number to be changed only when it's still the
       
  1762     only setting, and 3) We allow the interface number to be changed only for the default setting (0). (All
       
  1763     alternate settings created for that interface thereafter will inherit the new, changed number.)
       
  1764 
       
  1765     @param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
       
  1766     @param aClientId A pointer to the LDD requesting the setting of the descriptor.
       
  1767     @param aSettingNum The setting number of the interface for which the descriptor is to be set.
       
  1768     @param aInterfaceDescriptor A reference to a buffer which contains the descriptor to be set (most
       
  1769     likely located user-side).
       
  1770 
       
  1771     @return KErrNotFound if the specified interface couldn't be found, the return value of the thread read
       
  1772     operation, Kern::ThreadRead(), when reading from the source buffer in case of a failure, KErrArgument if the
       
  1773     interface  number is to be changed (via bInterfaceNumber in the descriptor) and either the requested
       
  1774     interface number is already used by another interface or the interface has more than one setting. KErrNone
       
  1775     if the new descriptor was successfully set.
       
  1776 */
       
  1777 EXPORT_C TInt DUsbClientController::SetInterfaceDescriptor(DThread* aThread, const DBase* aClientId,
       
  1778                                                            TInt aSettingNum, const TDes8& aInterfaceDescriptor)
       
  1779     {
       
  1780     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetInterfaceDescriptor(x, 0x%08x, %d, y)",
       
  1781                                     aClientId, aSettingNum));
       
  1782     const TInt ifcset = ClientId2InterfaceNumber(aClientId);
       
  1783     if (ifcset < 0)
       
  1784         {
       
  1785         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
       
  1786         return KErrNotFound;
       
  1787         }
       
  1788     TBuf8<KUsbDescSize_Interface> new_ifc;
       
  1789     TInt r = Kern::ThreadDesRead(aThread, &aInterfaceDescriptor, new_ifc, 0);
       
  1790     if (r != KErrNone)
       
  1791         {
       
  1792         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Copying interface descriptor buffer failed (%d)", r));
       
  1793         return r;
       
  1794         }
       
  1795     const TInt ifcset_new = new_ifc[2];
       
  1796     const TBool ifc_num_changes = (ifcset != ifcset_new);
       
  1797     TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(ifcset);
       
  1798     if (!ifcset_ptr)
       
  1799         {
       
  1800         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: interface number %d doesn't exist", ifcset));
       
  1801         return KErrNotFound;
       
  1802         }
       
  1803     if (ifc_num_changes)
       
  1804         {
       
  1805         // If the user wants to change the interface number, we need to do some sanity checks:
       
  1806         if (InterfaceExists(ifcset_new))
       
  1807             {
       
  1808             // Obviously we cannot accept a number that is already used by another interface.
       
  1809             __KTRACE_OPT(KPANIC, Kern::Printf("  Error: interface number %d already in use", ifcset_new));
       
  1810             return KErrArgument;
       
  1811             }
       
  1812         if (ifcset_ptr->iInterfaces.Count() > 1)
       
  1813             {
       
  1814             // We allow the interface number to be changed only when it's the only setting.
       
  1815             __KTRACE_OPT(KPANIC, Kern::Printf("  Error: interface has more than one alternate setting"));
       
  1816             return KErrArgument;
       
  1817             }
       
  1818         if (aSettingNum != 0)
       
  1819             {
       
  1820             // We allow the interface number to be changed only when it's the default setting.
       
  1821             __KTRACE_OPT(KPANIC, Kern::Printf("  Error: interface number can only be changed for setting 0"));
       
  1822             return KErrArgument;
       
  1823             }
       
  1824         }
       
  1825     if ((r = iDescriptors.SetInterfaceDescriptor(new_ifc, ifcset, aSettingNum)) != KErrNone)
       
  1826         {
       
  1827         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: iDescriptors.SetInterfaceDescriptorfailed"));
       
  1828         return r;
       
  1829         }
       
  1830     if (ifc_num_changes)
       
  1831         {
       
  1832         // Alright then, let's do it...
       
  1833         __KTRACE_OPT(KUSB, Kern::Printf("  about to change interface number from %d to %d",
       
  1834                                         ifcset, ifcset_new));
       
  1835         ifcset_ptr->iInterfaceNumber = ifcset_new;
       
  1836         }
       
  1837     return KErrNone;
       
  1838     }
       
  1839 
       
  1840 
       
  1841 /** Returns the size of a specific standard USB interface descriptor.
       
  1842 
       
  1843     @param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
       
  1844     @param aClientId A pointer to the LDD requesting the descriptor size.
       
  1845     @param aSettingNum The setting number of the interface for which the descriptor size is requested.
       
  1846     @param aSize A reference to a buffer into which the requested descriptor size should be written (most
       
  1847     likely located user-side).
       
  1848 
       
  1849     @return KErrNotFound if the specified interface couldn't be found, otherwise the return value of the thread
       
  1850     write operation, Kern::ThreadWrite(), when writing to the target buffer.
       
  1851 */
       
  1852 EXPORT_C TInt DUsbClientController::GetInterfaceDescriptorSize(DThread* aThread, const DBase* aClientId,
       
  1853                                                                TInt /*aSettingNum*/, TDes8& aSize)
       
  1854     {
       
  1855     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetInterfaceDescriptorSize()"));
       
  1856     const TInt ifcset = ClientId2InterfaceNumber(aClientId);
       
  1857     if (ifcset < 0)
       
  1858         {
       
  1859         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
       
  1860         return KErrNotFound;
       
  1861         }
       
  1862     // Actually, we do not really enquire here....
       
  1863     const TPtrC8 size(reinterpret_cast<const TUint8*>(&KUsbDescSize_Interface), sizeof(KUsbDescSize_Interface));
       
  1864     Kern::ThreadDesWrite(aThread, &aSize, size, 0);
       
  1865     return KErrNone;
       
  1866     }
       
  1867 
       
  1868 
       
  1869 /** Returns a specific standard USB endpoint descriptor.
       
  1870 
       
  1871     @param aThread A pointer to the thread the LDD requesting the descriptor is running in.
       
  1872     @param aClientId A pointer to the LDD requesting the descriptor.
       
  1873     @param aSettingNum The setting number of the interface that contains the endpoint for which the
       
  1874     descriptor is requested.
       
  1875     @param aEndpointNum The endpoint for which the descriptor is requested.
       
  1876     @param aEndpointDescriptor A reference to a buffer into which the requested descriptor should be written
       
  1877     (most likely located user-side).
       
  1878 
       
  1879     @return KErrNotFound if the specified interface or endpoint couldn't be found, otherwise the return value
       
  1880     of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
       
  1881 */
       
  1882 EXPORT_C TInt DUsbClientController::GetEndpointDescriptor(DThread* aThread, const DBase* aClientId,
       
  1883                                                           TInt aSettingNum, TInt aEndpointNum,
       
  1884                                                           TDes8& aEndpointDescriptor)
       
  1885     {
       
  1886     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetEndpointDescriptor(x, 0x%08x, %d, %d, y)",
       
  1887                                     aClientId, aSettingNum, aEndpointNum));
       
  1888     const TInt ifcset = ClientId2InterfaceNumber(aClientId);
       
  1889     if (ifcset < 0)
       
  1890         {
       
  1891         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
       
  1892         return KErrNotFound;
       
  1893         }
       
  1894     return iDescriptors.GetEndpointDescriptorTC(aThread, aEndpointDescriptor, ifcset,
       
  1895                                                 aSettingNum, EpIdx2Addr(aEndpointNum));
       
  1896     }
       
  1897 
       
  1898 
       
  1899 /** Sets a new standard USB endpoint descriptor.
       
  1900 
       
  1901     @param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
       
  1902     @param aClientId A pointer to the LDD requesting the setting of the descriptor.
       
  1903     @param aSettingNum The setting number of the interface that contains the endpoint for which the
       
  1904     descriptor is to be set.
       
  1905     @param aEndpointNum The endpoint for which the descriptor is to be set.
       
  1906     @param aEndpointDescriptor A reference to a buffer which contains the descriptor to be set (most
       
  1907     likely located user-side).
       
  1908 
       
  1909     @return KErrNotFound if the specified interface or endpoint couldn't be found, the return value of the
       
  1910     thread read operation, Kern::ThreadRead(), when reading from the source buffer in case of a read failure,
       
  1911     KErrNone if the new descriptor was successfully set.
       
  1912 */
       
  1913 EXPORT_C TInt DUsbClientController::SetEndpointDescriptor(DThread* aThread, const DBase* aClientId,
       
  1914                                                           TInt aSettingNum, TInt aEndpointNum,
       
  1915                                                           const TDes8& aEndpointDescriptor)
       
  1916     {
       
  1917     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetEndpointDescriptor(x, 0x%08x, %d, %d, y)",
       
  1918                                     aClientId, aSettingNum, aEndpointNum));
       
  1919     const TInt ifcset = ClientId2InterfaceNumber(aClientId);
       
  1920     if (ifcset < 0)
       
  1921         {
       
  1922         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
       
  1923         return KErrNotFound;
       
  1924         }
       
  1925     return iDescriptors.SetEndpointDescriptorTC(aThread, aEndpointDescriptor, ifcset,
       
  1926                                                 aSettingNum, EpIdx2Addr(aEndpointNum));
       
  1927     }
       
  1928 
       
  1929 
       
  1930 /** Returns the size of a specific standard USB endpoint descriptor.
       
  1931 
       
  1932     @param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
       
  1933     @param aClientId A pointer to the LDD requesting the descriptor size.
       
  1934     @param aSettingNum The setting number of the interface that contains the endpoint for which the
       
  1935     descriptor size is requested.
       
  1936     @param aEndpointNum The endpoint for which the descriptor size is requested.
       
  1937     @param aEndpointDescriptor A reference to a buffer into which the requested descriptor size should be
       
  1938     written (most likely located user-side).
       
  1939 
       
  1940     @return KErrNotFound if the specified interface or endpoint couldn't be found, otherwise the return value
       
  1941     of the thread write operation, kern::ThreadWrite(), when writing to the target buffer.
       
  1942 */
       
  1943 EXPORT_C TInt DUsbClientController::GetEndpointDescriptorSize(DThread* aThread, const DBase* aClientId,
       
  1944                                                               TInt aSettingNum, TInt aEndpointNum,
       
  1945                                                               TDes8& aSize)
       
  1946     {
       
  1947     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetEndpointDescriptorSize(x, 0x%08x, %d, %d, y)",
       
  1948                                     aClientId, aSettingNum, aEndpointNum));
       
  1949     const TInt ifcset = ClientId2InterfaceNumber(aClientId);
       
  1950     if (ifcset < 0)
       
  1951         {
       
  1952         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
       
  1953         return KErrNotFound;
       
  1954         }
       
  1955     TInt s;
       
  1956     TInt r = iDescriptors.GetEndpointDescriptorSize(ifcset, aSettingNum,
       
  1957                                                     EpIdx2Addr(aEndpointNum), s);
       
  1958     if (r == KErrNone)
       
  1959         {
       
  1960         TPtrC8 size(reinterpret_cast<const TUint8*>(&s), sizeof(s));
       
  1961         r = Kern::ThreadDesWrite(aThread, &aSize, size, 0);
       
  1962         }
       
  1963     else
       
  1964         {
       
  1965         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: endpoint descriptor not found"));
       
  1966         }
       
  1967     return r;
       
  1968     }
       
  1969 
       
  1970 
       
  1971 /** Returns the current Device_Qualifier descriptor. On a USB device which doesn't support high-speed
       
  1972     operation this function will return an error. Note that the contents of the descriptor depend on
       
  1973     the current device speed (full-speed or high-speed).
       
  1974 
       
  1975     @param aThread A pointer to the thread the LDD requesting the descriptor is running in.
       
  1976     @param aDeviceQualifierDescriptor A reference to a buffer into which the requested descriptor
       
  1977     should be written (most likely located user-side).
       
  1978 
       
  1979     @return KErrNotSupported if this descriptor is not supported, otherwise the return value of the thread
       
  1980     write operation, Kern::ThreadWrite(), when writing to the target buffer.
       
  1981 */
       
  1982 EXPORT_C TInt DUsbClientController::GetDeviceQualifierDescriptor(DThread* aThread,
       
  1983                                                                  TDes8& aDeviceQualifierDescriptor)
       
  1984     {
       
  1985     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetDeviceQualifierDescriptor()"));
       
  1986     return iDescriptors.GetDeviceQualifierDescriptorTC(aThread, aDeviceQualifierDescriptor);
       
  1987     }
       
  1988 
       
  1989 
       
  1990 /** Sets a new Device_Qualifier descriptor. On a USB device which doesn't support high-speed
       
  1991     operation this function will return an error. Note that the contents of the descriptor should take
       
  1992     into account the current device speed (full-speed or high-speed) as it is dependent on it.
       
  1993 
       
  1994     @param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
       
  1995     @param aDeviceQualifierDescriptor A reference to a buffer which contains the descriptor to be set (most
       
  1996     likely located user-side).
       
  1997 
       
  1998     @return KErrNotSupported if this descriptor is not supported, otherwise the return value of the thread
       
  1999     read operation, Kern::ThreadRead(), when reading from the source buffer in case of a failure, KErrNone if
       
  2000     the new descriptor was successfully set.
       
  2001 */
       
  2002 EXPORT_C TInt DUsbClientController::SetDeviceQualifierDescriptor(DThread* aThread,
       
  2003                                                                  const TDes8& aDeviceQualifierDescriptor)
       
  2004     {
       
  2005     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetDeviceQualifierDescriptor()"));
       
  2006     return iDescriptors.SetDeviceQualifierDescriptorTC(aThread, aDeviceQualifierDescriptor);
       
  2007     }
       
  2008 
       
  2009 
       
  2010 /** Returns the current Other_Speed_Configuration descriptor. On a USB device which doesn't support high-speed
       
  2011     operation this function will return an error. Note that the contents of the descriptor depend on the
       
  2012     current device speed (full-speed or high-speed).
       
  2013 
       
  2014     @param aThread A pointer to the thread the LDD requesting the descriptor is running in.
       
  2015     @param aConfigurationDescriptor A reference to a buffer into which the requested descriptor
       
  2016     should be written (most likely located user-side).
       
  2017 
       
  2018     @return KErrNotSupported if this descriptor is not supported, otherwise the return value of the thread
       
  2019     write operation, Kern::ThreadWrite(), when writing to the target buffer.
       
  2020 */
       
  2021 EXPORT_C TInt DUsbClientController::GetOtherSpeedConfigurationDescriptor(DThread* aThread,
       
  2022                                                                          TDes8& aConfigurationDescriptor)
       
  2023     {
       
  2024     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetOtherSpeedConfigurationDescriptor()"));
       
  2025     return iDescriptors.GetOtherSpeedConfigurationDescriptorTC(aThread, aConfigurationDescriptor);
       
  2026     }
       
  2027 
       
  2028 
       
  2029 /** Sets a new Other_Speed_Configuration descriptor. On a USB device which doesn't support high-speed
       
  2030     operation this function will return an error. Note that the contents of the descriptor should take
       
  2031     into account the current device speed (full-speed or high-speed) as it is dependent on it.
       
  2032 
       
  2033     @param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
       
  2034     @param aConfigurationDescriptor A reference to a buffer which contains the descriptor to be set (most
       
  2035     likely located user-side).
       
  2036 
       
  2037     @return KErrNotSupported if this descriptor is not supported, otherwise the return value of the thread
       
  2038     read operation, Kern::ThreadRead(), when reading from the source buffer in case of a failure, KErrNone if
       
  2039     the new descriptor was successfully set.
       
  2040 */
       
  2041 EXPORT_C TInt DUsbClientController::SetOtherSpeedConfigurationDescriptor(DThread* aThread,
       
  2042                                                                          const TDes8& aConfigurationDescriptor)
       
  2043     {
       
  2044     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetOtherSpeedConfigurationDescriptor()"));
       
  2045     return iDescriptors.SetOtherSpeedConfigurationDescriptorTC(aThread, aConfigurationDescriptor);
       
  2046     }
       
  2047 
       
  2048 
       
  2049 /** Returns a block of all available non-standard (class-specific) interface descriptors for a specific
       
  2050     interface.
       
  2051 
       
  2052     @param aThread A pointer to the thread the LDD requesting the descriptor block is running in.
       
  2053     @param aClientId A pointer to the LDD requesting the descriptor block.
       
  2054     @param aSettingNum The setting number of the interface for which the descriptor block is requested.
       
  2055     @param aInterfaceDescriptor A reference to a buffer into which the requested descriptor(s) should be
       
  2056     written (most likely located user-side).
       
  2057 
       
  2058     @return KErrNotFound if the specified interface couldn't be found, otherwise the return value of the thread
       
  2059     write operation, Kern::ThreadWrite(), when writing to the target buffer.
       
  2060 */
       
  2061 EXPORT_C TInt DUsbClientController::GetCSInterfaceDescriptorBlock(DThread* aThread, const DBase* aClientId,
       
  2062                                                                   TInt aSettingNum,
       
  2063                                                                   TDes8& aInterfaceDescriptor)
       
  2064     {
       
  2065     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetCSInterfaceDescriptorBlock(x, 0x%08x, %d, y)",
       
  2066                                     aClientId, aSettingNum));
       
  2067     const TInt ifcset = ClientId2InterfaceNumber(aClientId);
       
  2068     if (ifcset < 0)
       
  2069         {
       
  2070         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
       
  2071         return KErrNotFound;
       
  2072         }
       
  2073     return iDescriptors.GetCSInterfaceDescriptorTC(aThread, aInterfaceDescriptor, ifcset, aSettingNum);
       
  2074     }
       
  2075 
       
  2076 
       
  2077 /** Sets a block of (i.e. one or more) non-standard (class-specific) interface descriptors for a specific
       
  2078     interface.
       
  2079 
       
  2080     @param aThread A pointer to the thread the LDD requesting the setting of the descriptor block is running
       
  2081     in.
       
  2082     @param aClientId A pointer to the LDD requesting the setting of the descriptor block.
       
  2083     @param aSettingNum The setting number of the interface for which the setting of the descriptor block is
       
  2084     requested.
       
  2085     @param aInterfaceDescriptor A reference to a buffer which contains the descriptor block to be set (most
       
  2086     likely located user-side).
       
  2087     @param aSize The size of the descriptor block to be set.
       
  2088 
       
  2089     @return KErrNotFound if the specified interface couldn't be found, KErrArgument if aSize is less than 2,
       
  2090     KErrNoMemory if enough memory for the new descriptor(s) couldn't be allocated, otherwise the return value
       
  2091     of the thread read operation, Kern::ThreadRead(), when reading from the source buffer.
       
  2092 */
       
  2093 EXPORT_C TInt DUsbClientController::SetCSInterfaceDescriptorBlock(DThread* aThread, const DBase* aClientId,
       
  2094                                                                   TInt aSettingNum,
       
  2095                                                                   const TDes8& aInterfaceDescriptor, TInt aSize)
       
  2096     {
       
  2097     __KTRACE_OPT(KUSB,
       
  2098                  Kern::Printf("DUsbClientController::SetCSInterfaceDescriptorBlock(x, 0x%08x, %d, y, %d)",
       
  2099                               aClientId, aSettingNum, aSize));
       
  2100     const TInt ifcset = ClientId2InterfaceNumber(aClientId);
       
  2101     if (ifcset < 0)
       
  2102         {
       
  2103         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
       
  2104         return KErrNotFound;
       
  2105         }
       
  2106     if (aSize < 2)
       
  2107         {
       
  2108         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: aSize < 2 (%d)", aSize));
       
  2109         return KErrArgument;
       
  2110         }
       
  2111     return iDescriptors.SetCSInterfaceDescriptorTC(aThread, aInterfaceDescriptor, ifcset, aSettingNum, aSize);
       
  2112     }
       
  2113 
       
  2114 
       
  2115 /** Returns the total size all non-standard (class-specific) interface descriptors for a specific interface.
       
  2116 
       
  2117     @param aThread A pointer to the thread the LDD requesting the descriptor block size is running in.
       
  2118     @param aClientId A pointer to the LDD requesting the descriptor block size.
       
  2119     @param aSettingNum The setting number of the interface for which the descriptor block size is
       
  2120     requested.
       
  2121     @param aSize A reference to a buffer into which the requested descriptor block size should be written (most
       
  2122     likely located user-side).
       
  2123 
       
  2124     @return KErrNotFound if the specified interface couldn't be found, otherwise the return value of the thread
       
  2125     write operation, Kern::ThreadWrite(), when writing to the target buffer.
       
  2126 */
       
  2127 EXPORT_C TInt DUsbClientController::GetCSInterfaceDescriptorBlockSize(DThread* aThread, const DBase* aClientId,
       
  2128                                                                       TInt aSettingNum, TDes8& aSize)
       
  2129     {
       
  2130     __KTRACE_OPT(KUSB,
       
  2131                  Kern::Printf("DUsbClientController::GetCSInterfaceDescriptorBlockSize(x, 0x%08x, %d, y)",
       
  2132                               aClientId, aSettingNum));
       
  2133     const TInt ifcset = ClientId2InterfaceNumber(aClientId);
       
  2134     if (ifcset < 0)
       
  2135         {
       
  2136         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
       
  2137         return KErrNotFound;
       
  2138         }
       
  2139     TInt s;
       
  2140     const TInt r = iDescriptors.GetCSInterfaceDescriptorSize(ifcset, aSettingNum, s);
       
  2141     if (r == KErrNone)
       
  2142         {
       
  2143         const TPtrC8 size(reinterpret_cast<const TUint8*>(&s), sizeof(s));
       
  2144         Kern::ThreadDesWrite(aThread, &aSize, size, 0);
       
  2145         }
       
  2146     else
       
  2147         {
       
  2148         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: cs interface descriptor not found"));
       
  2149         }
       
  2150     return r;
       
  2151     }
       
  2152 
       
  2153 
       
  2154 /** Returns a block of all available non-standard (class-specific) endpoint descriptors for a specific endpoint.
       
  2155 
       
  2156     @param aThread A pointer to the thread the LDD requesting the descriptor block is running in.
       
  2157     @param aClientId A pointer to the LDD requesting the descriptor block.
       
  2158     @param aSettingNum The setting number of the interface that contains the endpoint for which the
       
  2159     descriptor block is requested.
       
  2160     @param aEndpointNum The endpoint for which the descriptor block is requested.
       
  2161     @param aEndpointDescriptor A reference to a buffer into which the requested descriptor(s) should be written
       
  2162     (most likely located user-side).
       
  2163 
       
  2164     @return KErrNotFound if the specified interface or endpoint couldn't be found, otherwise the return value
       
  2165     of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
       
  2166 */
       
  2167 EXPORT_C TInt DUsbClientController::GetCSEndpointDescriptorBlock(DThread* aThread, const DBase* aClientId,
       
  2168                                                                  TInt aSettingNum, TInt aEndpointNum,
       
  2169                                                                  TDes8& aEndpointDescriptor)
       
  2170     {
       
  2171     __KTRACE_OPT(KUSB,
       
  2172                  Kern::Printf("DUsbClientController::GetCSEndpointDescriptorBlock(x, 0x%08x, %d, %d, y)",
       
  2173                               aClientId, aSettingNum, aEndpointNum));
       
  2174     const TInt ifcset = ClientId2InterfaceNumber(aClientId);
       
  2175     if (ifcset < 0)
       
  2176         {
       
  2177         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
       
  2178         return KErrNotFound;
       
  2179         }
       
  2180     return iDescriptors.GetCSEndpointDescriptorTC(aThread, aEndpointDescriptor, ifcset,
       
  2181                                                   aSettingNum, EpIdx2Addr(aEndpointNum));
       
  2182     }
       
  2183 
       
  2184 
       
  2185 /** Sets a block of (i.e. one or more) non-standard (class-specific) endpoint descriptors for a specific
       
  2186     endpoint.
       
  2187 
       
  2188     @param aThread A pointer to the thread the LDD requesting the setting of the descriptor block is running
       
  2189     in.
       
  2190     @param aClientId A pointer to the LDD requesting the setting of the descriptor block.
       
  2191     @param aSettingNum The setting number of the interface that contains the endpoint for which the
       
  2192     descriptor block is to be set.
       
  2193     @param aEndpointNum The endpoint for which the descriptor block is to be set.
       
  2194     @param aEndpointDescriptor A reference to a buffer which contains the descriptor block to be set (most
       
  2195     likely located user-side).
       
  2196     @param aSize The size of the descriptor block to be set.
       
  2197 
       
  2198     @return KErrNotFound if the specified interface or endpoint couldn't be found, KErrArgument if aSize is
       
  2199     less than 2, KErrNoMemory if enough memory for the new descriptor(s) couldn't be allocated, otherwise the
       
  2200     return value of the thread read operation, Kern::ThreadRead(), when reading from the source buffer.
       
  2201 */
       
  2202 EXPORT_C TInt DUsbClientController::SetCSEndpointDescriptorBlock(DThread* aThread, const DBase* aClientId,
       
  2203                                                                  TInt aSettingNum, TInt aEndpointNum,
       
  2204                                                                  const TDes8& aEndpointDescriptor, TInt aSize)
       
  2205     {
       
  2206     __KTRACE_OPT(KUSB,
       
  2207                  Kern::Printf("DUsbClientController::SetCSEndpointDescriptorBlock(x, 0x%08x, %d, %d, y)",
       
  2208                               aClientId, aSettingNum, aEndpointNum));
       
  2209     const TInt ifcset = ClientId2InterfaceNumber(aClientId);
       
  2210     if (ifcset < 0)
       
  2211         {
       
  2212         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
       
  2213         return KErrNotFound;
       
  2214         }
       
  2215     if (aSize < 2)
       
  2216         {
       
  2217         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: aSize < 2 (%d)", aSize));
       
  2218         return KErrArgument;
       
  2219         }
       
  2220     return iDescriptors.SetCSEndpointDescriptorTC(aThread, aEndpointDescriptor, ifcset,
       
  2221                                                   aSettingNum, EpIdx2Addr(aEndpointNum), aSize);
       
  2222     }
       
  2223 
       
  2224 
       
  2225 /** Returns the total size all non-standard (class-specific) endpoint descriptors for a specific endpoint.
       
  2226 
       
  2227     @param aThread A pointer to the thread the LDD requesting the descriptor block size is running in.
       
  2228     @param aClientId A pointer to the LDD requesting the descriptor block size.
       
  2229     @param aSettingNum The setting number of the interface for which the descriptor block size is
       
  2230     requested.
       
  2231     @param aEndpointNum The endpoint for which the descriptor block size is requested.
       
  2232     @param aSize A reference to a buffer into which the requested descriptor block size should be written (most
       
  2233     likely located user-side).
       
  2234 
       
  2235     @return KErrNotFound if the specified interface or endpoint couldn't be found, otherwise the return value
       
  2236     of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
       
  2237 */
       
  2238 EXPORT_C TInt DUsbClientController::GetCSEndpointDescriptorBlockSize(DThread* aThread, const DBase* aClientId,
       
  2239                                                                      TInt aSettingNum, TInt aEndpointNum,
       
  2240                                                                      TDes8& aSize)
       
  2241     {
       
  2242     __KTRACE_OPT(KUSB,
       
  2243                  Kern::Printf("DUsbClientController::GetCSEndpointDescriptorBlockSize(x, 0x%08x, %d, %d, y)",
       
  2244                               aClientId, aSettingNum, aEndpointNum));
       
  2245     const TInt ifcset = ClientId2InterfaceNumber(aClientId);
       
  2246     if (ifcset < 0)
       
  2247         {
       
  2248         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
       
  2249         return KErrNotFound;
       
  2250         }
       
  2251     TInt s;
       
  2252     const TInt r = iDescriptors.GetCSEndpointDescriptorSize(ifcset, aSettingNum,
       
  2253                                                             EpIdx2Addr(aEndpointNum), s);
       
  2254     if (r == KErrNone)
       
  2255         {
       
  2256         const TPtrC8 size(reinterpret_cast<const TUint8*>(&s), sizeof(s));
       
  2257         Kern::ThreadDesWrite(aThread, &aSize, size, 0);
       
  2258         }
       
  2259     else
       
  2260         {
       
  2261         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: cs endpoint descriptor not found"));
       
  2262         }
       
  2263     return r;
       
  2264     }
       
  2265 
       
  2266 
       
  2267 /** Returns the currently set string descriptor language ID (LANGID) code.
       
  2268 
       
  2269     @param aThread A pointer to the thread the LDD requesting the LANGID is running in.
       
  2270     @param aLangId A reference to a buffer into which the requested code should be written (most likely
       
  2271     located user-side).
       
  2272 
       
  2273     @return The return value of the thread write operation, Kern::ThreadDesWrite(),
       
  2274     when writing to the target buffer.
       
  2275 */
       
  2276 EXPORT_C TInt DUsbClientController::GetStringDescriptorLangId(DThread* aThread, TDes8& aLangId)
       
  2277     {
       
  2278     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetStringDescriptorLangId()"));
       
  2279     return iDescriptors.GetStringDescriptorLangIdTC(aThread, aLangId);
       
  2280     }
       
  2281 
       
  2282 
       
  2283 /** Sets the string descriptor language ID (LANGID) code.
       
  2284 
       
  2285     @param aLangId The langauge ID code to be written.
       
  2286 
       
  2287     @return KErrNone.
       
  2288 */
       
  2289 EXPORT_C TInt DUsbClientController::SetStringDescriptorLangId(TUint16 aLangId)
       
  2290     {
       
  2291     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetStringDescriptorLangId()"));
       
  2292     return iDescriptors.SetStringDescriptorLangId(aLangId);
       
  2293     }
       
  2294 
       
  2295 
       
  2296 /** Returns the currently set Manufacturer string (which is referenced by the iManufacturer field in the device
       
  2297     descriptor).
       
  2298 
       
  2299     (Thus, the function should actually be called either 'GetManufacturerString'
       
  2300     or 'GetManufacturerStringDescriptorString'.)
       
  2301 
       
  2302     @param aThread A pointer to the thread the LDD requesting the string is running in.
       
  2303     @param aString A reference to a buffer into which the requested string should be written (most likely
       
  2304     located user-side).
       
  2305 
       
  2306     @return KErrNotFound if the string descriptor couldn't be found (PIL internal error), otherwise the return
       
  2307     value of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
       
  2308 */
       
  2309 EXPORT_C TInt DUsbClientController::GetManufacturerStringDescriptor(DThread* aThread, TDes8& aString)
       
  2310     {
       
  2311     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetManufacturerStringDescriptor()"));
       
  2312     return iDescriptors.GetManufacturerStringDescriptorTC(aThread, aString);
       
  2313     }
       
  2314 
       
  2315 
       
  2316 /** Sets a new Manufacturer string in the Manufacturer string descriptor (which is referenced by the
       
  2317     iManufacturer field in the device descriptor).
       
  2318 
       
  2319     (Thus, the function should actually be called either
       
  2320     'SetManufacturerString' or 'SetManufacturerStringDescriptorString'.)
       
  2321 
       
  2322     @param aThread A pointer to the thread the LDD requesting the setting of the string is running in.
       
  2323     @param aString A reference to a buffer which contains the string to be set (most likely located
       
  2324     user-side).
       
  2325 
       
  2326     @return KErrNoMemory if not enough memory for the new descriptor or the string could be allocated, the
       
  2327     return value of the thread read operation, Kern::ThreadRead(), if reading from the source buffer goes wrong,
       
  2328     KErrNone if new string descriptor successfully set.
       
  2329 */
       
  2330 EXPORT_C TInt DUsbClientController::SetManufacturerStringDescriptor(DThread* aThread, const TDes8& aString)
       
  2331     {
       
  2332     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetManufacturerStringDescriptor()"));
       
  2333     return iDescriptors.SetManufacturerStringDescriptorTC(aThread, aString);
       
  2334     }
       
  2335 
       
  2336 
       
  2337 /** Removes (deletes) the Manufacturer string descriptor (which is referenced by the
       
  2338     iManufacturer field in the device descriptor).
       
  2339 
       
  2340     @return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found
       
  2341 */
       
  2342 EXPORT_C TInt DUsbClientController::RemoveManufacturerStringDescriptor()
       
  2343     {
       
  2344     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RemoveManufacturerStringDescriptor()"));
       
  2345     return iDescriptors.RemoveManufacturerStringDescriptor();
       
  2346     }
       
  2347 
       
  2348 
       
  2349 /** Returns the currently set Product string (which is referenced by the iProduct field in the device
       
  2350     descriptor).
       
  2351 
       
  2352     (Thus, the function should actually be called either 'GetProductString' or
       
  2353     'GetProductStringDescriptorString'.)
       
  2354 
       
  2355     @param aThread A pointer to the thread the LDD requesting the string is running in.
       
  2356     @param aString A reference to a buffer into which the requested string should be written (most likely
       
  2357     located user-side).
       
  2358 
       
  2359     @return KErrNotFound if the string descriptor couldn't be found (PIL internal error), otherwise the return
       
  2360     value of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
       
  2361 */
       
  2362 EXPORT_C TInt DUsbClientController::GetProductStringDescriptor(DThread* aThread, TDes8& aString)
       
  2363     {
       
  2364     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetProductStringDescriptor()"));
       
  2365     return iDescriptors.GetProductStringDescriptorTC(aThread, aString);
       
  2366     }
       
  2367 
       
  2368 
       
  2369 /** Sets a new Product string in the Product string descriptor (which is referenced by the iProduct field in
       
  2370     the device descriptor).
       
  2371 
       
  2372     (Thus, the function should actually be called either 'SetProductString' or
       
  2373     'SetProductStringDescriptorString'.)
       
  2374 
       
  2375     @param aThread A pointer to the thread the LDD requesting the setting of the string is running in.
       
  2376     @param aString A reference to a buffer which contains the string to be set (most likely located
       
  2377     user-side).
       
  2378 
       
  2379     @return KErrNoMemory if not enough memory for the new descriptor or the string could be allocated, the
       
  2380     return value of the thread read operation, Kern::ThreadRead(), if reading from the source buffer goes wrong,
       
  2381     KErrNone if new string descriptor successfully set.
       
  2382 */
       
  2383 EXPORT_C TInt DUsbClientController::SetProductStringDescriptor(DThread* aThread, const TDes8& aString)
       
  2384     {
       
  2385     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetProductStringDescriptor()"));
       
  2386     return iDescriptors.SetProductStringDescriptorTC(aThread, aString);
       
  2387     }
       
  2388 
       
  2389 
       
  2390 /** Removes (deletes) the Product string descriptor (which is referenced by the
       
  2391     iProduct field in the device descriptor).
       
  2392 
       
  2393     @return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found
       
  2394 */
       
  2395 EXPORT_C TInt DUsbClientController::RemoveProductStringDescriptor()
       
  2396     {
       
  2397     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RemoveProductStringDescriptor()"));
       
  2398     return iDescriptors.RemoveProductStringDescriptor();
       
  2399     }
       
  2400 
       
  2401 
       
  2402 /** Returns the currently set SerialNumber string (which is referenced by the iSerialNumber field in the device
       
  2403     descriptor).
       
  2404 
       
  2405     (Thus, the function should actually be called either 'GetSerialNumberString' or
       
  2406     'GetSerialNumberStringDescriptorString'.)
       
  2407 
       
  2408     @param aThread A pointer to the thread the LDD requesting the string is running in.
       
  2409     @param aString A reference to a buffer into which the requested string should be written (most likely
       
  2410     located user-side).
       
  2411 
       
  2412     @return KErrNotFound if the string descriptor couldn't be found (PIL internal error), otherwise the return
       
  2413     value of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
       
  2414 */
       
  2415 EXPORT_C TInt DUsbClientController::GetSerialNumberStringDescriptor(DThread* aThread, TDes8& aString)
       
  2416     {
       
  2417     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetSerialNumberStringDescriptor()"));
       
  2418     return iDescriptors.GetSerialNumberStringDescriptorTC(aThread, aString);
       
  2419     }
       
  2420 
       
  2421 
       
  2422 /** Sets a new SerialNumber string in the SerialNumber string descriptor (which is referenced by the
       
  2423     iSerialNumber field in the device descriptor).
       
  2424 
       
  2425     (Thus, the function should actually be called either
       
  2426     'SetSerialNumberString' or 'SetSerialNumberStringDescriptorString'.)
       
  2427 
       
  2428     @param aThread A pointer to the thread the LDD requesting the setting of the string is running in.
       
  2429     @param aString A reference to a buffer which contains the string to be set (most likely located
       
  2430     user-side).
       
  2431 
       
  2432     @return KErrNoMemory if not enough memory for the new descriptor or the string could be allocated, the
       
  2433     return value of the thread read operation, Kern::ThreadRead(), if reading from the source buffer goes wrong,
       
  2434     KErrNone if new string descriptor successfully set.
       
  2435 */
       
  2436 EXPORT_C TInt DUsbClientController::SetSerialNumberStringDescriptor(DThread* aThread, const TDes8& aString)
       
  2437     {
       
  2438     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetSerialNumberStringDescriptor()"));
       
  2439     return iDescriptors.SetSerialNumberStringDescriptorTC(aThread, aString);
       
  2440     }
       
  2441 
       
  2442 
       
  2443 /** Removes (deletes) the Serial Number string descriptor (which is referenced by the
       
  2444     iSerialNumber field in the device descriptor).
       
  2445 
       
  2446     @return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found
       
  2447 */
       
  2448 EXPORT_C TInt DUsbClientController::RemoveSerialNumberStringDescriptor()
       
  2449     {
       
  2450     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RemoveSerialNumberStringDescriptor()"));
       
  2451     return iDescriptors.RemoveSerialNumberStringDescriptor();
       
  2452     }
       
  2453 
       
  2454 
       
  2455 /** Returns the currently set Configuration string (which is referenced by the iConfiguration field in the
       
  2456     configuration descriptor).
       
  2457 
       
  2458     (Thus, the function should actually be called either 'GetConfigurationString' or
       
  2459     'GetConfigurationStringDescriptorString'.)
       
  2460 
       
  2461     @param aThread A pointer to the thread the LDD requesting the string is running in.
       
  2462     @param aString A reference to a buffer into which the requested string should be written (most likely
       
  2463     located user-side).
       
  2464 
       
  2465     @return KErrNotFound if the string descriptor couldn't be found (PIL internal error), otherwise the return
       
  2466     value of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
       
  2467 */
       
  2468 EXPORT_C TInt DUsbClientController::GetConfigurationStringDescriptor(DThread* aThread, TDes8& aString)
       
  2469     {
       
  2470     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetConfigurationStringDescriptor()"));
       
  2471     return iDescriptors.GetConfigurationStringDescriptorTC(aThread, aString);
       
  2472     }
       
  2473 
       
  2474 
       
  2475 /** Sets a new Configuration string in the Configuration string descriptor (which is referenced by the
       
  2476     iConfiguration field in the configuration descriptor).
       
  2477 
       
  2478     (Thus, the function should actually be called either
       
  2479     'SetConfigurationString' or 'SetConfigurationStringDescriptorString'.)
       
  2480 
       
  2481     @param aThread A pointer to the thread the LDD requesting the setting of the string is running in.
       
  2482     @param aString A reference to a buffer which contains the string to be set (most likely located
       
  2483     user-side).
       
  2484 
       
  2485     @return KErrNoMemory if not enough memory for the new descriptor or the string could be allocated, the
       
  2486     return value of the thread read operation, Kern::ThreadRead(), if reading from the source buffer goes wrong,
       
  2487     KErrNone if new string descriptor successfully set.
       
  2488 */
       
  2489 EXPORT_C TInt DUsbClientController::SetConfigurationStringDescriptor(DThread* aThread, const TDes8& aString)
       
  2490     {
       
  2491     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetConfigurationStringDescriptor()"));
       
  2492     return iDescriptors.SetConfigurationStringDescriptorTC(aThread, aString);
       
  2493     }
       
  2494 
       
  2495 
       
  2496 /** Removes (deletes) the Configuration string descriptor (which is referenced by the
       
  2497     iConfiguration field in the configuration descriptor).
       
  2498 
       
  2499     @return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found.
       
  2500 */
       
  2501 EXPORT_C TInt DUsbClientController::RemoveConfigurationStringDescriptor()
       
  2502     {
       
  2503     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RemoveConfigurationStringDescriptor()"));
       
  2504     return iDescriptors.RemoveConfigurationStringDescriptor();
       
  2505     }
       
  2506 
       
  2507 
       
  2508 /** Copies the string descriptor at the specified index in the string descriptor array into
       
  2509     the aString argument.
       
  2510 
       
  2511     @param aIndex The position of the string descriptor in the string descriptor array.
       
  2512     @param aThread A pointer to the thread the LDD requesting the string is running in.
       
  2513     @param aString A reference to a buffer into which the requested string should be written (most likely
       
  2514     located user-side).
       
  2515 
       
  2516     @return KErrNone if successful, KErrNotFound if no string descriptor exists at the specified index, or the
       
  2517     return value of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
       
  2518 */
       
  2519 EXPORT_C TInt DUsbClientController::GetStringDescriptor(DThread* aThread, TUint8 aIndex, TDes8& aString)
       
  2520     {
       
  2521     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetStringDescriptor(%d)", aIndex));
       
  2522     return iDescriptors.GetStringDescriptorTC(aThread, aIndex, aString);
       
  2523     }
       
  2524 
       
  2525 
       
  2526 /** Sets the aString argument to be a string descriptor at the specified index in the string
       
  2527     descriptor array. If a string descriptor already exists at that position then it will be replaced.
       
  2528 
       
  2529     @param aIndex The position of the string descriptor in the string descriptor array.
       
  2530     @param aThread A pointer to the thread the LDD requesting the setting of the string is running in.
       
  2531     @param aString A reference to a buffer which contains the string to be set (most likely located
       
  2532     user-side).
       
  2533 
       
  2534     @return KErrNone if successful, KErrArgument if aIndex is invalid, KErrNoMemory if no memory is available
       
  2535     to store the new string (an existing descriptor at that index will be preserved), or the return value of
       
  2536     the thread read operation, Kern::ThreadRead(), if reading from the source buffer goes wrong.
       
  2537 */
       
  2538 EXPORT_C TInt DUsbClientController::SetStringDescriptor(DThread* aThread, TUint8 aIndex, const TDes8& aString)
       
  2539     {
       
  2540     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetStringDescriptor(%d)", aIndex));
       
  2541     return iDescriptors.SetStringDescriptorTC(aThread, aIndex, aString);
       
  2542     }
       
  2543 
       
  2544 
       
  2545 /** Removes (deletes) the string descriptor at the specified index in the string descriptor array.
       
  2546 
       
  2547     @param aIndex The position of the string descriptor in the string descriptor array.
       
  2548 
       
  2549     @return KErrNone if successful, KErrNotFound if no string descriptor exists at the specified index.
       
  2550 */
       
  2551 EXPORT_C TInt DUsbClientController::RemoveStringDescriptor(TUint8 aIndex)
       
  2552     {
       
  2553     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RemoveStringDescriptor(%d)", aIndex));
       
  2554     return iDescriptors.RemoveStringDescriptor(aIndex);
       
  2555     }
       
  2556 
       
  2557 
       
  2558 /** Queries the use of and endpoint resource.
       
  2559 
       
  2560     If the resource gets successfully allocated, it will be used from when the current bus transfer
       
  2561     has been completed.
       
  2562 
       
  2563     @param aClientId A pointer to the LDD querying the endpoint resource.
       
  2564     @param aEndpointNum The number of the endpoint.
       
  2565     @param aResource The endpoint resource to be queried.
       
  2566 
       
  2567     @return ETrue if the specified resource is in use at the endpoint, EFalse if not or if there was any error
       
  2568     during the execution of the function.
       
  2569 */
       
  2570 EXPORT_C TBool DUsbClientController::QueryEndpointResource(const DBase* /*aClientId*/, TInt aEndpointNum,
       
  2571                                                            TUsbcEndpointResource aResource)
       
  2572     {
       
  2573     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::QueryEndpointResource()"));
       
  2574     return iController.QueryEndpointResource(aEndpointNum, aResource);
       
  2575     }
       
  2576 
       
  2577 
       
  2578 EXPORT_C TInt DUsbClientController::EndpointPacketSize(const DBase* aClientId, TInt aEndpointNum)
       
  2579     {
       
  2580     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EndpointPacketSize(0x%08x, %d)",
       
  2581                                     aClientId, aEndpointNum));
       
  2582 
       
  2583     const TUsbcInterfaceSet* const ifcset_ptr = ClientId2InterfacePointer(aClientId);
       
  2584     if (!ifcset_ptr)
       
  2585         {
       
  2586         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: interface or clientid not found"));
       
  2587         return -1;
       
  2588         }
       
  2589     const TUsbcInterface* const ifc_ptr = ifcset_ptr->iInterfaces[ifcset_ptr->iCurrentInterface];
       
  2590     const RPointerArray<TUsbcLogicalEndpoint>& ep_array = ifc_ptr->iEndpoints;
       
  2591     const TInt n = ep_array.Count();
       
  2592     for (TInt i = 0; i < n; i++)
       
  2593         {
       
  2594         const TUsbcLogicalEndpoint* const ep = ep_array[i];
       
  2595         if (EpAddr2Idx(ep->iPEndpoint->iEndpointAddr) == static_cast<TUint>(aEndpointNum))
       
  2596             {
       
  2597             __KTRACE_OPT(KUSB, Kern::Printf("  Endpoint packet sizes: FS = %d  HS = %d",
       
  2598                                             ep->iEpSize_Fs, ep->iEpSize_Hs));
       
  2599             const TInt size = iHighSpeed ? ep->iEpSize_Hs : ep->iEpSize_Fs;
       
  2600             __KTRACE_OPT(KUSB, Kern::Printf("  Returning %d", size));
       
  2601             return size;
       
  2602             }
       
  2603         }
       
  2604     __KTRACE_OPT(KPANIC, Kern::Printf("  Error: endpoint not found"));
       
  2605     return -1;
       
  2606     }
       
  2607     
       
  2608 EXPORT_C TDfcQue*  DUsbClientController::DfcQ(TInt /*aIndex*/)
       
  2609     {
       
  2610     return iControllerProperties.iDfcQueue;
       
  2611     }
       
  2612     
       
  2613 EXPORT_C void DUsbClientController::DumpRegisters()
       
  2614     {
       
  2615     return;
       
  2616     }
       
  2617     
       
  2618 EXPORT_C TInt DUsbClientController::SignalRemoteWakeup()
       
  2619     {
       
  2620     return iController.SignalRemoteWakeup();
       
  2621     }
       
  2622     
       
  2623 EXPORT_C TBool DUsbClientController::CurrentlyUsingHighSpeed()
       
  2624     {
       
  2625     UsbShai::TSpeed speed = iController.DeviceOperatingSpeed();
       
  2626     
       
  2627     return (speed == UsbShai::EHighSpeed)?ETrue:EFalse;
       
  2628     }
       
  2629 
       
  2630 //
       
  2631 // === USB Controller member function implementations - PSL API (public) ===========================
       
  2632 //
       
  2633 
       
  2634 /** Gets called by the PSL to register a newly created derived class controller object.
       
  2635 
       
  2636     @param aUdc The number of the new UDC. It should be 0 for the first (or only) UDC in the system, 1 for the
       
  2637     second one, and so forth. KUsbcMaxUdcs determines how many UDCs are supported.
       
  2638 
       
  2639     @return A pointer to the controller if successfully registered, NULL if aUdc out of (static) range.
       
  2640 
       
  2641     @publishedPartner @released
       
  2642 */
       
  2643 TInt DUsbClientController::RegisterUdc(TInt aUdc)
       
  2644     {
       
  2645     TInt err = KErrNone;
       
  2646     
       
  2647     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RegisterUdc()"));
       
  2648     
       
  2649     if (aUdc < 0 || aUdc > (KUsbcMaxUdcs - 1))
       
  2650         {
       
  2651         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: aUdc out of range (%d)", aUdc));
       
  2652         return KErrInUse;
       
  2653         }
       
  2654     else
       
  2655         {
       
  2656         UsbClientController[aUdc] = this;
       
  2657         }
       
  2658         
       
  2659     return err;
       
  2660     }
       
  2661 
       
  2662 
       
  2663 //
       
  2664 // === USB Controller member function implementations - PSL API (protected) ========================
       
  2665 //
       
  2666 
       
  2667 /** Initialises an instance of this class, which is the base class of the derived class (= PSL, which is
       
  2668     supposed to call this function).
       
  2669 
       
  2670     It does the following things:
       
  2671 
       
  2672     - disconnects the UDC from the bus,
       
  2673     - initialises the USB descriptor pool, uses data from the PSL (see function argument list)
       
  2674     - creates and initialises the basic USB device configuration
       
  2675     - initialises the array of physical endpoints
       
  2676     - initialises Ep0 structures (but doesn't configure & enable Ep0 yet)
       
  2677     - creates and installs the USB power handler
       
  2678 
       
  2679     @param aDeviceDesc A pointer to a valid standard USB device descriptor or NULL. The values initially
       
  2680     required in the descriptor follow from its constructor. The descriptor is not copied over, but rather this
       
  2681     pointer is queued directly into the descriptor pool. Must be writable memory.
       
  2682 
       
  2683     @param aConfigDesc A pointer to a valid standard USB configuration descriptor or NULL. The values
       
  2684     initially required in the descriptor follow from its constructor. The descriptor is not copied over, but
       
  2685     rather this pointer is queued directly into the descriptor pool. Must be writable memory.
       
  2686 
       
  2687     @param aLangId A pointer to a valid USB language ID (string) descriptor. The values initially required in
       
  2688     the descriptor follow from its constructor. The descriptor is not copied over, but rather this pointer is
       
  2689     queued directly into the descriptor pool. Must be writable memory. Other than the remaining four string
       
  2690     descriptors, this one is not optional. The reason is that the USB spec mandates a LangId descriptor as
       
  2691     soon as a single string descriptor gets returned by the device. So, even though the device might omit the
       
  2692     Manufacturer, Product, SerialNumber, and Configuration string descriptors, it is at this point not known
       
  2693     whether there will be any Interface string descriptors. Since any USB API user can create an interface
       
  2694     with an Interface string descriptor, we have to insist here on the provision of a LangId string
       
  2695     descriptor. (The PIL decides at run-time whether or not to return the LangId string descriptor to the
       
  2696     host, depending on whether there exist any string descriptors at that time.)
       
  2697 
       
  2698     @param aManufacturer A pointer to a valid USB string descriptor or NULL. The values initially required in
       
  2699     the descriptor follow from its constructor. The descriptor is not copied over, but rather this pointer is
       
  2700     queued directly into the descriptor pool. Must be writable memory. This descriptor will be referenced by
       
  2701     the iManufacturer field in the device descriptor.
       
  2702 
       
  2703     @param aProduct A pointer to a valid USB string descriptor or NULL. The values initially required in the
       
  2704     descriptor follow from its constructor. The descriptor is not copied over, but rather this pointer is
       
  2705     queued directly into the descriptor pool. Must be writable memory. This descriptor will be referenced by
       
  2706     the iProduct field in the device descriptor.
       
  2707 
       
  2708     @param aSerialNum A pointer to a valid USB string descriptor or NULL. The values initially required in the
       
  2709     descriptor follow from its constructor. The descriptor is not copied over, but rather this pointer is
       
  2710     queued directly into the descriptor pool. Must be writable memory. This descriptor will be referenced by
       
  2711     the iSerialNumber field in the device descriptor.
       
  2712 
       
  2713     @param aConfig A pointer to a valid USB string descriptor or NULL. The values initially required in the
       
  2714     descriptor follow from its constructor. The descriptor is not copied over, but rather this pointer is
       
  2715     queued directly into the descriptor pool. Must be writable memory. This descriptor will be referenced by
       
  2716     the iConfiguration field in the configuration descriptor.
       
  2717 
       
  2718     @param aOtgDesc A pointer to a valid USB OTG descriptor (if OTG is supported by this device and is to be
       
  2719     supported by the driver) or NULL. The values initially required in the descriptor follow from its
       
  2720     constructor. The descriptor is not copied over, but rather this pointer is queued directly into the
       
  2721     descriptor pool. Must be writable memory.
       
  2722 
       
  2723     @return EFalse, if USB descriptor pool initialisation fails, or if configuration creation fails, or if the
       
  2724     PSL reports more endpoints than the constant KUsbcMaxEndpoints permits, or if the Ep0 logical endpoint
       
  2725     creation fails, or if the creation of the power handler fails; ETrue, if base class object successfully
       
  2726     initialised.
       
  2727 
       
  2728     @publishedPartner @released
       
  2729 */
       
  2730 TBool DUsbClientController::Initialise(TUsbPeripheralDescriptorPool& aDescPool,
       
  2731                                        const UsbShai::TUsbPeripheralEndpointCaps* aEndpointCaps,
       
  2732                                        TInt aTotalEndpoints)
       
  2733     {
       
  2734     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::InitialiseBaseClass()"));
       
  2735     
       
  2736     // We don't want the host to see us (at least not yet):
       
  2737     UsbDisconnect();
       
  2738     
       
  2739     iDeviceTotalEndpoints = aTotalEndpoints;    
       
  2740     
       
  2741     // Initialise USB descriptor pool
       
  2742     if (iDescriptors.Init(aDescPool.iDeviceDesc, 
       
  2743                           aDescPool.iConfigDesc, 
       
  2744                           aDescPool.iLangId, 
       
  2745                           aDescPool.iManufacturer, 
       
  2746                           aDescPool.iProduct,
       
  2747                           aDescPool.iSerialNum, 
       
  2748                           aDescPool.iConfig, 
       
  2749                           aDescPool.iOtgDesc) != KErrNone)
       
  2750         {
       
  2751         __KTRACE_OPT(KUSB, Kern::Printf("  Error: Descriptor initialization failed"));
       
  2752         return EFalse;
       
  2753         }
       
  2754 
       
  2755     if (aDescPool.iOtgDesc)
       
  2756         {
       
  2757         iOtgSupport = ETrue;
       
  2758         iOtgFuncMap = aDescPool.iOtgDesc->DescriptorData()[2];
       
  2759         }
       
  2760 
       
  2761     // Some member variables
       
  2762     iSelfPowered  = aDescPool.iConfigDesc->Byte(7) & (1 << 6);        // Byte 7: bmAttributes
       
  2763     iRemoteWakeup = aDescPool.iConfigDesc->Byte(7) & (1 << 5);
       
  2764 
       
  2765     if (iControllerProperties.iControllerCaps & UsbShai::KDevCapHighSpeed)
       
  2766         {
       
  2767         if (iDescriptors.InitHs() != KErrNone)
       
  2768             {
       
  2769             return EFalse;
       
  2770             }
       
  2771         }
       
  2772 
       
  2773     // Create and initialise our first (and only) configuration
       
  2774     TUsbcConfiguration* config = new TUsbcConfiguration(1);
       
  2775     if (!config)
       
  2776         {
       
  2777         return EFalse;
       
  2778         }
       
  2779     iConfigs.Append(config);
       
  2780 
       
  2781     // Initialise the array of physical endpoints    
       
  2782     __KTRACE_OPT(KUSB, Kern::Printf("  DeviceTotalEndpoints: %d", aTotalEndpoints));
       
  2783     
       
  2784     // KUsbcMaxEndpoints doesn't include ep 0
       
  2785     if ((aTotalEndpoints > (KUsbcMaxEndpoints + 2)) ||
       
  2786         ((aTotalEndpoints * sizeof(TUsbcPhysicalEndpoint)) > sizeof(iRealEndpoints)))
       
  2787         {
       
  2788         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: too many endpoints! (change KUsbcMaxEndpoints: %d)",
       
  2789                                           KUsbcMaxEndpoints));
       
  2790         return EFalse;
       
  2791         }      
       
  2792     
       
  2793     for (TInt i = 0; i < aTotalEndpoints; ++i)
       
  2794         {
       
  2795         iRealEndpoints[i].iEndpointAddr = EpIdx2Addr(i);
       
  2796         
       
  2797         __KTRACE_OPT(KUSB, Kern::Printf("  aEndpointCaps[%02d] - iTypes: 0x%08x iSizes: 0x%08x",
       
  2798                                         i, aEndpointCaps[i].iTypesAndDir, aEndpointCaps[i].iSizes));
       
  2799                                                                                 
       
  2800         iRealEndpoints[i].iCaps = aEndpointCaps[i];
       
  2801         
       
  2802         // Reset revered bytes to zero
       
  2803         iRealEndpoints[i].iCaps.iReserved[0] = 0;
       
  2804         iRealEndpoints[i].iCaps.iReserved[1] = 0;
       
  2805         
       
  2806         if ((i > 1) && (aEndpointCaps[i].iTypesAndDir != UsbShai::KUsbEpNotAvailable))
       
  2807             {
       
  2808             __KTRACE_OPT(KUSB, Kern::Printf("  --> UsableEndpoint: #%d", i));
       
  2809             iDeviceUsableEndpoints++;
       
  2810             }
       
  2811         }
       
  2812 
       
  2813     // Initialise Ep0 structures (logical endpoints are numbered 1..KMaxEndpointsPerClient,
       
  2814     // and virtual 0 is real 0):
       
  2815     // -- Ep0 OUT
       
  2816     iEp0MaxPacketSize = MaxEndpointPacketSize(aEndpointCaps[0].iSizes);
       
  2817     __KTRACE_OPT(KUSB, Kern::Printf("  using Ep0 maxpacketsize of %d bytes", iEp0MaxPacketSize));
       
  2818     
       
  2819     TUsbcEndpointInfo info(UsbShai::KUsbEpTypeControl, UsbShai::KUsbEpDirOut, 0);
       
  2820     TUsbcLogicalEndpoint* ep = NULL;
       
  2821     
       
  2822     info.iSize = iEp0MaxPacketSize;
       
  2823     ep = new TUsbcLogicalEndpoint(this, 0, info, NULL, &iRealEndpoints[KEp0_Out]);
       
  2824     if (!ep)
       
  2825         {
       
  2826         return EFalse;
       
  2827         }
       
  2828         
       
  2829     __KTRACE_OPT(KUSB, Kern::Printf("  creating ep: mapping real ep %d --> logical ep 0", KEp0_Out));
       
  2830     iRealEndpoints[KEp0_Out].iLEndpoint = ep;
       
  2831     
       
  2832     // -- Ep0 IN
       
  2833     info.iDir = UsbShai::KUsbEpDirIn;
       
  2834     ep = new TUsbcLogicalEndpoint(this, 0, info, NULL, &iRealEndpoints[KEp0_In]);
       
  2835     if (!ep)
       
  2836         {
       
  2837         delete iRealEndpoints[KEp0_Out].iLEndpoint;
       
  2838         iRealEndpoints[KEp0_Out].iLEndpoint = NULL;
       
  2839         return EFalse;
       
  2840         }
       
  2841     __KTRACE_OPT(KUSB, Kern::Printf("  creating ep: mapping real ep %d --> logical ep 0", KEp0_In));
       
  2842     iRealEndpoints[KEp0_In].iLEndpoint = ep;    
       
  2843     
       
  2844     iPowerHandler = new DUsbcPowerHandler(this);
       
  2845     if (!iPowerHandler)
       
  2846         {
       
  2847         delete iRealEndpoints[KEp0_Out].iLEndpoint;
       
  2848         iRealEndpoints[KEp0_Out].iLEndpoint = NULL;
       
  2849         delete iRealEndpoints[KEp0_In].iLEndpoint;
       
  2850         iRealEndpoints[KEp0_In].iLEndpoint = NULL;
       
  2851         return EFalse;
       
  2852         }
       
  2853     iPowerHandler->Add();
       
  2854 
       
  2855     return ETrue;    
       
  2856     }
       
  2857 
       
  2858 /** The standard constructor for this class.
       
  2859 
       
  2860     @publishedPartner @released
       
  2861  */
       
  2862 DUsbClientController::DUsbClientController(UsbShai::MPeripheralControllerIf&               aPeripheralControllerIf, 
       
  2863                                            const UsbShai::TPeripheralControllerProperties& aProperties,
       
  2864                                            TBool                                  aIsOtgPort)
       
  2865     : iEp0ReceivedNonStdRequest(EFalse),
       
  2866       iRmWakeupStatus_Enabled(EFalse),
       
  2867       iEp0_RxBuf(),
       
  2868       iDeviceTotalEndpoints(0),
       
  2869       iDeviceUsableEndpoints(0),
       
  2870       iDeviceState(UsbShai::EUsbPeripheralStateUndefined),
       
  2871       iDeviceStateB4Suspend(UsbShai::EUsbPeripheralStateUndefined),
       
  2872       iSelfPowered(EFalse),
       
  2873       iRemoteWakeup(EFalse),
       
  2874       iHardwareActivated(EFalse),
       
  2875       iOtgSupport(EFalse),
       
  2876       iOtgFuncMap(0),
       
  2877       iHighSpeed(EFalse),
       
  2878       iEp0MaxPacketSize(0),
       
  2879       iEp0ClientId(NULL),
       
  2880       iEp0DataReceived(0),
       
  2881       iEp0WritePending(EFalse),
       
  2882       iEp0ClientDataTransmitting(EFalse),
       
  2883       iEp0DeviceControl(NULL),
       
  2884       iDescriptors(iEp0_TxBuf),
       
  2885       iCurrentConfig(0),
       
  2886       iConfigs(1),
       
  2887       iRealEndpoints(),
       
  2888       iEp0_TxBuf(),
       
  2889       iEp0_RxExtraCount(0),
       
  2890       iEp0_TxNonStdCount(0),
       
  2891       iEp0ReadRequestCallbacks(_FOFF(TUsbcRequestCallback, iLink)),
       
  2892       iClientCallbacks(_FOFF(TUsbcClientCallback, iLink)),
       
  2893       iStatusCallbacks(_FOFF(TUsbcStatusCallback, iLink)),
       
  2894       iEpStatusCallbacks(_FOFF(TUsbcEndpointStatusCallback, iLink)),
       
  2895       iOtgCallbacks(_FOFF(TUsbcOtgFeatureCallback, iLink)),
       
  2896       iReconnectTimer(ReconnectTimerCallback, this),
       
  2897       iUsbLock(TSpinLock::EOrderGenericIrqLow3),      
       
  2898       iController(aPeripheralControllerIf),
       
  2899       iControllerProperties(aProperties),
       
  2900       iIsOtgPort(aIsOtgPort),
       
  2901       iOtgObserver(NULL),
       
  2902       iConTransferMgr(NULL),
       
  2903       iLastError(EFalse),
       
  2904       iSetupPacketPending(EFalse),
       
  2905       iCommonDfcQThread(NULL),
       
  2906       iPowerUpDfc(PowerUpDfc, this, 3),
       
  2907       iPowerDownDfc(PowerDownDfc, this, 3),
       
  2908       iDeviceEventNotifyDfc(DeviceEventNotifyDfc,this,3),
       
  2909       iThreadContextFinder(ThreadContextFinderDfc,this,3),
       
  2910       iStandby(EFalse),
       
  2911       iStackIsActive(EFalse),
       
  2912       iClientSupportReady(EFalse),
       
  2913       iUsbResetDeferred(EFalse),
       
  2914       iEnablePullUpOnDPlus(NULL),
       
  2915       iDisablePullUpOnDPlus(NULL),
       
  2916       iOtgContext(NULL)
       
  2917     {
       
  2918     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DUsbClientController()"));
       
  2919     
       
  2920     iLastError = KErrNone;
       
  2921     
       
  2922 #ifndef SEPARATE_USB_DFC_QUEUE
       
  2923     iPowerUpDfc.SetDfcQ(Kern::DfcQue0());
       
  2924     iPowerDownDfc.SetDfcQ(Kern::DfcQue0());
       
  2925 #endif // SEPARATE_USB_DFC_QUEUE
       
  2926 
       
  2927     for (TInt i = 0; i < KUsbcEpArraySize; i++)
       
  2928         iRequestCallbacks[i] = NULL;
       
  2929     }
       
  2930 
       
  2931 TInt DUsbClientController::Construct()
       
  2932     {
       
  2933     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::Construct"));
       
  2934     
       
  2935     // Setup the state machines of ep0
       
  2936     TInt err = SetupEp0StateMachine();
       
  2937     if( err != KErrNone)
       
  2938         {
       
  2939         __KTRACE_OPT(KUSB, Kern::Printf("    Can not setup state machines, exit"));
       
  2940         return err;
       
  2941         }
       
  2942         
       
  2943 #ifdef SEPARATE_USB_DFC_QUEUE
       
  2944     iPowerUpDfc.SetDfcQ(iControllerProperties.iDfcQueue);
       
  2945     iPowerDownDfc.SetDfcQ(iControllerProperties.iDfcQueue);
       
  2946 #endif  // SEPARATE_USB_DFC_QUEUE
       
  2947     
       
  2948     iDeviceEventNotifyDfc.SetDfcQ(iControllerProperties.iDfcQueue);
       
  2949     iThreadContextFinder.SetDfcQ(iControllerProperties.iDfcQueue);
       
  2950     
       
  2951     // Register 
       
  2952     if( RegisterUdc(0) != KErrNone)
       
  2953         {
       
  2954         // This is the only reason.
       
  2955         return KErrInUse;
       
  2956         }
       
  2957         
       
  2958     __KTRACE_OPT(KUSB, Kern::Printf("    peripheral controller registered"));
       
  2959     TUsbPeripheralDescriptorPool descPool;       
       
  2960     
       
  2961     if( CreateDescriptors(descPool) == KErrNone)
       
  2962         {
       
  2963         __KTRACE_OPT(KUSB, Kern::Printf("    descriptors created"));
       
  2964         
       
  2965         // Initialise the array of physical endpoints 
       
  2966         __KTRACE_OPT(KUSB, Kern::Printf("    initialising PIL "));
       
  2967         TBool initOk = Initialise(descPool,
       
  2968                                   iControllerProperties.iDeviceEndpointCaps,
       
  2969                                   iControllerProperties.iDeviceTotalEndpoints);
       
  2970         
       
  2971         // Let UDC has a changes to know the callback interface is ready.
       
  2972         // Any further initialization/startup/preparation etc can be performed now.
       
  2973         if  ( initOk )
       
  2974             {
       
  2975             __KTRACE_OPT(KUSB, Kern::Printf("    Initializing PSL "));
       
  2976             
       
  2977             // Set Rx buffer for endpoint zero
       
  2978             iController.SetEp0RxBuffer(iEp0_RxBuf,KUsbcBufSzControl);
       
  2979             
       
  2980             // Set pil callback interface for PSL.
       
  2981             iController.SetPilCallbackInterface(*this);
       
  2982             
       
  2983             }
       
  2984         else
       
  2985             {
       
  2986             return KErrNoMemory;
       
  2987             }
       
  2988         }
       
  2989     
       
  2990     // Register ourself as the ONLY one client of charger detection observer
       
  2991     gChargerObsever = this;
       
  2992     
       
  2993     // In case the charger detector already registered, start monitor
       
  2994     // Charger type notifications
       
  2995     if( gChargerDetector != NULL )
       
  2996         {
       
  2997         gChargerDetector->SetChargerDetectorObserver(*gChargerObsever);
       
  2998         }
       
  2999     
       
  3000     iThreadContextFinder.Enque();
       
  3001     
       
  3002     return KErrNone;
       
  3003     }
       
  3004 
       
  3005 // This function doesn't consider the situation of OOM.
       
  3006 // Because, this function will be call during extension's entry point,
       
  3007 // There is no way to start up phone successfully if anything failed anyway...
       
  3008 TInt DUsbClientController::SetupEp0StateMachine()
       
  3009     {
       
  3010 	// Create the state machine first
       
  3011 	__ASSERT_DEBUG((iConTransferMgr == NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
       
  3012 	iConTransferMgr = new DControlTransferManager(*this);
       
  3013 	if(iConTransferMgr == 0)
       
  3014 		{
       
  3015 		return KErrNoMemory;
       
  3016 		}
       
  3017 		
       
  3018     // Add UsbShai::EControlTransferStageSetup stage machine
       
  3019     TControlStageSm* stageSm = new DSetupStageSm(*iConTransferMgr);    
       
  3020     __ASSERT_DEBUG((stageSm != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
       
  3021     if(stageSm != NULL)
       
  3022         {
       
  3023         iConTransferMgr->AddState(UsbShai::EControlTransferStageSetup,*stageSm);
       
  3024         }
       
  3025     else
       
  3026         {
       
  3027         return KErrNoMemory;
       
  3028         }
       
  3029         
       
  3030     // Add EControlTransferStageDataOut stage state machine        
       
  3031     stageSm = new DDataOutStageSm(*iConTransferMgr);
       
  3032     __ASSERT_DEBUG((stageSm != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
       
  3033     if(stageSm != NULL)
       
  3034         {
       
  3035         iConTransferMgr->AddState(UsbShai::EControlTransferStageDataOut,*stageSm);
       
  3036         }
       
  3037     else
       
  3038         {
       
  3039         // we don't need bother to delete the previous allocated memory
       
  3040         // system can not bootup if we return error
       
  3041         return KErrNoMemory;
       
  3042         }
       
  3043         
       
  3044     // Add EControlTransferStageStatusIn stage state machine     
       
  3045     stageSm = new DStatusInStageSm(*iConTransferMgr);
       
  3046     __ASSERT_DEBUG((stageSm != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
       
  3047     if(stageSm != NULL)
       
  3048         {
       
  3049         iConTransferMgr->AddState(UsbShai::EControlTransferStageStatusIn,*stageSm); 
       
  3050         }
       
  3051     else
       
  3052         {
       
  3053         return KErrNoMemory;
       
  3054         }
       
  3055             
       
  3056     // Add EControlTransferStageDataIn stage state machine    
       
  3057     stageSm = new DDataInStageSm(*iConTransferMgr);
       
  3058     __ASSERT_DEBUG((stageSm != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
       
  3059    if(stageSm != NULL)
       
  3060         {
       
  3061         iConTransferMgr->AddState(UsbShai::EControlTransferStageDataIn,*stageSm);
       
  3062         }
       
  3063     else
       
  3064         {
       
  3065         return KErrNoMemory;
       
  3066         }
       
  3067     
       
  3068     // Add EControlTransferStageStatusOut stage state machine    
       
  3069     stageSm = new DStatusOutStageSm(*iConTransferMgr);
       
  3070     __ASSERT_DEBUG((stageSm != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
       
  3071     if(stageSm != NULL)
       
  3072         {
       
  3073         iConTransferMgr->AddState(UsbShai::EControlTransferStageStatusOut,*stageSm);
       
  3074         }    
       
  3075     else
       
  3076         {
       
  3077         return KErrNoMemory;
       
  3078         }
       
  3079         
       
  3080     return KErrNone;
       
  3081     }
       
  3082     
       
  3083 // ---------------------------------------------------------------------------
       
  3084 // From MUsbPeripheralPilCallbackIf.
       
  3085 // Enable the peripheral stack
       
  3086 // ---------------------------------------------------------------------------
       
  3087 //
       
  3088 void DUsbClientController::EnablePeripheralStack()
       
  3089     {
       
  3090     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EnablePeripheralStack"));
       
  3091 
       
  3092     if (iStackIsActive)
       
  3093         {
       
  3094         __KTRACE_OPT(KUSB, Kern::Printf("  Already enabled - returning"));
       
  3095         return;
       
  3096         }
       
  3097 
       
  3098     // Mark stack is enabled, Waiting upper application to power controller
       
  3099     // Anyway, this will lead us to attached state
       
  3100     iStackIsActive = ETrue;    
       
  3101     NextDeviceState(UsbShai::EUsbPeripheralStateAttached);
       
  3102     
       
  3103     // If hardware is not activated yet, do it here.
       
  3104     if(iClientSupportReady && !iHardwareActivated)
       
  3105         {
       
  3106         // PowerUpUdc only do Activating Hardware when there are at least 1
       
  3107         // Iterface registered.
       
  3108         PowerUpUdc();
       
  3109         }
       
  3110     
       
  3111     }
       
  3112 
       
  3113 
       
  3114 // ---------------------------------------------------------------------------
       
  3115 // From MUsbPeripheralPilCallbackIf.
       
  3116 // Disable the peripheral stack
       
  3117 // ---------------------------------------------------------------------------
       
  3118 //
       
  3119 void DUsbClientController::DisablePeripheralStack()
       
  3120     {
       
  3121     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DisablePeripheralStack"));
       
  3122 
       
  3123     if (!iStackIsActive)
       
  3124         {
       
  3125         __KTRACE_OPT(KUSB, Kern::Printf("  Already disabled - returning"));
       
  3126         return;
       
  3127         }
       
  3128 
       
  3129     // Reset OTG features, leave attributes as is (just as in USB Reset case)
       
  3130     // (OTG spec 1.3 sections 6.5.x all say "... on a bus reset or at the end
       
  3131     //  of a session." VBus drop is the end of a session.)
       
  3132     iOtgFuncMap &= KUsbOtgAttr_SrpSupp | KUsbOtgAttr_HnpSupp;
       
  3133     OtgFeaturesNotify();
       
  3134     // Tear down the current configuration (if any)
       
  3135     ChangeConfiguration(0);
       
  3136 
       
  3137     if (iDeviceState != UsbShai::EUsbPeripheralStateUndefined)
       
  3138         {
       
  3139         // Not being in state UNDEFINED implies that the cable is inserted.
       
  3140         if (iHardwareActivated)
       
  3141             {
       
  3142             NextDeviceState(UsbShai::EUsbPeripheralStatePowered);
       
  3143             }
       
  3144         // (If the hardware is NOT activated at this point, we can only be in
       
  3145         //    state UsbShai::EUsbPeripheralStateAttached, so we don't have to move to it.)
       
  3146         }
       
  3147     DeActivateHardwareController();                     // turn off UDC altogether
       
  3148     iStackIsActive = EFalse;
       
  3149     // Notify registered clients on the user side about a USB device state
       
  3150     // change event and a transition to the "Undefined" state.
       
  3151     // Note: the state should be changed to "Undefined" before calling RunClientCallbacks(), 
       
  3152     //       otherwise the "Undefined" state will probably be lost.
       
  3153     NextDeviceState(UsbShai::EUsbPeripheralStateUndefined);
       
  3154     // Complete all pending requests, returning KErrDisconnected
       
  3155     RunClientCallbacks();
       
  3156     }
       
  3157 
       
  3158 
       
  3159 // ---------------------------------------------------------------------------
       
  3160 // From MUsbPeripheralPilCallbackIf.
       
  3161 // Set the OTG Observer
       
  3162 // ---------------------------------------------------------------------------
       
  3163 //
       
  3164 void DUsbClientController::SetOtgObserver(MUsbOtgPeripheralObserverIf* aObserver)
       
  3165     {
       
  3166     iOtgObserver = aObserver;
       
  3167     }
       
  3168 
       
  3169 
       
  3170 /** This function gets called by the PSL upon detection of either of the following events:
       
  3171     - USB Reset,
       
  3172     - USB Suspend event,
       
  3173     - USB Resume signalling,
       
  3174     - The USB cable has been attached (inserted) or detached (removed).
       
  3175 
       
  3176     @param anEvent An enum denoting the event that has occured.
       
  3177 
       
  3178     @return KErrArgument if the event is not recognized, otherwise KErrNone.
       
  3179 
       
  3180     @publishedPartner @released
       
  3181 */
       
  3182 TInt DUsbClientController::DeviceEventNotification(UsbShai::TUsbPeripheralEvent anEvent)
       
  3183     {
       
  3184     TInt err = KErrNone;
       
  3185     
       
  3186     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeviceEventNotification(anEvent=%d)", anEvent));
       
  3187     
       
  3188     switch (anEvent)
       
  3189         {
       
  3190         case UsbShai::EUsbEventSuspend:
       
  3191         case UsbShai::EUsbEventResume:
       
  3192         case UsbShai::EUsbEventReset:
       
  3193         case UsbShai::EUsbEventVbusRisen:
       
  3194         case UsbShai::EUsbEventVbusFallen:
       
  3195             {
       
  3196             TInt nkern_curr_ctx= NKern::CurrentContext();
       
  3197             
       
  3198             if( (nkern_curr_ctx != NKern::EInterrupt) && (nkern_curr_ctx != NKern::EIDFC))
       
  3199                 {
       
  3200                 // Normal context
       
  3201                 __ASSERT_DEBUG((iCommonDfcQThread != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
       
  3202                 if(iCommonDfcQThread == &(Kern::CurrentThread().iNThread))
       
  3203                     {
       
  3204                     // we already in the correct context, just run processes here directly.
       
  3205                     __KTRACE_OPT(KUSB, Kern::Printf("  Correct thread context"));
       
  3206                     ProcessDeviceEventNotification(anEvent);
       
  3207                     }
       
  3208                 else
       
  3209                     {
       
  3210                     // we're in a normal thread, but it is not the same as the DfcQ context
       
  3211                     // passed by PSL, queue it
       
  3212                     __KTRACE_OPT(KUSB, Kern::Printf("  Incorrect thread context"));
       
  3213                     iDevEventQueue.FifoAdd(anEvent);
       
  3214                     iDeviceEventNotifyDfc.Enque();
       
  3215                     }
       
  3216                 }
       
  3217             else
       
  3218                 {                
       
  3219                 // We're in a ISR or IDFC context
       
  3220                 __KTRACE_OPT(KUSB, Kern::Printf("  ISR|IDFC context"));
       
  3221                 iDevEventQueue.FifoAdd(anEvent);
       
  3222                 iDeviceEventNotifyDfc.Add();
       
  3223                 }
       
  3224             }
       
  3225             break;
       
  3226             
       
  3227         default:
       
  3228             err = KErrArgument;
       
  3229         }
       
  3230     
       
  3231     return err;    
       
  3232     }
       
  3233 
       
  3234 
       
  3235 /** This function gets called by the PSL upon completion of a pending data transfer request.
       
  3236 
       
  3237     This function is not to be used for endpoint zero completions (use Ep0RequestComplete instead).
       
  3238 
       
  3239     @param aCallback A pointer to a data transfer request callback structure which was previously passed to
       
  3240     the PSL in a SetupReadBuffer() or SetupWriteBuffer() call.
       
  3241 
       
  3242     @publishedPartner @released
       
  3243 */
       
  3244 void DUsbClientController::EndpointRequestComplete(UsbShai::TUsbPeripheralRequest* aCallback)
       
  3245     {
       
  3246     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EndpointRequestComplete(%p)", aCallback));
       
  3247     
       
  3248     TUsbcRequestCallback* cb = static_cast<TUsbcRequestCallback*>(aCallback);
       
  3249     // This function may be called by the PSL from within an ISR -- so we have
       
  3250     // to take care what we do here (and also in all functions that get called
       
  3251     // from here).
       
  3252 
       
  3253     // We don't test aCallback for NULL here (and therefore risk a crash)
       
  3254     // because the PSL should never give us a NULL argument. If it does it
       
  3255     // means the PSL is buggy and ought to be fixed.
       
  3256     ProcessDataTransferDone(*cb);
       
  3257     }
       
  3258 
       
  3259 
       
  3260 /** This function should be called by the PSL after reception of an Ep0
       
  3261     SET_FEATURE request with a feature selector of either {b_hnp_enable,
       
  3262     a_hnp_support, a_alt_hnp_support}, but only when that Setup packet is not
       
  3263     handed up to the PIL (for instance because it is auto-decoded and
       
  3264     'swallowed' by the UDC hardware).
       
  3265 
       
  3266     @param aHnpState A bitmask indicating the present state of the three OTG
       
  3267     feature selectors as follows:
       
  3268 
       
  3269     bit.0 == a_alt_hnp_support
       
  3270     bit.1 == a_hnp_support
       
  3271     bit.2 == b_hnp_enable
       
  3272 
       
  3273     @see DUsbClientController::ProcessSetClearDevFeature()
       
  3274 
       
  3275     @publishedPartner @released
       
  3276 */
       
  3277 void DUsbClientController::HandleHnpRequest(TInt aHnpState)
       
  3278 // This function is called by the PSL from within an ISR -- so we have to take care what we do here
       
  3279 // (and also in all functions that get called from here).
       
  3280     {
       
  3281     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::HandleHnpRequest(%d)", aHnpState));
       
  3282 
       
  3283     if (!iOtgSupport)
       
  3284         {
       
  3285         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Request only supported on a OTG device"));
       
  3286         return;
       
  3287         }
       
  3288     if (!(iOtgFuncMap & KUsbOtgAttr_HnpSupp))
       
  3289         {
       
  3290         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Request only valid if OTG device supports HNP"));
       
  3291         return;
       
  3292         }
       
  3293     //    (case KUsbFeature_B_HnpEnable:)
       
  3294     if (aHnpState & 0x04)
       
  3295         {
       
  3296         iOtgFuncMap |= KUsbOtgAttr_B_HnpEnable;
       
  3297         }
       
  3298     // (case KUsbFeature_A_HnpSupport:)
       
  3299     if (aHnpState & 0x02)
       
  3300         {
       
  3301         iOtgFuncMap |= KUsbOtgAttr_A_HnpSupport;
       
  3302         }
       
  3303     // (case KUsbFeature_A_AltHnpSupport:)
       
  3304     if (aHnpState & 0x01)
       
  3305         {
       
  3306         iOtgFuncMap |= KUsbOtgAttr_A_AltHnpSupport;
       
  3307         }
       
  3308     OtgFeaturesNotify();
       
  3309     }
       
  3310 
       
  3311 void DUsbClientController::GetEp0RxBufferInfo(TUint8*& aBuffer, TInt& aBufferLen)
       
  3312     {
       
  3313     aBuffer = iEp0_RxBuf;
       
  3314     aBufferLen = KUsbcBufSzControl;
       
  3315     }
       
  3316     
       
  3317 UsbShai::TUsbPeripheralState DUsbClientController::DeviceStatus() const
       
  3318     {
       
  3319     return iDeviceState;
       
  3320     }
       
  3321 
       
  3322 TBool DUsbClientController::Ep0ReceivedNonStdRequest()
       
  3323     {
       
  3324     return iEp0ReceivedNonStdRequest;
       
  3325     }
       
  3326     
       
  3327 /** This function gets called by the PSL upon completion of a pending endpoint zero data transfer request.
       
  3328 
       
  3329     @param aRealEndpoint Either 0 for Ep0 OUT (= Read), or 1 for Ep0 IN (= Write).
       
  3330     @param aCount The number of bytes received or transmitted, respectively.
       
  3331     @param aError The error status of the completed transfer request. Can be KErrNone if no error, KErrCancel
       
  3332     if transfer was cancelled, or KErrPrematureEnd if a premature status end was encountered.
       
  3333 
       
  3334     @return KErrNone if no error during transfer completion processing, KErrGeneral if the request was a read &
       
  3335     a Setup packet was received & the recipient for that packet couldn't be found (invalid packet: Ep0 has been
       
  3336     stalled), KErrNotFound if the request was a read & the recipient for that packet (Setup or data) _was_
       
  3337     found - however no read had been set up by that recipient (this case should be used by the PSL to disable
       
  3338     the Ep0 interrupt at that point and give the LDD time to set up a new Ep0 read; once the 'missing' read
       
  3339     was set up either Ep0ReceiveProceed or Ep0ReadSetupPktProceed will be called by the PIL).
       
  3340 
       
  3341     @publishedPartner @released
       
  3342 */
       
  3343 TInt DUsbClientController::Ep0RequestComplete(TInt aRealEndpoint,
       
  3344                                               TInt aCount, 
       
  3345                                               TInt aError, 
       
  3346                                               UsbShai::TControlPacketType aPktType)
       
  3347     {
       
  3348     __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::Ep0RequestComplete(%d)", aRealEndpoint));
       
  3349     
       
  3350     iLastError = KErrNone;
       
  3351     
       
  3352     iConTransferMgr->Ep0RequestComplete(iEp0_RxBuf,aCount,aError,aPktType);
       
  3353     
       
  3354     __KTRACE_OPT(KUSB, Kern::Printf("    iLastError(%d)", iLastError));
       
  3355     
       
  3356     if(iEp0WritePending == EFalse)
       
  3357         {
       
  3358         iConTransferMgr->SetupEndpointZeroRead();
       
  3359         }
       
  3360         
       
  3361     __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::Ep0RequestComplete"));
       
  3362     return iLastError;
       
  3363     }    
       
  3364 
       
  3365 /** This function should be called by the PSL once the UDC (and thus the USB device) is in the Address state.
       
  3366 
       
  3367     @publishedPartner @released
       
  3368 */
       
  3369 void DUsbClientController::MoveToAddressState()
       
  3370     {
       
  3371     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::MoveToAddressState()"));
       
  3372 
       
  3373     // This function may be called by the PSL from within an ISR -- so we have
       
  3374     // to take care what we do here (and also in all functions that get called
       
  3375     // from here).
       
  3376 
       
  3377     NextDeviceState(UsbShai::EUsbPeripheralStateAddress);
       
  3378     }
       
  3379 
       
  3380 
       
  3381 TBool DUsbClientController::CreateDescriptors(TUsbPeripheralDescriptorPool& aOutput)
       
  3382     {
       
  3383     TInt errCode = KErrNone;
       
  3384     
       
  3385     // Create all the string descriptors
       
  3386     TUsbcDeviceDescriptor* deviceDesc = TUsbcDeviceDescriptor::New(
       
  3387                                                 0,     // aDeviceClass, will be changed later by upper app
       
  3388                                                 0,     // aDeviceSubClass, will be changed later by upper app
       
  3389                                                 0,     // aDeviceProtocol, will be changed later by upper app
       
  3390                                                 iControllerProperties.iMaxEp0Size  ,   // aMaxPacketSize0
       
  3391                                                 KUsbVendorId,           // aVendorId
       
  3392                                                 KUsbProductId ,         // aProductId
       
  3393                                                 iControllerProperties.iDeviceRelease,         // aDeviceRelease
       
  3394                                                 KUsbNumberOfConfiguration);// aNumConfigurations
       
  3395     __ASSERT_DEBUG( (deviceDesc != NULL), Kern::Fault( "USB PSL Out of memory, deviceDesc", __LINE__ ));    
       
  3396     
       
  3397     TUsbcConfigDescriptor* configDesc = TUsbcConfigDescriptor::New(
       
  3398                                             1,       // Only one configruation is supported current.
       
  3399                                             EFalse,  // at here, we always mark it as bus powered.
       
  3400                                             (iControllerProperties.iControllerCaps & UsbShai::KDevCapRemoteWakeupSupport)?ETrue:EFalse,  // remote wakeup
       
  3401                                             100);    // 100 is a default value, thise value will be changed by
       
  3402     
       
  3403     __ASSERT_DEBUG( (configDesc != NULL), Kern::Fault( "USB PSL Out of memory, configDesc", __LINE__ ));
       
  3404         
       
  3405     TUsbcLangIdDescriptor* stringDescLang = TUsbcLangIdDescriptor::New(KUsbLangId);
       
  3406     __ASSERT_DEBUG( (stringDescLang != NULL), Kern::Fault( "USB PSL Out of memory, stringDescLang", __LINE__ ));
       
  3407     
       
  3408     // Default manufacturer string
       
  3409     TPtrC8 aString;
       
  3410     aString.Set(reinterpret_cast<const TUint8*>(KStringManufacturer), sizeof(KStringManufacturer) - 2);
       
  3411     TUsbcStringDescriptor* stringDescManu = TUsbcStringDescriptor::New(aString);
       
  3412     __ASSERT_DEBUG( (stringDescManu != NULL), Kern::Fault( "USB PSL Out of memory, stringDescManu", __LINE__ ));
       
  3413     
       
  3414     // Default product name string
       
  3415     aString.Set(reinterpret_cast<const TUint8*>(KStringProduct), sizeof(KStringProduct) - 2);
       
  3416     TUsbcStringDescriptor* stringDescProd = TUsbcStringDescriptor::New(aString);
       
  3417     __ASSERT_DEBUG( (stringDescProd != NULL), Kern::Fault( "USB PSL Out of memory, stringDescProd", __LINE__ ));
       
  3418     
       
  3419     // Default configuration name string
       
  3420     aString.Set(reinterpret_cast<const TUint8*>(KStringConfig), sizeof(KStringConfig) - 2);
       
  3421     TUsbcStringDescriptor* stringDescConf = TUsbcStringDescriptor::New(aString);
       
  3422     __ASSERT_DEBUG( (stringDescConf != NULL), Kern::Fault( "USB PSL Out of memory, stringDescConf", __LINE__ ));
       
  3423     
       
  3424     // Default serial bumber string
       
  3425     aString.Set(reinterpret_cast<const TUint8*>(KStringSerial), sizeof(KStringSerial) - 2);
       
  3426     TUsbcStringDescriptor* stringSerial = TUsbcStringDescriptor::New(aString);
       
  3427     __ASSERT_DEBUG( (stringSerial != NULL), Kern::Fault( "USB PSL Out of memory, stringDescConf", __LINE__ ));
       
  3428    
       
  3429     TUsbcOtgDescriptor* otgDesc = NULL;
       
  3430 
       
  3431     // In an OTG-environment, we also need to create the OTG
       
  3432     // descriptor. The PSL supports both HNP and SRP and hence we
       
  3433     // report support for them. Upper layers will override the
       
  3434     // descriptors anyway.
       
  3435     if (iIsOtgPort)
       
  3436         {
       
  3437         TBool srpSupported = (iControllerProperties.iControllerCaps & UsbShai::KDevCapSrpSupport)?ETrue:EFalse;
       
  3438         TBool hnpSupported = (iControllerProperties.iControllerCaps & UsbShai::KDevCapHnpSupport)?ETrue:EFalse;
       
  3439         
       
  3440         otgDesc = TUsbcOtgDescriptor::New(srpSupported,
       
  3441                                           hnpSupported);
       
  3442         
       
  3443         __ASSERT_DEBUG( (otgDesc != NULL), Kern::Fault( "USB PSL Out of memory, otgDesc", __LINE__ ));     
       
  3444         }
       
  3445     
       
  3446     if( (deviceDesc != NULL) && 
       
  3447         (configDesc != NULL) && 
       
  3448         (stringDescLang != NULL) &&
       
  3449         (stringDescManu != NULL) && 
       
  3450         (stringDescProd != NULL) && 
       
  3451         (stringDescConf != NULL) &&
       
  3452         ((!iIsOtgPort) || (iIsOtgPort && (otgDesc != NULL))))
       
  3453         {    
       
  3454         aOutput.iDeviceDesc = deviceDesc;
       
  3455         aOutput.iConfigDesc = configDesc;
       
  3456         aOutput.iLangId = stringDescLang;
       
  3457         aOutput.iManufacturer = stringDescManu;
       
  3458         aOutput.iProduct = stringDescProd;
       
  3459         aOutput.iConfig = stringDescConf;
       
  3460         aOutput.iSerialNum = stringSerial;
       
  3461         aOutput.iOtgDesc = otgDesc;
       
  3462         }
       
  3463     else
       
  3464         {
       
  3465         if( deviceDesc != NULL )
       
  3466             {
       
  3467             delete deviceDesc;
       
  3468             }
       
  3469         
       
  3470         if( configDesc != NULL )
       
  3471             {
       
  3472             delete configDesc;
       
  3473             }
       
  3474             
       
  3475         if( stringDescLang != NULL )
       
  3476             {
       
  3477             delete stringDescLang;
       
  3478             }
       
  3479             
       
  3480         if( stringDescManu != NULL )
       
  3481             {
       
  3482             delete stringDescManu;
       
  3483             }
       
  3484             
       
  3485         if( stringDescProd != NULL )
       
  3486             {
       
  3487             delete stringDescProd;
       
  3488             }
       
  3489             
       
  3490         if( stringDescConf != NULL )
       
  3491             {
       
  3492             delete stringDescConf;
       
  3493             }
       
  3494             
       
  3495         if( stringSerial != NULL )
       
  3496             {
       
  3497             delete stringSerial;
       
  3498             }
       
  3499             
       
  3500         if( otgDesc != NULL )
       
  3501             {
       
  3502             delete otgDesc;
       
  3503             }
       
  3504         
       
  3505         errCode = KErrNoMemory;
       
  3506         }
       
  3507     
       
  3508     // We don't support serial number 
       
  3509     aOutput.iSerialNum = NULL;
       
  3510     
       
  3511     return errCode;    
       
  3512     }
       
  3513     
       
  3514 //
       
  3515 // === USB Controller member function implementations - Internal utility functions (private) =======
       
  3516 //
       
  3517 
       
  3518 TInt DUsbClientController::DeRegisterClientCallback(const DBase* aClientId)
       
  3519     {
       
  3520     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterClientCallback()"));
       
  3521     __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
       
  3522     TSglQueIter<TUsbcClientCallback> iter(iClientCallbacks);
       
  3523     TUsbcClientCallback* p;
       
  3524     while ((p = iter++) != NULL)
       
  3525         if (p->Owner() == aClientId)
       
  3526             {
       
  3527             __KTRACE_OPT(KUSB, Kern::Printf("  removing ClientCallback @ 0x%x", p));
       
  3528             iClientCallbacks.Remove(*p);
       
  3529             return KErrNone;
       
  3530             }
       
  3531     __KTRACE_OPT(KUSB, Kern::Printf("  Client not found"));
       
  3532     return KErrNotFound;
       
  3533     }
       
  3534 
       
  3535 
       
  3536 TBool DUsbClientController::CheckEpAvailability(TInt aEndpointsUsed,
       
  3537                                                 const TUsbcEndpointInfoArray& aEndpointData,
       
  3538                                                 TInt aIfcNumber) const
       
  3539     {
       
  3540     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CheckEpAvailability()"));
       
  3541     if (aEndpointsUsed > KMaxEndpointsPerClient)
       
  3542         {
       
  3543         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: too many endpoints claimed (%d)", aEndpointsUsed));
       
  3544         return EFalse;
       
  3545         }
       
  3546     TBool reserve[KUsbcEpArraySize]; // iDeviceTotalEndpoints can be equal to 32
       
  3547     memset(reserve, EFalse, sizeof(reserve));                // reset the array
       
  3548     for (TInt i = 0; i < aEndpointsUsed; ++i)
       
  3549         {
       
  3550         __KTRACE_OPT(KUSB, Kern::Printf("  checking for (user) endpoint #%d availability...", i + 1));
       
  3551         TInt j = 2;
       
  3552         while (j < iDeviceTotalEndpoints)
       
  3553             {
       
  3554             if ((iRealEndpoints[j].EndpointSuitable(&aEndpointData[i], aIfcNumber)) &&
       
  3555                 (reserve[j] == EFalse))
       
  3556                 {
       
  3557                 __KTRACE_OPT(KUSB, Kern::Printf("  ---> found suitable endpoint: RealEndpoint #%d", j));
       
  3558                 reserve[j] = ETrue;                            // found one: mark this ep as reserved
       
  3559                 break;
       
  3560                 }
       
  3561             __KTRACE_OPT(KUSB, Kern::Printf("  -> endpoint not suitable: RealEndpoint #%d", j));
       
  3562             j++;
       
  3563             }
       
  3564         if (j == iDeviceTotalEndpoints)
       
  3565             {
       
  3566             return EFalse;
       
  3567             }
       
  3568         }
       
  3569     return ETrue;
       
  3570     }
       
  3571 
       
  3572 
       
  3573 TUsbcInterface* DUsbClientController::CreateInterface(const DBase* aClientId, TInt aIfc, TUint32 aFeatureWord)
       
  3574 // We know that 9.2.3 says: "Interfaces are numbered from zero to one less than the number of
       
  3575 // concurrent interfaces supported by the configuration."  But since we permit the user to
       
  3576 // change interface numbers, we can neither assume nor enforce anything about them here.
       
  3577     {
       
  3578     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CreateInterface(x, aIfc=%d)", aIfc));
       
  3579     TUsbcInterfaceSet* ifcset_ptr = NULL;
       
  3580     TInt ifcset = ClientId2InterfaceNumber(aClientId);
       
  3581     TBool new_ifc;
       
  3582     if (ifcset < 0)
       
  3583         {
       
  3584         // New interface(set), so we need to find a number for it.
       
  3585         new_ifc = ETrue;
       
  3586         const TInt num_ifcsets = iConfigs[0]->iInterfaceSets.Count();
       
  3587         if (num_ifcsets == 255)
       
  3588             {
       
  3589             __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Too many interfaces already exist: 255"));
       
  3590             return NULL;
       
  3591             }
       
  3592         // Find the smallest interface number that has not yet been used.
       
  3593         for (ifcset = 0; ifcset < 256; ++ifcset)
       
  3594             {
       
  3595             TBool n_used = EFalse;
       
  3596             for (TInt i = 0; i < num_ifcsets; ++i)
       
  3597                 {
       
  3598                 if ((iConfigs[0]->iInterfaceSets[i]->iInterfaceNumber) == ifcset)
       
  3599                     {
       
  3600                     __KTRACE_OPT(KUSB, Kern::Printf("  interface number %d already used", ifcset));
       
  3601                     n_used = ETrue;
       
  3602                     break;
       
  3603                     }
       
  3604                 }
       
  3605             if (!n_used)
       
  3606                 {
       
  3607                 break;
       
  3608                 }
       
  3609             }
       
  3610         if (ifcset == 256)
       
  3611             {
       
  3612             __KTRACE_OPT(KPANIC, Kern::Printf("  Error: no available interface number found"));
       
  3613             return NULL;
       
  3614             }
       
  3615         // append the ifcset
       
  3616         __KTRACE_OPT(KUSB, Kern::Printf("  creating new InterfaceSet %d first", ifcset));
       
  3617         if (aIfc != 0)
       
  3618             {
       
  3619             __KTRACE_OPT(KPANIC, Kern::Printf("  Error: invalid interface setting number (1): %d", aIfc));
       
  3620             return NULL;
       
  3621             }
       
  3622         if ((ifcset_ptr = new TUsbcInterfaceSet(aClientId, ifcset)) == NULL)
       
  3623             {
       
  3624             __KTRACE_OPT(KPANIC,
       
  3625                          Kern::Printf("  Error: new TUsbcInterfaceSet(aClientId, ifcset_num) failed"));
       
  3626             return NULL;
       
  3627             }
       
  3628         iConfigs[0]->iInterfaceSets.Append(ifcset_ptr);
       
  3629         }
       
  3630     else /* if (ifcset_num >= 0) */
       
  3631         {
       
  3632         // use an existent ifcset
       
  3633         new_ifc = EFalse;
       
  3634         __KTRACE_OPT(KUSB, Kern::Printf("  using existing InterfaceSet %d", ifcset));
       
  3635         ifcset_ptr = InterfaceNumber2InterfacePointer(ifcset);
       
  3636         if (aIfc != ifcset_ptr->iInterfaces.Count())
       
  3637             {
       
  3638             // 9.2.3: "Alternate settings range from zero to one less than the number of alternate
       
  3639             // settings for a specific interface." (Thus we can here only append a setting.)
       
  3640             __KTRACE_OPT(KPANIC, Kern::Printf("  Error: invalid interface setting number (2): %d", aIfc));
       
  3641             return NULL;
       
  3642             }
       
  3643         // Check whether the existing interface belongs indeed to this client
       
  3644         if (ifcset_ptr->iClientId != aClientId)
       
  3645             {
       
  3646             __KTRACE_OPT(KPANIC, Kern::Printf("  Error: iClientId (%p) != aClientId (%p)",
       
  3647                                               ifcset_ptr->iClientId, aClientId));
       
  3648             return NULL;
       
  3649             }
       
  3650         }
       
  3651     const TBool no_ep0_requests = aFeatureWord & KUsbcInterfaceInfo_NoEp0RequestsPlease;
       
  3652     TUsbcInterface* const ifc_ptr = new TUsbcInterface(ifcset_ptr, aIfc, no_ep0_requests);
       
  3653     if (!ifc_ptr)
       
  3654         {
       
  3655         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: new TUsbcInterface(ifcset, aIfc) failed"));
       
  3656         if (new_ifc)
       
  3657             {
       
  3658             DeleteInterfaceSet(ifcset);
       
  3659             }
       
  3660         return NULL;
       
  3661         }
       
  3662     ifcset_ptr->iInterfaces.Append(ifc_ptr);
       
  3663     return ifc_ptr;
       
  3664     }
       
  3665 
       
  3666 
       
  3667 #define RESET_SETTINGRESERVE \
       
  3668     for (TInt i = start_ep; i < iDeviceTotalEndpoints; i++) \
       
  3669         { \
       
  3670         if (iRealEndpoints[i].iSettingReserve) \
       
  3671             iRealEndpoints[i].iSettingReserve = EFalse; \
       
  3672         } \
       
  3673 
       
  3674 TInt DUsbClientController::CreateEndpoints(TUsbcInterface* aIfc, TInt aEndpointsUsed,
       
  3675                                            const TUsbcEndpointInfoArray& aEndpointData,
       
  3676                                            TInt aRealEpNumbers[])
       
  3677     {
       
  3678     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CreateEndpoints()"));
       
  3679     const TInt ifc_num = aIfc->iInterfaceSet->iInterfaceNumber;
       
  3680     const TInt start_ep = 2;
       
  3681     for (TInt i = 0; i < aEndpointsUsed; ++i)
       
  3682         {
       
  3683         for (TInt j = start_ep; j < iDeviceTotalEndpoints; ++j)
       
  3684             {
       
  3685             if (iRealEndpoints[j].EndpointSuitable(&aEndpointData[i], ifc_num))
       
  3686                 {
       
  3687                 // Logical endpoints are numbered 1..KMaxEndpointsPerClient (virtual 0 is real 0 and 1)
       
  3688                 TUsbcLogicalEndpoint* const ep = new TUsbcLogicalEndpoint(this, i + 1, aEndpointData[i],
       
  3689                                                                           aIfc, &iRealEndpoints[j]);
       
  3690                 if (!ep)
       
  3691                     {
       
  3692                     __KTRACE_OPT(KPANIC, Kern::Printf("  Error: new TUsbcLogicalEndpoint() failed"));
       
  3693                     aIfc->iEndpoints.ResetAndDestroy();
       
  3694                     RESET_SETTINGRESERVE;
       
  3695                     return KErrNoMemory;
       
  3696                     }
       
  3697                 aIfc->iEndpoints.Append(ep);
       
  3698                 // Check on logical endpoint's sizes for compliance with special restrictions.
       
  3699                 if (aIfc->iSettingCode == 0)
       
  3700                     {
       
  3701                     // For details see last paragraph of 5.7.3 "Interrupt Transfer Packet Size Constraints".
       
  3702                     if ((ep->iInfo.iType == UsbShai::KUsbEpTypeInterrupt) && (ep->iEpSize_Hs > 64))
       
  3703                         {
       
  3704                         __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: INT ep HS size = %d on default ifc setting",
       
  3705                                                           ep->iEpSize_Hs));
       
  3706                         __KTRACE_OPT(KPANIC, Kern::Printf("           (should be <= 64)"));
       
  3707                         }
       
  3708                     // For details see last paragraph of 5.6.3 "Isochronous Transfer Packet Size Constraints".
       
  3709                     else if ((ep->iInfo.iType == UsbShai::KUsbEpTypeIsochronous) && (ep->iInfo.iSize > 0))
       
  3710                         {
       
  3711                         __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: ISO ep size = %d on default ifc setting",
       
  3712                                                           ep->iInfo.iSize));
       
  3713                         __KTRACE_OPT(KPANIC, Kern::Printf("           (should be zero or ep non-existent)"));
       
  3714                         }
       
  3715                     }
       
  3716                 // If the endpoint doesn't support DMA (now or never) the next operation
       
  3717                 // will be a successful no-op.
       
  3718                 /*
       
  3719                 const TInt r = OpenDmaChannel(j);
       
  3720                 if (r != KErrNone)
       
  3721                     {
       
  3722                     __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Opening of DMA channel failed"));
       
  3723                     aIfc->iEndpoints.ResetAndDestroy();
       
  3724                     RESET_SETTINGRESERVE;
       
  3725                     return r;
       
  3726                     }
       
  3727                 */
       
  3728                 __KTRACE_OPT(KUSB, Kern::Printf("  creating ep: mapping real ep %d -> logical ep %d",
       
  3729                                                 j, i + 1));
       
  3730                 iRealEndpoints[j].iIfcNumber = &aIfc->iInterfaceSet->iInterfaceNumber;
       
  3731                 iRealEndpoints[j].iSettingReserve = ETrue;
       
  3732                 __KTRACE_OPT(KUSB,
       
  3733                              Kern::Printf("  ep->iInfo: iType=0x%x iDir=0x%x iSize=%d iInterval=%d",
       
  3734                                           ep->iInfo.iType, ep->iInfo.iDir, ep->iInfo.iSize,
       
  3735                                           ep->iInfo.iInterval));
       
  3736                 __KTRACE_OPT(KUSB,
       
  3737                              Kern::Printf("  ep->iInfo: iInterval_Hs=%d iTransactions=%d iExtra=%d",
       
  3738                                           ep->iInfo.iInterval_Hs, ep->iInfo.iTransactions,
       
  3739                                           ep->iInfo.iExtra));
       
  3740                 // Store real endpoint numbers:
       
  3741                 // array[x] holds the number for logical ep x.
       
  3742                 aRealEpNumbers[i + 1] = j;
       
  3743                 break;
       
  3744                 }
       
  3745             }
       
  3746         }
       
  3747     aRealEpNumbers[0] = 0;                                // ep0: 0.
       
  3748     __KTRACE_OPT(KUSB,{
       
  3749         Kern::Printf("  Endpoint Mapping for Interface %d / Setting %d:", ifc_num, aIfc->iSettingCode);
       
  3750         Kern::Printf("Logical  | Real");
       
  3751         Kern::Printf("Endpoint | Endpoint");
       
  3752         for (TInt ep = 0; ep <= aEndpointsUsed; ++ep) Kern::Printf("   %2d       %3d",ep, aRealEpNumbers[ep]);
       
  3753         });
       
  3754     RESET_SETTINGRESERVE;
       
  3755     return KErrNone;
       
  3756     }
       
  3757 
       
  3758 
       
  3759 TInt DUsbClientController::SetupIfcDescriptor(TUsbcInterface* aIfc, TUsbcClassInfo& aClass, DThread* aThread,
       
  3760                                               TDesC8* aString, const TUsbcEndpointInfoArray& aEndpointData)
       
  3761     {
       
  3762     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetupIfcDescriptor()"));
       
  3763 
       
  3764     // Interface descriptor
       
  3765     TUsbcDescriptorBase* d = TUsbcInterfaceDescriptor::New(aIfc->iInterfaceSet->iInterfaceNumber,
       
  3766                                                            aIfc->iSettingCode,
       
  3767                                                            aIfc->iEndpoints.Count(),
       
  3768                                                            aClass);
       
  3769     if (!d)
       
  3770         {
       
  3771         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for ifc desc failed."));
       
  3772         return KErrNoMemory;
       
  3773         }
       
  3774     iDescriptors.InsertDescriptor(d);
       
  3775 
       
  3776     // Interface string descriptor
       
  3777     if (aString)
       
  3778         {
       
  3779         // we don't know the length of the string, so we have to allocate memory dynamically
       
  3780         TUint strlen = Kern::ThreadGetDesLength(aThread, aString);
       
  3781         if (strlen > KUsbStringDescStringMaxSize)
       
  3782             {
       
  3783             __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: $ descriptor too long - string will be truncated"));
       
  3784             strlen = KUsbStringDescStringMaxSize;
       
  3785             }
       
  3786         HBuf8* const stringbuf = HBuf8::New(strlen);
       
  3787         if (!stringbuf)
       
  3788             {
       
  3789             __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for ifc $ desc string failed."));
       
  3790             iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber,
       
  3791                                              aIfc->iSettingCode);
       
  3792             return KErrNoMemory;
       
  3793             }
       
  3794         stringbuf->SetMax();
       
  3795         // the aString points to data that lives in user memory, so we have to copy it:
       
  3796         TInt r = Kern::ThreadDesRead(aThread, aString, *stringbuf, 0);
       
  3797         if (r != KErrNone)
       
  3798             {
       
  3799             __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Thread read error"));
       
  3800             iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber,
       
  3801                                              aIfc->iSettingCode);
       
  3802             delete stringbuf;
       
  3803             return r;
       
  3804             }
       
  3805         TUsbcStringDescriptor* const sd = TUsbcStringDescriptor::New(*stringbuf);
       
  3806         if (!sd)
       
  3807             {
       
  3808             __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for ifc $ desc failed."));
       
  3809             iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber,
       
  3810                                              aIfc->iSettingCode);
       
  3811             delete stringbuf;
       
  3812             return KErrNoMemory;
       
  3813             }
       
  3814         iDescriptors.SetIfcStringDescriptor(sd, aIfc->iInterfaceSet->iInterfaceNumber, aIfc->iSettingCode);
       
  3815         delete stringbuf;                                    // the (EPOC) descriptor was copied by New()
       
  3816         }
       
  3817 
       
  3818     // Endpoint descriptors
       
  3819     for (TInt i = 0; i < aIfc->iEndpoints.Count(); ++i)
       
  3820         {
       
  3821         // The reason for using another function argument for Endpoint Info
       
  3822         // (and not possibly - similar to the Endpoint Address -
       
  3823         // "aIfc->iEndpoints[i]->iPEndpoint->iLEndpoint->iInfo") is that this time
       
  3824         // there are no logical endpoints associated with our real endpoints,
       
  3825         // i.e. iLEndpoint is NULL!.
       
  3826         if (aEndpointData[i].iExtra)
       
  3827             {
       
  3828             // if a non-standard endpoint descriptor is requested...
       
  3829             if (aEndpointData[i].iExtra != 2)
       
  3830                 {
       
  3831                 // ...then it must be a Audio Class endpoint descriptor. Else...
       
  3832                 __KTRACE_OPT(KPANIC, Kern::Printf("  Error: EP desc extension > 2 bytes (%d)",
       
  3833                                                   aEndpointData[i].iExtra));
       
  3834                 iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber,
       
  3835                                                  aIfc->iSettingCode);
       
  3836                 return KErrArgument;
       
  3837                 }
       
  3838             d = TUsbcAudioEndpointDescriptor::New(aIfc->iEndpoints[i]->iPEndpoint->iEndpointAddr,
       
  3839                                                   aEndpointData[i]);
       
  3840             }
       
  3841         else
       
  3842             {
       
  3843             d = TUsbcEndpointDescriptor::New(aIfc->iEndpoints[i]->iPEndpoint->iEndpointAddr,
       
  3844                                              aEndpointData[i]);
       
  3845             }
       
  3846         if (!d)
       
  3847             {
       
  3848             __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for ep desc #%d failed.", i));
       
  3849             iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber,
       
  3850                                              aIfc->iSettingCode);
       
  3851             return KErrNoMemory;
       
  3852             }
       
  3853         iDescriptors.InsertDescriptor(d);
       
  3854         }
       
  3855 
       
  3856     return KErrNone;
       
  3857     }
       
  3858 
       
  3859 
       
  3860 TInt DUsbClientController::ClientId2InterfaceNumber(const DBase* aClientId) const
       
  3861     {
       
  3862     const TInt num_ifcsets = iConfigs[0]->iInterfaceSets.Count();
       
  3863     for (TInt i = 0; i < num_ifcsets; ++i)
       
  3864         {
       
  3865         if (iConfigs[0]->iInterfaceSets[i]->iClientId == aClientId)
       
  3866             {
       
  3867             return iConfigs[0]->iInterfaceSets[i]->iInterfaceNumber;
       
  3868             }
       
  3869         }
       
  3870     return -1;
       
  3871     }
       
  3872 
       
  3873 
       
  3874 TUsbcInterfaceSet* DUsbClientController::ClientId2InterfacePointer(const DBase* aClientId) const
       
  3875     {
       
  3876     const TInt num_ifcsets = iConfigs[0]->iInterfaceSets.Count();
       
  3877     for (TInt i = 0; i < num_ifcsets; ++i)
       
  3878         {
       
  3879         if (iConfigs[0]->iInterfaceSets[i]->iClientId == aClientId)
       
  3880             {
       
  3881             return iConfigs[0]->iInterfaceSets[i];
       
  3882             }
       
  3883         }
       
  3884     return NULL;
       
  3885     }
       
  3886 
       
  3887 
       
  3888 const DBase* DUsbClientController::InterfaceNumber2ClientId(TInt aIfcSet) const
       
  3889     {
       
  3890     if (!InterfaceExists(aIfcSet))
       
  3891         {
       
  3892         return NULL;
       
  3893         }
       
  3894     return InterfaceNumber2InterfacePointer(aIfcSet)->iClientId;
       
  3895     }
       
  3896 
       
  3897 
       
  3898 TUsbcInterfaceSet* DUsbClientController::InterfaceNumber2InterfacePointer(TInt aIfcSet) const
       
  3899     {
       
  3900     const TInt num_ifcsets = iConfigs[0]->iInterfaceSets.Count();
       
  3901     for (TInt i = 0; i < num_ifcsets; ++i)
       
  3902         {
       
  3903         if ((iConfigs[0]->iInterfaceSets[i]->iInterfaceNumber) == aIfcSet)
       
  3904             {
       
  3905             return iConfigs[0]->iInterfaceSets[i];
       
  3906             }
       
  3907         }
       
  3908     return NULL;
       
  3909     }
       
  3910 
       
  3911 
       
  3912 TInt DUsbClientController::ActivateHardwareController()
       
  3913     {
       
  3914     __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::ActivateHardwareController()"));
       
  3915     
       
  3916     // iStackIsActive must be ETrue at this time
       
  3917     // the caller of this function shall checked that iStackIsActive is ETrue
       
  3918     __ASSERT_DEBUG(iStackIsActive, Kern::Fault(KUsbPILPanicCat, __LINE__));   
       
  3919     
       
  3920     if (iHardwareActivated)
       
  3921         {
       
  3922         __KTRACE_OPT(KUSB, Kern::Printf("  already active -> returning"));
       
  3923         return KErrNone;
       
  3924         }
       
  3925     // Initialise HW
       
  3926     TInt r = iController.StartPeripheralController();
       
  3927     if (r != KErrNone)
       
  3928         {
       
  3929         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: StartPeripheralController() failed"));
       
  3930         return KErrHardwareNotAvailable;
       
  3931         }
       
  3932     
       
  3933     iHardwareActivated = ETrue;
       
  3934 
       
  3935     // Configure & enable endpoint zero
       
  3936     const TUsbcLogicalEndpoint* const ep0_0 = iRealEndpoints[0].iLEndpoint;
       
  3937     const TUsbcLogicalEndpoint* const ep0_1 = iRealEndpoints[1].iLEndpoint;
       
  3938     if (iHighSpeed)
       
  3939         {
       
  3940         const_cast<TUsbcLogicalEndpoint*>(ep0_0)->iInfo.iSize = ep0_0->iEpSize_Hs;
       
  3941         const_cast<TUsbcLogicalEndpoint*>(ep0_1)->iInfo.iSize = ep0_1->iEpSize_Hs;
       
  3942         }
       
  3943     else
       
  3944         {
       
  3945         const_cast<TUsbcLogicalEndpoint*>(ep0_0)->iInfo.iSize = ep0_0->iEpSize_Fs;
       
  3946         const_cast<TUsbcLogicalEndpoint*>(ep0_1)->iInfo.iSize = ep0_1->iEpSize_Fs;
       
  3947         }
       
  3948     iController.ConfigureEndpoint(0, ep0_0->iInfo);
       
  3949     iController.ConfigureEndpoint(1, ep0_1->iInfo);
       
  3950     iEp0MaxPacketSize = ep0_0->iInfo.iSize;
       
  3951 
       
  3952     __KTRACE_OPT(KUSB, Kern::Printf("  Controller activated."));
       
  3953     
       
  3954     // Controller is powered up, changes device state to powered
       
  3955     NextDeviceState(UsbShai::EUsbPeripheralStatePowered);
       
  3956     
       
  3957     __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::ActivateHardwareController()"));
       
  3958     return  KErrNone;;
       
  3959     }
       
  3960 
       
  3961 
       
  3962 void DUsbClientController::DeActivateHardwareController()
       
  3963     {
       
  3964     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeActivateHardwareController()"));
       
  3965     if (!iHardwareActivated)
       
  3966         {
       
  3967         __KTRACE_OPT(KUSB, Kern::Printf("  not active -> returning"));
       
  3968         return;
       
  3969         }
       
  3970     // Deconfigure & disable endpoint zero
       
  3971     iController.DeConfigureEndpoint(KEp0_Out);
       
  3972     iController.DeConfigureEndpoint(KEp0_In);
       
  3973     // Stop HW
       
  3974     iController.StopPeripheralController();
       
  3975     iHardwareActivated = EFalse;
       
  3976     __KTRACE_OPT(KUSB, Kern::Printf("  Controller deactivated."));
       
  3977     
       
  3978     // Always go to attached state, until statck is disabled
       
  3979     NextDeviceState(UsbShai::EUsbPeripheralStateAttached);
       
  3980     
       
  3981     return;
       
  3982     }
       
  3983 
       
  3984 
       
  3985 void DUsbClientController::DeleteInterfaceSet(TInt aIfcSet)
       
  3986     {
       
  3987     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteInterfaceSet(%d)", aIfcSet));
       
  3988     TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(aIfcSet);
       
  3989     if (!ifcset_ptr)
       
  3990         {
       
  3991         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: invalid interface number: %d", aIfcSet));
       
  3992         return;
       
  3993         }
       
  3994     const TInt idx = iConfigs[0]->iInterfaceSets.Find(ifcset_ptr);
       
  3995     if (idx == KErrNotFound)
       
  3996         {
       
  3997         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: interface not found in array"));
       
  3998         return;
       
  3999         }
       
  4000     //Add this mutex to protect the interface set data structure
       
  4001     if (NKern::CurrentContext() == EThread)
       
  4002         {
       
  4003         NKern::FMWait(&iMutex);
       
  4004         }
       
  4005     
       
  4006     iConfigs[0]->iInterfaceSets.Remove(idx);
       
  4007     if (NKern::CurrentContext() == EThread)
       
  4008         {
       
  4009         NKern::FMSignal(&iMutex);    
       
  4010         }
       
  4011     delete ifcset_ptr;
       
  4012     }
       
  4013 
       
  4014 
       
  4015 void DUsbClientController::DeleteInterface(TInt aIfcSet, TInt aIfc)
       
  4016     {
       
  4017     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteInterface(%d, %d)", aIfcSet, aIfc));
       
  4018     TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(aIfcSet);
       
  4019     if (!ifcset_ptr)
       
  4020         {
       
  4021         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: invalid interface number: %d", aIfcSet));
       
  4022         return;
       
  4023         }
       
  4024     if (ifcset_ptr->iInterfaces.Count() <= aIfc)
       
  4025         {
       
  4026         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: invalid interface setting: %d", aIfc));
       
  4027         return;
       
  4028         }
       
  4029     //Add this mutex to protect the interface set data structure
       
  4030     if (NKern::CurrentContext() == EThread)
       
  4031         {
       
  4032         NKern::FMWait(&iMutex);
       
  4033         }    
       
  4034     TUsbcInterface* const ifc_ptr = ifcset_ptr->iInterfaces[aIfc];
       
  4035     // Always first remove, then delete (see ~TUsbcLogicalEndpoint() for the reason why)
       
  4036     ifcset_ptr->iInterfaces.Remove(aIfc);
       
  4037 
       
  4038     if (aIfc == ifcset_ptr->iCurrentInterface)
       
  4039         {
       
  4040         __KTRACE_OPT(KUSB, Kern::Printf(" > Warning: deleting current interface setting"));
       
  4041         ifcset_ptr->iCurrentInterface = 0;
       
  4042         }
       
  4043     if (NKern::CurrentContext() == EThread)
       
  4044         {
       
  4045         NKern::FMSignal(&iMutex);
       
  4046         }    
       
  4047     delete ifc_ptr;
       
  4048     }
       
  4049 
       
  4050 
       
  4051 void DUsbClientController::CancelTransferRequests(TInt aRealEndpoint)
       
  4052     {
       
  4053     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CancelTransferRequests(aRealEndpoint=%d)",
       
  4054                                     aRealEndpoint));
       
  4055     const DBase* const clientId = PEndpoint2ClientId(aRealEndpoint);
       
  4056     if (EpIdx2Addr(aRealEndpoint) & KUsbEpAddress_In)
       
  4057         {
       
  4058         CancelWriteBuffer(clientId, aRealEndpoint);
       
  4059         }
       
  4060     else
       
  4061         {
       
  4062         CancelReadBuffer(clientId, aRealEndpoint);
       
  4063         }
       
  4064     }
       
  4065 
       
  4066 
       
  4067 void DUsbClientController::DeleteRequestCallback(const DBase* aClientId, TInt aEndpointNum,
       
  4068                                                  UsbShai::TTransferDirection aTransferDir)
       
  4069     {
       
  4070     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteRequestCallback()"));
       
  4071     // Ep0 OUT
       
  4072     if (aEndpointNum == 0)
       
  4073         {
       
  4074         const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
       
  4075         TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks);
       
  4076         TUsbcRequestCallback* p;
       
  4077         while ((p = iter++) != NULL)
       
  4078             {
       
  4079             if (p->Owner() == aClientId)
       
  4080                 {
       
  4081                 __ASSERT_DEBUG((p->iRealEpNum == 0), Kern::Fault(KUsbPILPanicCat, __LINE__));
       
  4082                 __ASSERT_DEBUG((p->iTransferDir == UsbShai::EControllerRead), Kern::Fault(KUsbPILPanicCat, __LINE__));
       
  4083                 __KTRACE_OPT(KUSB, Kern::Printf("  removing RequestCallback @ 0x%x (ep0)", p));
       
  4084                 iEp0ReadRequestCallbacks.Remove(*p);
       
  4085                 }
       
  4086             }
       
  4087         __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
       
  4088         return;
       
  4089         }
       
  4090     // Other endpoints
       
  4091     TUsbcRequestCallback* const p = iRequestCallbacks[aEndpointNum];
       
  4092     if (p)
       
  4093         {
       
  4094          __ASSERT_DEBUG((p->Owner() == aClientId), Kern::Fault(KUsbPILPanicCat, __LINE__));
       
  4095         __ASSERT_DEBUG((p->iTransferDir == aTransferDir), Kern::Fault(KUsbPILPanicCat, __LINE__));
       
  4096         __KTRACE_OPT(KUSB, Kern::Printf("  removing RequestCallback @ 0x%x", p));
       
  4097         iRequestCallbacks[aEndpointNum] = NULL;
       
  4098         }
       
  4099     }
       
  4100 
       
  4101 
       
  4102 void DUsbClientController::DeleteRequestCallbacks(const DBase* aClientId)
       
  4103     {
       
  4104     // aClientId being NULL means: delete all requests for *all* clients.
       
  4105     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteRequestCallbacks()"));
       
  4106     // Ep0 OUT
       
  4107     const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
       
  4108     TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks);
       
  4109     TUsbcRequestCallback* p;
       
  4110     while ((p = iter++) != NULL)
       
  4111         {
       
  4112         if (!aClientId || p->Owner() == aClientId)
       
  4113             {
       
  4114             __KTRACE_OPT(KUSB, Kern::Printf("  removing RequestCallback @ 0x%x (ep0)", p));
       
  4115             iEp0ReadRequestCallbacks.Remove(*p);
       
  4116             }
       
  4117         }
       
  4118     __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
       
  4119     // Other endpoints
       
  4120     for (TInt i = 1; i < KUsbcEpArraySize; i++)
       
  4121         {
       
  4122         TUsbcRequestCallback* const p = iRequestCallbacks[i];
       
  4123         if (p && (!aClientId || p->Owner() == aClientId))
       
  4124             {
       
  4125             __KTRACE_OPT(KUSB, Kern::Printf("  removing RequestCallback @ 0x%x", p));
       
  4126             iRequestCallbacks[i] = NULL;
       
  4127             }
       
  4128         }
       
  4129     }
       
  4130 
       
  4131 
       
  4132 void DUsbClientController::StatusNotify(UsbShai::TUsbPeripheralState aState, const DBase* aClientId)
       
  4133     {
       
  4134     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::StatusNotify()"));
       
  4135 
       
  4136     // This function may be called by the PSL (via chapter9.cpp) from within an
       
  4137     // ISR -- so we have to take care what we do here (and also in all
       
  4138     // functions that get called from here).
       
  4139 
       
  4140     TSglQueIter<TUsbcStatusCallback> iter(iStatusCallbacks);
       
  4141     TUsbcStatusCallback* p;
       
  4142     while ((p = iter++) != NULL)
       
  4143         {
       
  4144         if (!aClientId || aClientId == p->Owner())
       
  4145             {
       
  4146             __KTRACE_OPT(KUSB, Kern::Printf("  notifying LDD @ 0x%x about %d", p->Owner(), aState));
       
  4147             p->SetState(aState);
       
  4148             p->DoCallback();
       
  4149             }
       
  4150         }
       
  4151     }
       
  4152 
       
  4153 
       
  4154 void DUsbClientController::EpStatusNotify(TInt aRealEndpoint)
       
  4155     {
       
  4156     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EpStatusNotify()"));
       
  4157 
       
  4158     // This function may be called by the PSL (via chapter9.cpp) from within an
       
  4159     // ISR -- so we have to take care what we do here (and also in all
       
  4160     // functions that get called from here).
       
  4161 
       
  4162     const DBase* const client_id = PEndpoint2ClientId(aRealEndpoint);
       
  4163     if (!client_id)
       
  4164         {
       
  4165         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Client not found for real ep %d", aRealEndpoint));
       
  4166         return;
       
  4167         }
       
  4168     // Check if there is a notification request queued for that client (if not, we can return here).
       
  4169     TSglQueIter<TUsbcEndpointStatusCallback> iter(iEpStatusCallbacks);
       
  4170     TUsbcEndpointStatusCallback* p;
       
  4171     while ((p = iter++) != NULL)
       
  4172         {
       
  4173         if (p->Owner() == client_id)
       
  4174             {
       
  4175             break;
       
  4176             }
       
  4177         }
       
  4178     if (!p)
       
  4179         {
       
  4180         __KTRACE_OPT(KUSB, Kern::Printf("  No notification request for that client, returning"));
       
  4181         return;
       
  4182         }
       
  4183     const TInt ifcset = ClientId2InterfaceNumber(client_id);
       
  4184     if (ifcset < 0)
       
  4185         {
       
  4186         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Ifcset not found for clientid %d", client_id));
       
  4187         return;
       
  4188         }
       
  4189     const TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(ifcset);
       
  4190     if (!ifcset_ptr)
       
  4191         {
       
  4192         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Ifcset pointer not found for ifcset %d", ifcset));
       
  4193         return;
       
  4194         }
       
  4195     const TUsbcInterface* const ifc_ptr = ifcset_ptr->CurrentInterface();
       
  4196     if (!ifc_ptr)
       
  4197         {
       
  4198         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Current ifc pointer not found for ifcset %d", ifcset));
       
  4199         return;
       
  4200         }
       
  4201     TUint state = 0;
       
  4202     const TInt eps = ifc_ptr->iEndpoints.Count();
       
  4203     for (TInt i = 0; i < eps; i++)
       
  4204         {
       
  4205         const TUsbcLogicalEndpoint* const ep_ptr = ifc_ptr->iEndpoints[i];
       
  4206         __KTRACE_OPT(KUSB, Kern::Printf("  checking logical ep #%d for stall state...",
       
  4207                                         ep_ptr->iLEndpointNum));
       
  4208         if (ep_ptr->iPEndpoint->iHalt)
       
  4209             {
       
  4210             __KTRACE_OPT(KUSB, Kern::Printf("  -- stalled"));
       
  4211             // set the bit n to 1, where n is the logical endpoint number minus one
       
  4212             state |= (1 << (ep_ptr->iLEndpointNum - 1));
       
  4213             }
       
  4214         else
       
  4215             {
       
  4216             __KTRACE_OPT(KUSB, Kern::Printf("  -- not stalled"));
       
  4217             }
       
  4218         }
       
  4219     __KTRACE_OPT(KUSB, Kern::Printf(" passing ep state 0x%x on to LDD @ 0x%x", state, client_id));
       
  4220     p->SetState(state);
       
  4221     p->DoCallback();
       
  4222     }
       
  4223 
       
  4224 
       
  4225 void DUsbClientController::OtgFeaturesNotify()
       
  4226     {
       
  4227     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::OtgFeaturesNotify()"));
       
  4228 
       
  4229     // This function may be called from the PSL (via PIL's chapter9.cpp) from
       
  4230     // within an ISR -- so we have to take care what we do here (and also in
       
  4231     // all functions that get called from here).
       
  4232 
       
  4233     TSglQueIter<TUsbcOtgFeatureCallback> iter(iOtgCallbacks);
       
  4234     TUsbcOtgFeatureCallback* p;
       
  4235     while ((p = iter++) != NULL)
       
  4236         {
       
  4237         p->SetFeatures(iOtgFuncMap & 0x1C);
       
  4238         p->DoCallback();
       
  4239         }
       
  4240     }
       
  4241 
       
  4242 
       
  4243 void DUsbClientController::RunClientCallbacks()
       
  4244     {
       
  4245     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RunClientCallbacks()"));
       
  4246     TSglQueIter<TUsbcClientCallback> iter(iClientCallbacks);
       
  4247     TUsbcClientCallback* p;
       
  4248     while ((p = iter++) != NULL)
       
  4249         {
       
  4250         __KTRACE_OPT(KUSB, Kern::Printf("Callback 0x%x", p));
       
  4251         p->DoCallback();
       
  4252         }
       
  4253     }
       
  4254 
       
  4255 
       
  4256 void DUsbClientController::ProcessDataTransferDone(TUsbcRequestCallback& aRcb)
       
  4257     {
       
  4258     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessDataTransferDone()"));
       
  4259     // This piece can only be called in thread context from ProcessEp0DataReceived() /
       
  4260     // ProcessEp0SetupReceived() via the call to ProcessEp0ReceiveDone() in
       
  4261     // SetupReadBuffer(), which is guarded by an interrupt lock.
       
  4262     TInt ep = aRcb.iRealEpNum;
       
  4263     if (ep == 0)
       
  4264         {
       
  4265         if (aRcb.iTransferDir == UsbShai::EControllerRead)
       
  4266             {
       
  4267             // Ep0 OUT is special
       
  4268             iEp0ReadRequestCallbacks.Remove(aRcb);
       
  4269             }
       
  4270         else                                                // UsbShai::EControllerWrite
       
  4271             {
       
  4272             // Ep0 IN needs to be adjusted: it's '1' within the PIL.
       
  4273             ep = KEp0_Tx;
       
  4274             }
       
  4275         }
       
  4276     if (ep > 0)                                                // not 'else'!
       
  4277         {
       
  4278         __ASSERT_DEBUG((iRequestCallbacks[ep] == &aRcb), Kern::Fault(KUsbPILPanicCat, __LINE__));
       
  4279         __KTRACE_OPT(KUSB, Kern::Printf(" > removing RequestCallback[%d] @ 0x%x", ep, &aRcb));
       
  4280         iRequestCallbacks[ep] = NULL;
       
  4281         }
       
  4282     aRcb.DoCallback();
       
  4283     }
       
  4284 
       
  4285 
       
  4286 void DUsbClientController::NextDeviceState(UsbShai::TUsbPeripheralState aNextState)
       
  4287     {
       
  4288     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::NextDeviceState()"));
       
  4289 #ifdef _DEBUG
       
  4290     const char* const states[] = {"Undefined", "Attached", "Powered", "Default",
       
  4291                                   "Address", "Configured", "Suspended"};
       
  4292     if ((aNextState >= UsbShai::EUsbPeripheralStateUndefined) &&
       
  4293         (aNextState <= UsbShai::EUsbPeripheralStateSuspended))
       
  4294         {
       
  4295         __KTRACE_OPT(KUSB, Kern::Printf("  next device state: %s", states[aNextState]));
       
  4296         }
       
  4297     else
       
  4298         {
       
  4299         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Unknown next device state: %d", aNextState));
       
  4300         }
       
  4301     // Print a warning when an invalid state transition is detected
       
  4302     // 'Undefined' is not a state that is mentioned in the USB spec, but
       
  4303     // that's what we're in once the cable gets pulled (for instance).
       
  4304     switch (iDeviceState)
       
  4305         {
       
  4306     case UsbShai::EUsbPeripheralStateUndefined:
       
  4307         // valid: Undefined -> Attached
       
  4308         if (aNextState != UsbShai::EUsbPeripheralStateAttached)
       
  4309             break;
       
  4310         goto OK;
       
  4311     case UsbShai::EUsbPeripheralStateAttached:
       
  4312         // valid: Attached -> {Undefined, Powered}
       
  4313         if ((aNextState != UsbShai::EUsbPeripheralStateUndefined) &&
       
  4314             (aNextState != UsbShai::EUsbPeripheralStatePowered))
       
  4315             break;
       
  4316         goto OK;
       
  4317     case UsbShai::EUsbPeripheralStatePowered:
       
  4318         // valid: Powered -> {Undefined, Attached, Default, Suspended}
       
  4319         if ((aNextState != UsbShai::EUsbPeripheralStateUndefined) &&
       
  4320             (aNextState != UsbShai::EUsbPeripheralStateAttached) &&
       
  4321             (aNextState != UsbShai::EUsbPeripheralStateDefault)     &&
       
  4322             (aNextState != UsbShai::EUsbPeripheralStateSuspended))
       
  4323             break;
       
  4324         goto OK;
       
  4325     case UsbShai::EUsbPeripheralStateDefault:
       
  4326         // valid: Default -> {Undefined, Powered, Default, Address, Suspended}
       
  4327         if ((aNextState != UsbShai::EUsbPeripheralStateUndefined) &&
       
  4328             (aNextState != UsbShai::EUsbPeripheralStatePowered) &&
       
  4329             (aNextState != UsbShai::EUsbPeripheralStateDefault) &&
       
  4330             (aNextState != UsbShai::EUsbPeripheralStateAddress) &&
       
  4331             (aNextState != UsbShai::EUsbPeripheralStateSuspended))
       
  4332             break;
       
  4333         goto OK;
       
  4334     case UsbShai::EUsbPeripheralStateAddress:
       
  4335         // valid: Address -> {Undefined, Powered, Default, Configured, Suspended}
       
  4336         if ((aNextState != UsbShai::EUsbPeripheralStateUndefined) &&
       
  4337             (aNextState != UsbShai::EUsbPeripheralStatePowered) &&
       
  4338             (aNextState != UsbShai::EUsbPeripheralStateDefault) &&
       
  4339             (aNextState != UsbShai::EUsbPeripheralStateConfigured) &&
       
  4340             (aNextState != UsbShai::EUsbPeripheralStateSuspended))
       
  4341             break;
       
  4342         goto OK;
       
  4343     case UsbShai::EUsbPeripheralStateConfigured:
       
  4344         // valid: Configured -> {Undefined, Powered, Default, Address, Suspended}
       
  4345         if ((aNextState != UsbShai::EUsbPeripheralStateUndefined) &&
       
  4346             (aNextState != UsbShai::EUsbPeripheralStatePowered) &&
       
  4347             (aNextState != UsbShai::EUsbPeripheralStateDefault) &&
       
  4348             (aNextState != UsbShai::EUsbPeripheralStateAddress) &&
       
  4349             (aNextState != UsbShai::EUsbPeripheralStateSuspended))
       
  4350             break;
       
  4351         goto OK;
       
  4352     case UsbShai::EUsbPeripheralStateSuspended:
       
  4353         // valid: Suspended -> {Undefined, Powered, Default, Address, Configured}
       
  4354         if ((aNextState != UsbShai::EUsbPeripheralStateUndefined) &&
       
  4355             (aNextState != UsbShai::EUsbPeripheralStatePowered) &&
       
  4356             (aNextState != UsbShai::EUsbPeripheralStateDefault) &&
       
  4357             (aNextState != UsbShai::EUsbPeripheralStateAddress) &&
       
  4358             (aNextState != UsbShai::EUsbPeripheralStateConfigured))
       
  4359             break;
       
  4360         goto OK;
       
  4361     default:
       
  4362         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Unknown current device state: %d", iDeviceState));
       
  4363         goto OK;
       
  4364         }
       
  4365     // KUSB only (instead of KPANIC) so as not to worry people too much where
       
  4366     // a particular h/w regularly enforces invalid (but harmless) transitions
       
  4367     __KTRACE_OPT(KUSB, Kern::Printf("  Warning: Invalid next state from %s", states[iDeviceState]));
       
  4368 OK:
       
  4369 #endif // _DEBUG
       
  4370 
       
  4371     iDeviceState = aNextState;
       
  4372     StatusNotify(iDeviceState);
       
  4373     }
       
  4374 
       
  4375 
       
  4376 TInt DUsbClientController::ProcessSuspendEvent()
       
  4377     {
       
  4378     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSuspendEvent()"));
       
  4379     // A suspend interrupt has been received and needs attention.
       
  4380     iDeviceStateB4Suspend = iDeviceState;
       
  4381     
       
  4382     // We have to move to the Suspend state immediately (in case it's a genuine Suspend)
       
  4383     // because 7.1.7.6 says: "The device must actually be suspended, [...] after no more
       
  4384     // than 10ms of bus inactivity [...]." Assuming we got the interrupt 3ms after the
       
  4385     // Suspend condition arose, we have now 7ms left.
       
  4386     NextDeviceState(UsbShai::EUsbPeripheralStateSuspended);
       
  4387     iController.Suspend();
       
  4388     
       
  4389     return KErrNone;
       
  4390     }
       
  4391 
       
  4392 TInt DUsbClientController::ProcessResumeEvent()
       
  4393     {
       
  4394     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessResumeEvent()"));
       
  4395     if (iDeviceState == UsbShai::EUsbPeripheralStateSuspended)
       
  4396         {
       
  4397         NextDeviceState(iDeviceStateB4Suspend);
       
  4398         }
       
  4399     iController.Resume();
       
  4400     return KErrNone;
       
  4401     }
       
  4402 
       
  4403 
       
  4404 TInt DUsbClientController::ProcessResetEvent(TBool aPslUpcall)
       
  4405     {
       
  4406     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessResetEvent()"));
       
  4407 
       
  4408     if (aPslUpcall)
       
  4409         {
       
  4410         // Call back into PSL if we're coming from there.
       
  4411         // Also, do it always, even when PIL processing will be deferred.
       
  4412         iController.Reset();
       
  4413         }
       
  4414 
       
  4415     // In an OTG-environment, some OTG controllers have implemented
       
  4416     // the OTG state machine in HW and connect to the bus
       
  4417     // automatically already before the SW has indicated
       
  4418     // readiness. Peripheral PSL operating on top of such controller
       
  4419     // may report a reset event already before the upper layers are
       
  4420     // ready. In this case we defer the reset processing to after the
       
  4421     // upper layers have indicated their readiness.
       
  4422     if (iUsbResetDeferred)
       
  4423         {
       
  4424         __KTRACE_OPT(KUSB, Kern::Printf("  User-side (still) not ready -> returning"));
       
  4425         return KErrNone;
       
  4426         }
       
  4427     else if (!iClientSupportReady)
       
  4428         {
       
  4429         // Wait with the PIL Reset processing until user-side is ready
       
  4430         __KTRACE_OPT(KUSB, Kern::Printf("  User-side not ready -> deferring"));
       
  4431         iUsbResetDeferred = ETrue;
       
  4432         return KErrNone;
       
  4433         }
       
  4434 
       
  4435     if (iDeviceState == UsbShai::EUsbPeripheralStateAttached)
       
  4436         {
       
  4437         NextDeviceState(UsbShai::EUsbPeripheralStatePowered);
       
  4438         }
       
  4439     // Notify the world. (This will just queue a DFC, so users won't actually be
       
  4440     // notified before we return. But we change the device state already here so
       
  4441     // ChangeConfiguration will see the correct one.)
       
  4442     NextDeviceState(UsbShai::EUsbPeripheralStateDefault);
       
  4443     // Tear down the current configuration (never called from thread)
       
  4444     ChangeConfiguration(0);
       
  4445     // Reset essential vars
       
  4446     ResetEp0DataOutVars();
       
  4447     //iEp0_RxExtraData = EFalse;
       
  4448     iEp0WritePending = EFalse;
       
  4449     iEp0ClientDataTransmitting = EFalse;
       
  4450     
       
  4451     iLastError = KErrNone;
       
  4452     iSetupPacketPending = EFalse;
       
  4453     //iEp0_RxExtraError = 0;
       
  4454     iConTransferMgr->Reset();
       
  4455     
       
  4456     // Reset OTG features, leave attributes as is
       
  4457     iOtgFuncMap &= KUsbOtgAttr_SrpSupp | KUsbOtgAttr_HnpSupp;
       
  4458     if (iOtgSupport)
       
  4459         {
       
  4460         OtgFeaturesNotify();
       
  4461         }
       
  4462 
       
  4463     // Check whether there's a speed change
       
  4464     const TBool was_hs = iHighSpeed;
       
  4465     iHighSpeed = CurrentlyUsingHighSpeed();
       
  4466     if (!was_hs && iHighSpeed)
       
  4467         {
       
  4468         __KTRACE_OPT(KUSB, Kern::Printf("  Moving to High-speed"));
       
  4469         EnterHighSpeed();
       
  4470         }
       
  4471     else if (was_hs && !iHighSpeed)
       
  4472         {
       
  4473         __KTRACE_OPT(KUSB, Kern::Printf("  Moving to Full-speed"));
       
  4474         EnterFullSpeed();
       
  4475         }
       
  4476 
       
  4477     // Setup initial Ep0 read (SetupEndpointZeroRead never called from thread)
       
  4478     if (iConTransferMgr->SetupEndpointZeroRead() != KErrNone)
       
  4479         {
       
  4480         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: while setting up Ep0 read"));
       
  4481         return KErrGeneral;
       
  4482         }
       
  4483 
       
  4484     return KErrNone;
       
  4485     }
       
  4486 
       
  4487 
       
  4488 TInt DUsbClientController::ProcessVbusRisenEvent()
       
  4489     {
       
  4490     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessVbusRisenEvent()"));
       
  4491     if (iIsOtgPort)
       
  4492         {
       
  4493         // In an OTG environment, this notification is not expected
       
  4494         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: EUsbEventVbusRisen shouldn't be sent by an OTG Client PSL"));
       
  4495         return KErrArgument;
       
  4496         }
       
  4497     else
       
  4498         {
       
  4499         // In a non-OTG environment, seeing VBUS rising causes the
       
  4500         // peripheral stack to be enabled
       
  4501         EnablePeripheralStack();
       
  4502         return KErrNone;
       
  4503         }
       
  4504     }
       
  4505 
       
  4506 
       
  4507 TInt DUsbClientController::ProcessVbusFallenEvent()
       
  4508     {
       
  4509     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessVbusFallenEvent()"));
       
  4510     if (iIsOtgPort)
       
  4511         {
       
  4512         // In an OTG environment, this notification is not expected
       
  4513         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: EUsbEventVbusFallen shouldn't be sent by an OTG Client PSL"));
       
  4514         return KErrArgument;
       
  4515         }
       
  4516     else
       
  4517         {
       
  4518         // In a non-OTG environment, seeing VBUS falling causes the
       
  4519         // peripheral stack to be disabled
       
  4520         DisablePeripheralStack();
       
  4521         return KErrNone;
       
  4522         }
       
  4523     }
       
  4524 
       
  4525 
       
  4526 void DUsbClientController::EnterFullSpeed()
       
  4527     {
       
  4528     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EnterFullSpeed()"));
       
  4529     iDescriptors.UpdateDescriptorsFs();
       
  4530     }
       
  4531 
       
  4532 
       
  4533 void DUsbClientController::EnterHighSpeed()
       
  4534     {
       
  4535     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EnterHighSpeed()"));
       
  4536     iDescriptors.UpdateDescriptorsHs();
       
  4537     }
       
  4538 
       
  4539 
       
  4540 //
       
  4541 // DFC (static), we are runing in a DFC context.
       
  4542 //
       
  4543 void DUsbClientController::ReconnectTimerCallback(TAny *aPtr)
       
  4544     {
       
  4545     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ReconnectTimerCallback()"));
       
  4546     if (!aPtr)
       
  4547         {
       
  4548         __KTRACE_OPT(KPANIC, Kern::Printf("  Error: !aPtr"));
       
  4549         return;
       
  4550         }
       
  4551     
       
  4552     DUsbClientController* const ptr = static_cast<DUsbClientController*>(aPtr);
       
  4553     
       
  4554     ptr->UsbConnect();
       
  4555     
       
  4556     }
       
  4557 
       
  4558 //
       
  4559 // static Dfc function
       
  4560 //
       
  4561 void DUsbClientController::PowerUpDfc(TAny* aPtr)
       
  4562     {
       
  4563     __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::PowerUpDfc"));
       
  4564     if (!aPtr)
       
  4565         {
       
  4566         __KTRACE_OPT(KPANIC, Kern::Printf("     Error: !aPtr"));
       
  4567         return;
       
  4568         }
       
  4569     
       
  4570     DUsbClientController* const ptr = static_cast<DUsbClientController*>(aPtr);
       
  4571     
       
  4572     __PM_ASSERT(ptr->iStandby);
       
  4573     
       
  4574     ptr->iStandby = EFalse;
       
  4575     
       
  4576     // We have nothing to do when powerup
       
  4577     ptr->iPowerHandler->PowerUpDone();
       
  4578     
       
  4579     __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::PowerUpDfc"));
       
  4580     return ;
       
  4581     }
       
  4582 
       
  4583 //
       
  4584 // static Dfc function
       
  4585 //
       
  4586 void DUsbClientController::PowerDownDfc(TAny* aPtr)
       
  4587     {
       
  4588     __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::PowerDownDfc"));
       
  4589     if (!aPtr)
       
  4590         {
       
  4591         __KTRACE_OPT(KPANIC, Kern::Printf("     Error: !aPtr"));
       
  4592         return;
       
  4593         }
       
  4594         
       
  4595     DUsbClientController* const ptr = static_cast<DUsbClientController*>(aPtr);
       
  4596     __PM_ASSERT(!ptr->iStandby);
       
  4597     
       
  4598     ptr->iStandby = ETrue;
       
  4599     
       
  4600     // Disable stack(stop controller inside)
       
  4601     ptr->DisablePeripheralStack();
       
  4602     
       
  4603     ptr->iPowerHandler->PowerDownDone();
       
  4604     
       
  4605     __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::PowerDownDfc"));
       
  4606     return ;
       
  4607     }
       
  4608 
       
  4609 //
       
  4610 // Static Dfc function
       
  4611 //
       
  4612 void DUsbClientController::DeviceEventNotifyDfc(TAny* aPtr)
       
  4613     {
       
  4614     __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::DeviceEventNotifyDfc"));
       
  4615     DUsbClientController* const ptr = static_cast<DUsbClientController*>(aPtr);
       
  4616     
       
  4617     UsbShai::TUsbPeripheralEvent event = ptr->iDevEventQueue.FifoGet();
       
  4618     
       
  4619     if( event == -1)
       
  4620         {
       
  4621         // No event queued
       
  4622         __KTRACE_OPT(KUSB, Kern::Printf("  Warning, No event found, exit !!!"));
       
  4623         return;
       
  4624         }
       
  4625     
       
  4626     ptr->ProcessDeviceEventNotification(event);
       
  4627     __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::DeviceEventNotifyDfc"));
       
  4628     }
       
  4629 
       
  4630 //
       
  4631 // Static Dfc function
       
  4632 //    
       
  4633 void DUsbClientController::ThreadContextFinderDfc(TAny* aPtr)
       
  4634     {
       
  4635     __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::ThreadContextFinderDfc"));
       
  4636 
       
  4637     DUsbClientController* const ptr = static_cast<DUsbClientController*>(aPtr);
       
  4638     
       
  4639     ptr->iCommonDfcQThread = NKern::CurrentThread();
       
  4640     __KTRACE_OPT(KUSB, Kern::Printf("  iCommonDfcQThread = %d",ptr->iCommonDfcQThread));
       
  4641 
       
  4642     __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::ThreadContextFinderDfc"));    
       
  4643     }
       
  4644 //
       
  4645 // 
       
  4646 //
       
  4647 void DUsbClientController::ProcessDeviceEventNotification(UsbShai::TUsbPeripheralEvent aEvent)
       
  4648     {
       
  4649     __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::ProcessDeviceEventNotification %d",aEvent));    
       
  4650     // If an OTG Observer has registered, forward the event
       
  4651     // notification to it as well
       
  4652     if (iOtgObserver != NULL)
       
  4653         {
       
  4654         __KTRACE_OPT(KUSB, Kern::Printf("  Forwarding to OTG Observer"));
       
  4655         iOtgObserver->NotifyPeripheralEvent(aEvent);
       
  4656         }
       
  4657 
       
  4658     // This function may be called by the PSL from within an ISR -- so we have
       
  4659     // to take care what we do here (and also in all functions that get called
       
  4660     // from here).
       
  4661 
       
  4662     switch (aEvent)
       
  4663         {
       
  4664     case UsbShai::EUsbEventSuspend:
       
  4665         ProcessSuspendEvent();
       
  4666         break;
       
  4667     case UsbShai::EUsbEventResume:
       
  4668         ProcessResumeEvent();
       
  4669         break;
       
  4670     case UsbShai::EUsbEventReset:
       
  4671         ProcessResetEvent();
       
  4672         break;
       
  4673     case UsbShai::EUsbEventVbusRisen:
       
  4674         ProcessVbusRisenEvent();
       
  4675         break;
       
  4676     case UsbShai::EUsbEventVbusFallen:
       
  4677         ProcessVbusFallenEvent();
       
  4678         break;
       
  4679         
       
  4680     default:
       
  4681         break;
       
  4682         }
       
  4683         
       
  4684     __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::ProcessDeviceEventNotification"));    
       
  4685     }
       
  4686     
       
  4687 // Functions from UsbShai::MChargerDetectorObserverIf
       
  4688 void DUsbClientController::NotifyPortType(UsbShai::TPortType aPortType)
       
  4689     {
       
  4690     // FIXME: Not yet implemented!
       
  4691     }
       
  4692 
       
  4693 void DUsbClientController::Buffer2Setup(const TAny* aBuf, TUsbcSetup& aSetup) const
       
  4694 	{
       
  4695 	// TUint8 index
       
  4696 	aSetup.iRequestType = static_cast<const TUint8*>(aBuf)[0];
       
  4697 	aSetup.iRequest		= static_cast<const TUint8*>(aBuf)[1];
       
  4698 	// TUint16 index from here!
       
  4699 	aSetup.iValue  = SWAP_BYTES_16((static_cast<const TUint16*>(aBuf))[1]);
       
  4700 	aSetup.iIndex  = SWAP_BYTES_16((static_cast<const TUint16*>(aBuf))[2]);
       
  4701 	aSetup.iLength = SWAP_BYTES_16((static_cast<const TUint16*>(aBuf))[3]);
       
  4702 	}
       
  4703     
       
  4704 TUsbPeriDeviceEventQueue::TUsbPeriDeviceEventQueue()
       
  4705     {
       
  4706     iDeviceQueueHead = 0;
       
  4707     iDeviceQueueTail = 0;
       
  4708     }
       
  4709 
       
  4710 // FifoAdd will be called from Isr or IDfc context
       
  4711 // be careful when processing
       
  4712 void TUsbPeriDeviceEventQueue::FifoAdd(UsbShai::TUsbPeripheralEvent aDeviceEvent)
       
  4713     {
       
  4714     __KTRACE_OPT(KUSB, Kern::Printf("> TUsbPeriDeviceEventQueue::FifoAdd %d , %d",iDeviceQueueHead,iDeviceQueueTail));
       
  4715     iDeviceEventQueue[iDeviceQueueTail] = aDeviceEvent;
       
  4716     
       
  4717     iDeviceQueueTail ++;
       
  4718     iDeviceQueueTail %= KUsbDeviceEventQueueDepth;
       
  4719     if(iDeviceQueueTail == iDeviceQueueHead)
       
  4720         {
       
  4721         __KTRACE_OPT(KUSB, Kern::Printf("TUsbPeriDeviceEventQueue::FifoAdd overflow, oldest event missed"));
       
  4722         iDeviceQueueHead ++;
       
  4723         iDeviceQueueHead %= KUsbDeviceEventQueueDepth;
       
  4724         }
       
  4725     __KTRACE_OPT(KUSB, Kern::Printf("< TUsbPeriDeviceEventQueue::FifoAdd %d , %d",iDeviceQueueHead,iDeviceQueueTail));
       
  4726     }
       
  4727 
       
  4728 // FifoAdd will be called from thread context
       
  4729 UsbShai::TUsbPeripheralEvent TUsbPeriDeviceEventQueue::FifoGet()
       
  4730     {
       
  4731     __KTRACE_OPT(KUSB, Kern::Printf("> TUsbPeriDeviceEventQueue::FifoGet %d , %d",iDeviceQueueHead,iDeviceQueueTail));    
       
  4732     UsbShai::TUsbPeripheralEvent ret = (UsbShai::TUsbPeripheralEvent)-1;
       
  4733     
       
  4734     if(iDeviceQueueHead != iDeviceQueueTail)
       
  4735         {
       
  4736         ret = iDeviceEventQueue[iDeviceQueueHead];    
       
  4737         iDeviceQueueHead++;
       
  4738         iDeviceQueueHead %= KUsbDeviceEventQueueDepth;
       
  4739         }
       
  4740     __KTRACE_OPT(KUSB, Kern::Printf("< TUsbPeriDeviceEventQueue::FifoGet %d , %d",iDeviceQueueHead,iDeviceQueueTail));
       
  4741     return ret;
       
  4742     }
       
  4743     
       
  4744 /** Sets some data members of this request for a read request.
       
  4745 
       
  4746     @param aBufferStart The start of the data buffer to be filled.
       
  4747     @param aBufferAddr The physical address of the buffer (used for DMA).
       
  4748     @param aPacketIndex A pointer to the packet index values array.
       
  4749     @param aPacketSize A pointer to the packet size values array.
       
  4750     @param aLength The number of bytes to be received.
       
  4751 */
       
  4752 EXPORT_C void TUsbcRequestCallback::SetRxBufferInfo(TUint8* aBufferStart, TUintPtr aBufferAddr,
       
  4753                                            TUint32* aPacketIndex,
       
  4754                                            TUint32* aPacketSize,
       
  4755                                            TInt aLength)
       
  4756     {
       
  4757     iTransferDir = UsbShai::EControllerRead;
       
  4758     iBufferStart = aBufferStart;
       
  4759     iBufferAddr = aBufferAddr;
       
  4760     iPacketIndex = aPacketIndex;
       
  4761     iPacketSize = aPacketSize;
       
  4762     iLength = aLength;
       
  4763     }
       
  4764 
       
  4765 
       
  4766 /** Sets some data members of this request for a write request.
       
  4767 
       
  4768     @param aBufferStart The start of the buffer that contains the data to be sent.
       
  4769     @param aBufferAddr The physical address of the buffer (used for DMA).
       
  4770     @param aLength The number of bytes to be transmitted.
       
  4771 */
       
  4772 EXPORT_C void TUsbcRequestCallback::SetTxBufferInfo(TUint8* aBufferStart, TUintPtr aBufferAddr, TInt aLength)
       
  4773     {
       
  4774     iTransferDir = UsbShai::EControllerWrite;
       
  4775     iBufferStart = aBufferStart;
       
  4776     iBufferAddr = aBufferAddr;
       
  4777     iLength = aLength;
       
  4778     }
       
  4779 
       
  4780 EXPORT_C UsbShai::TUsbPeripheralRequest::TUsbPeripheralRequest(TInt aRealEpNum):
       
  4781     iRealEpNum(aRealEpNum),
       
  4782     iBufferStart(NULL), 
       
  4783     iBufferAddr(0),
       
  4784     iLength(0),
       
  4785     iTxBytes(0),
       
  4786     iRxPackets(0),   
       
  4787     iPacketIndex(NULL),          // actually TUint16 (*)[]
       
  4788     iPacketSize(NULL),           // actually TUint16 (*)[]
       
  4789     iTransferDir(EControllerNone),
       
  4790     iZlpReqd(EFalse),
       
  4791     iError(KErrNone)
       
  4792     {
       
  4793     }
       
  4794 
       
  4795 // Peripheral PSL use this interface to register itself to PIL layer, in our case, 
       
  4796 // DUsbClientController instance
       
  4797 //
       
  4798 // param aPeripheralControllerIf point to an implementation of 
       
  4799 // UsbShai::MPeripheralControllerIf which represent a peripheral controller hardware.
       
  4800 EXPORT_C void UsbShai::UsbPeripheralPil::RegisterPeripheralController( UsbShai::MPeripheralControllerIf& aPeripheralControllerIf, 
       
  4801                                                               const UsbShai::TPeripheralControllerProperties& aProperties)
       
  4802     {
       
  4803     __KTRACE_OPT(KUSB, Kern::Printf("> UsbPeripheralPil::RegisterPeripheralController enter."));
       
  4804     
       
  4805     DUsbClientController* usbcc = DUsbClientController::Create(aPeripheralControllerIf,
       
  4806                                                                aProperties,
       
  4807                                                                /*aIsOtgPort=*/EFalse);
       
  4808     __ASSERT_DEBUG( (usbcc != NULL),
       
  4809                     Kern::Fault( "DUsbClientController extension entry point: USB PSL Out of memory", __LINE__ ) );
       
  4810     }
       
  4811 
       
  4812 // The way for charger detector(PSL) to make it known to us.
       
  4813 EXPORT_C void UsbShai::UsbChargerDetectionPil::RegisterChargerDetector(UsbShai::MChargerDetectorIf&         aChargerDetector,
       
  4814                                                                        UsbShai::TChargerDetectorProperties& aProperties)
       
  4815     {
       
  4816     // Only on charger detector is allowed per system.
       
  4817     if( gChargerDetector != NULL)
       
  4818         {
       
  4819         return ;
       
  4820         }
       
  4821         
       
  4822     gChargerDetector = &aChargerDetector;
       
  4823     
       
  4824     if(gChargerObsever != NULL)
       
  4825         {
       
  4826         // Register to charger detector to listen to any charger type change
       
  4827         // events.
       
  4828         gChargerDetector->SetChargerDetectorObserver(*gChargerObsever);
       
  4829         }
       
  4830     }
       
  4831 
       
  4832 // -EOF-