201028_02
authorhgs
Fri, 23 Jul 2010 15:54:47 +0800
changeset 33 089413cdde3c
parent 29 59aa7d6e3e0f
child 34 2fcc881ba6f5
201028_02
package_definition.xml
usb_plat/group/bld.inf
usb_plat/usb_shai_api/group/bld.inf
usb_plat/usb_shai_api/inc/usb_charger_detection_shai.h
usb_plat/usb_shai_api/inc/usb_common_shai.h
usb_plat/usb_shai_api/inc/usb_host_shai.h
usb_plat/usb_shai_api/inc/usb_otg_shai.h
usb_plat/usb_shai_api/inc/usb_peripheral_shai.h
usb_plat/usb_shai_api/inc/usb_peripheral_shai.inl
usb_plat/usb_shai_api/inc/usb_peripheral_shai_shared.h
usbdrv/peripheral/ldd/perildd/group/base_e32_drivers_usbcli.mrp
usbdrv/peripheral/ldd/perildd/group/bld.inf
usbdrv/peripheral/ldd/perildd/group/usbc.mmp
usbdrv/peripheral/ldd/perildd/src/d_usbc.cpp
usbdrv/peripheral/ldd/perildd/src/usbdma.cpp
usbdrv/peripheral/ldd/perilddsc/appifwrapper/eabi/usbcscu.def
usbdrv/peripheral/ldd/perilddsc/appifwrapper/group/bld.inf
usbdrv/peripheral/ldd/perilddsc/appifwrapper/group/usbcsc_bil.mmp
usbdrv/peripheral/ldd/perilddsc/appifwrapper/src/usbcsc_bil.cpp
usbdrv/peripheral/ldd/perilddsc/group/bld.inf
usbdrv/peripheral/ldd/perilddsc/group/usbcsc.mmp
usbdrv/peripheral/ldd/perilddsc/src/d_usbcsc.cpp
usbdrv/peripheral/pdd/pil/eabi/usbperipheralpilu.def
usbdrv/peripheral/pdd/pil/group/bld.inf
usbdrv/peripheral/pdd/pil/group/usbperipheralpil.mmp
usbdrv/peripheral/pdd/pil/src/chapter9.cpp
usbdrv/peripheral/pdd/pil/src/controltransfersm.cpp
usbdrv/peripheral/pdd/pil/src/descriptors.cpp
usbdrv/peripheral/pdd/pil/src/misc.cpp
usbdrv/peripheral/pdd/pil/src/ps_usbc.cpp
usbdrv/peripheral/pdd/pil/src/queue.cpp
usbdrv/peripheral/public/d32usbc.h
usbdrv/peripheral/public/d32usbc.inl
usbdrv/peripheral/public/d32usbcsc.h
usbdrv/peripheral/public/d32usbcsc.inl
usbdrv/peripheral/public/d32usbcshared.h
usbdrv/peripheral/public/d32usbcshared.inl
usbdrv/peripheral/public/d32usbdescriptors.h
usbdrv/peripheral/public/d32usbtransfers.h
usbdrv/peripheral/public/usb.h
usbdrv/peripheral/public/usbc.h
usbdrv/peripheral/public/usbc.inl
usbdrv/peripheral/public/usbcdesc.h
usbdrv/peripheral/public/usbcontrolxferif.h
usbdrv/peripheral/public/usbcque.h
usbdrv/peripheral/public/usbcsc.h
usbdrv/peripheral/public/usbcsc.inl
usbdrv/peripheral/public/usbcshared.h
usbdrv/peripheral/public/usbcshared.inl
usbdrv/peripheral/public/usbotgperipheralcontrolif.h
--- a/package_definition.xml	Wed Jul 07 15:08:54 2010 +0800
+++ b/package_definition.xml	Fri Jul 23 15:54:47 2010 +0800
@@ -1,8 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <SystemDefinition schema="3.0.0">
   <package id="usb" name="USB" levels="adaptation hw-if plugin framework server app-if">
-    <collection id="usbldd" name="USB Logical Device Drivers" level="hw-if">
-      <!-- usbclientdrivers  to be moved here from kernelhwsrv-->
+    <collection id="usbdrv" name="USB Device Drivers" level="hw-if">
+      <component id="peripheraldrv" name="Usb peripheral driver" purpose="optional">
+          <unit version="1" bldFile="usbdrv/peripheral/group" mrp="usbdrv/peripheral/group/peripheral.mrp"/>
+      </component>
     </collection>
     <collection id="usbmgmt" name="USB Management" level="server">
       <component id="usbmgr" name="USB Manager" purpose="optional">
--- a/usb_plat/group/bld.inf	Wed Jul 07 15:08:54 2010 +0800
+++ b/usb_plat/group/bld.inf	Fri Jul 23 15:54:47 2010 +0800
@@ -15,6 +15,7 @@
 *
 */
 
+#include "../usb_shai_api/group/bld.inf"
 
 PRJ_PLATFORMS
 DEFAULT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usb_plat/usb_shai_api/group/bld.inf	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,32 @@
+/*
+* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Build information file
+*
+*/
+
+#include <platform_paths.hrh>
+
+PRJ_PLATFORMS
+ARMV5
+
+PRJ_EXPORTS
+
+
+../inc/usb_common_shai.h               SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(usb/)
+../inc/usb_host_shai.h                 SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(usb/)
+../inc/usb_otg_shai.h                  SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(usb/)
+../inc/usb_peripheral_shai.h            SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(usb/)
+../inc/usb_peripheral_shai.inl          SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(usb/)
+../inc/usb_peripheral_shai_shared.h      SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(usb/)
+../inc/usb_charger_detection_shai.h      SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(usb/)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usb_plat/usb_shai_api/inc/usb_charger_detection_shai.h	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,403 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+/** @file
+    @brief USB Charger Detection SHAI header
+    @version 0.2.0
+
+    This header specifies the USB Charger Detection SHAI.
+
+    @publishedDeviceAbstraction
+*/
+
+
+#ifndef USB_CHARGER_DETECTION_SHAI_H
+#define USB_CHARGER_DETECTION_SHAI_H
+
+// System includes
+#include <kern_priv.h>
+
+/**
+ * This macro specifies the version of the USB Charger Detection SHAI
+ * header in binary coded decimal format. This allows the PSL layer to
+ * confirm a certain definition is available, if needed. This can for
+ * example make it possible for a new PSL to support compilation in an
+ * older environment with old USB SHAI version that is missing some
+ * new definitions.
+ */
+#define USB_CHARGER_DETECTION_SHAI_VERSION 0x020
+
+// The namespace is documented in file usb_common_shai.h, so it is not
+// repeated here
+namespace UsbShai
+    {
+    // Data types
+
+    /**
+     * An enumeration listing the different port types that can be
+     * reported to the PIL layer by a registered Charger Detector
+     * PSL. The available types mostly correspond to those mentioned
+     * in the Battery Charging Specification Revision 1.1.
+     */
+    enum TPortType
+        {
+        /**
+         * This type is reported to indicate that the Charger Detector
+         * PSL has detected that we are no longer connected to a
+         * powered port. This situation occurs when VBUS driven from
+         * outside drops, or the Accessory Charger Adapter changes the
+         * RID state from RID_A to RID_GND (which usually also means
+         * that VBUS will drop very soon).
+         */
+        EPortTypeNone = 0,
+
+        /**
+         * This type is reported to indicate that the Charger
+         * Detector PSL has detected that our device is connected to
+         * an unsupported port. One common type of an unsupported port
+         * is a PS/2 to USB adapter connected to a PS/2 port of a
+         * computer.
+         */
+        EPortTypeUnsupported,
+
+        /** 
+         * This type is reported when the Charger Detector PSL has
+         * detected that our device is connected to a charging port,
+         * but has not yet distinguished whether the port is a
+         * Charging Downstream Port or a Dedicated Charging Port.
+         *
+         * When this port type is detected, the upper layers will
+         * connect to the USB bus as the peripheral by requesting the
+         * Peripheral Controller PSL to assert the D+ pull-up. The
+         * Charger Detector PSL can then detect the exact port type by
+         * observing what happens to the level of the D- line, as
+         * specified in the Battery Charging Specification. Upon
+         * detecting the exact port type, the Charger Detector PSL can
+         * notify a new event with the correct type.
+         *
+         * If the Charger Detector PSL can directly distinguish the
+         * exact port type, the PSL does not need to report this
+         * generic charging port type, but can directly report the
+         * more specific type EPortTypeDedicatedChargingPort or
+         * EPortTypeChargingDownstreamPort.
+         */
+        EPortTypeChargingPort,
+
+        /** 
+         * This type is reported when the Charger Detector PSL has
+         * detected that our device is connected to a Dedicated
+         * Charging Port.
+         *
+         * When this port type is detected, the upper layers will
+         * connect to the USB bus as the peripheral by requesting the
+         * Peripheral Controller PSL to assert the D+ pull-up, as
+         * specified in the Battery Charging Specification.
+         */
+        EPortTypeDedicatedChargingPort,
+            
+        /** 
+         * This type is reported when the Charger Detector PSL has
+         * detected that our device is connected to a Charging
+         * Downstream Port.
+         *
+         * When this port type is detected, the upper layers will
+         * connect to the USB bus as the peripheral by requesting the
+         * Peripheral Controller PSL to assert the D+ pull-up, as
+         * specified in the Battery Charging Specification.
+         */
+        EPortTypeChargingDownstreamPort,
+            
+        /** 
+         * This type is reported when the Charger Detector PSL has
+         * detected that our device is connected to a Standard
+         * Downstream Port.
+         *
+         * When this port type is detected, the upper layers will
+         * connect to the USB bus as the peripheral by requesting the
+         * Peripheral Controller PSL to assert the D+ pull-up, as
+         * specified in the Battery Charging Specification.
+         */
+        EPortTypeStandardDownstreamPort,
+
+        /** 
+         * This type is reported when the Charger Detector PSL has
+         * detected that our device is connected to the OTG port of an
+         * Accessory Charger Adapter and the ID pin is in the RID_A
+         * range.
+         *
+         * When this port type is detected in an OTG-capable device,
+         * the OTG State Machine will default to the host role.
+         */
+        EPortTypeAcaRidA,
+
+        /** 
+         * This type is reported when the Charger Detector PSL has
+         * detected that our device is connected to the OTG port of an
+         * Accessory Charger Adapter and the ID pin is in the RID_B
+         * range.
+         *
+         * When this port type is detected, the USB Peripheral PIL
+         * layer will ensure that the Peripheral Controller PSL is not
+         * allowed to connect to the bus, as required by the Battery
+         * Charging Specification.
+         */
+        EPortTypeAcaRidB,
+
+        /** 
+         * This type is reported when the Charger Detector PSL has
+         * detected that our device is connected to the OTG port of an
+         * Accessory Charger Adapter and the ID pin is in the RID_C
+         * range.
+         *
+         * When this port type is detected, the upper layers will
+         * connect to the USB bus as the peripheral by requesting the
+         * Peripheral Controller PSL to assert the D+ pull-up, as
+         * specified in the Battery Charging Specification.
+         */
+        EPortTypeAcaRidC,
+        };
+
+
+    // Class declaration
+
+    /**
+     * An interface class implemented by the PIL layer to allow the
+     * Charger Detector PSL to report charger detection events to the
+     * PIL layer.
+     */
+    NONSHARABLE_CLASS( MChargerDetectorObserverIf )
+        {
+        public:            
+        /**
+         * Called by the Charger Detector PSL to report the detection
+         * of a specified type of a port.
+         *
+         * When the PIL layer has registered itself as the observer of
+         * the Charger Detector PSL, it is the responsibility of the
+         * Charger Detector PSL to run the charger detection algorithm
+         * when applicable. These situations include:
+         *
+         * 1. When VBUS has risen while our device is the B-device. A
+         *    Charger Detector PSL that supports Data Contact Detect
+         *    (see Battery Charging Specification 1.1, Section 3.3)
+         *    should complete Data Contact Detect and the charger
+         *    detection algorithm before notifying the VBUS rising
+         *    event to the respective PIL layer.
+         *
+         *    For a peripheral-only port, this requirement is
+         *    documented in more detail in usb_peripheral_shai.h,
+         *    function
+         *    MUsbPeripheralPilCallbackIf::DeviceEventNotification(). For
+         *    an OTG-capable port, the requirement is documented in
+         *    usb_otg_shai.h, function
+         *    MOtgObserverIf::NotifyVbusState().
+         *
+         * 2. When VBUS is high, the Charger Detector PSL needs to
+         *    observe changes in the ID pin state, if the Charger
+         *    Detector PSL support detecting the port types relevant
+         *    to Accessory Charger Adapter. This requirement is
+         *    documented in more detail in usb_otg_shai.h, function
+         *    MOtgObserverIf::NotifyIdPinState().
+         *
+         * @param aPortType The type of the port detected
+         */    
+        virtual void NotifyPortType( TPortType aPortType ) = 0;
+        };
+
+
+    /**
+     * An interface class that needs to be implemented by the Charger
+     * Detector PSL that registers to the PIL layer.
+     *
+     * A system that does not support USB Battery Charging does not
+     * need a Charger Detector PSL. In this case the PIL layer will
+     * always assume the device is connected to a Standard Downstream
+     * Port and will always connect to the bus when VBUS rises.
+     *
+     * Due to the dependencies between normal USB functionality
+     * (observing the state of the ID pin, the VBUS level, the line
+     * state, and controlling connecting to the bus) and USB Battery
+     * Charging (in terms of charger detection and requirements about
+     * connecting to the bus and driving VBUS), the Charger Detector
+     * PSL cannot be considered independent of the USB Controller
+     * PSLs.
+     *
+     * In practice, it is expected that the Charger Detector interface
+     * for a peripheral-only port is implemented by the Peripheral
+     * Controller PSL, or at least that the Peripheral Controller PSL
+     * is communicating with the Charger Detector PSL. This is
+     * necessary to ensure that the necessary parts of charger
+     * detection are run before reporting VBUS high, and that the
+     * Peripheral Controller and the charger detection can safely
+     * share the bus without conflict (as both will need to touch the
+     * line state). See usb_peripheral_shai.h,
+     * MUsbPeripheralPilCallbackIf::DeviceEventNotification() for
+     * description of the requirements.
+     *
+     * Similarly, it is expected that the Charger Detector interface
+     * for an OTG-capable port is implemented by the OTG Controller
+     * PSL, or at least that the OTG Controller PSL is communicating
+     * with the Charger Detector PSL. See usb_otg_shai.h,
+     * MOtgObserverIf::NotifyIdPinState() and
+     * MOtgObserverIf::NotifyVbusState() for description of the
+     * requirements.
+     *
+     * When the PIL layer is ready to receive charger detection
+     * notifications from the PSL, it will use this interface to
+     * register itself as the Charger Detector PSL observer. This is
+     * guaranteed to occur before any USB usage is attempted.
+     */
+    NONSHARABLE_CLASS( MChargerDetectorIf )
+        {
+        public:
+        /**
+         * Called by the PIL layer to set itself as the observer of
+         * charger detection events.
+         *
+         * If the port type has already been detected by the Charger
+         * Detector PSL when the observer is being set (typically
+         * because VBUS was already high at boot time), it is the
+         * responsibility of the Charger Detector PSL to immediately
+         * report the previously detected port type to the observer to
+         * get the PIL layer to the correct state.
+         *
+         * @param aObserver Reference to the observer interface that
+         *   the charger detector is required to report events to
+         */            
+        virtual void SetChargerDetectorObserver( MChargerDetectorObserverIf& aObserver ) = 0;  
+        };
+
+
+    /**
+     * This class specifies the information provided by a Charger
+     * Detector PSL when registering to the PIL layer.
+     *
+     * The PSL should prepare for the possibility that members may be
+     * added to the end of this class in later SHAI versions if new
+     * information is needed to support new features. The PSL should
+     * not use this class as a direct member in an object that is not
+     * allowed to grow in size due to binary compatibility reasons.
+     *
+     * @see UsbChargerDetectionPil::RegisterChargerDetector()
+     */
+    NONSHARABLE_CLASS( TChargerDetectorProperties )
+        {
+        public: // Types and constants
+        /**
+         * A bitmask type used to indicate the static capabilities of
+         * the Charger Detector.
+         */
+        typedef TUint32 TChargerDetectorCaps;
+
+        /**
+         * Capability bit to indicate whether the USB system below the
+         * SHAI (either in HW or in the low-level SW) supports
+         * automatically reducing charging current for the duration of
+         * the USB high-speed chirp signalling. See Battery Charging
+         * Specification Revision 1.1, Chapter 3.6.2 for description
+         * of the problem.
+         *
+         * If the system does not support this feature, the upper
+         * layer USB components that calculate available charging
+         * current will always limit the charging current taken from a
+         * Charging Downstream Port so that the maximum current during
+         * chirp is not violated.
+         *
+         * If the system supports this feature, the full available
+         * charging current from a Charging Downstream Port is
+         * utilized. It is then the responsibility of the HW or some
+         * low-level SW below to SHAI to ensure that the charging
+         * current is automatically reduced for the duration of chirp
+         * signalling.
+         *
+         * If the system supports this feature, the PSL shall set the
+         * corresponding bit in iCapabilities (by bitwise OR'ing this
+         * value). Otherwise the PSL shall clear the corresponding bit
+         * in iCapabilities.
+         */
+        static const TChargerDetectorCaps KChargerDetectorCapChirpCurrentLimiting = 0x00000001;
+
+        public:
+        /**
+         * Inline constructor for the Charger Detector properties
+         * object. This is inline rather than an exported function to
+         * prevent a binary break in a case where an older PSL binary
+         * might provide the constructor a smaller object due to the
+         * PSL being compiled against an older version of the SHAI
+         * header. When it's inline, the function is always in sync
+         * with the object size.
+         *
+         * We slightly violate the coding conventions which say that
+         * inline functions should be in their own file. We don't want
+         * to double the number of USB SHAI headers just for sake of a
+         * trivial constructor.
+         */
+        inline TChargerDetectorProperties() :
+            iCapabilities(0)
+            {
+            };
+
+        public: // Data
+        /**
+         * A bitmask specifying the static capabilities of this
+         * Charger Detector. The PSL fills this field by bitwise
+         * OR'ing the TChargerDetectorCaps capability bits
+         * corresponding to supported features.
+         */
+        TChargerDetectorCaps iCapabilities;
+        };
+
+    /**
+     * A static class implemented by the USB PIL layer to allow the
+     * PSL layer to register its charger detector component to the PIL
+     * layer.
+     */
+    NONSHARABLE_CLASS( UsbChargerDetectionPil )
+        {
+        public:
+        /**
+         * Registration function to be used by the USB PSL layer to
+         * register a charger detector component to the PIL layer. The
+         * PIL layer will set itself as the observer of the charger
+         * detector component to receive notification of detected USB
+         * chargers.
+         *
+         * The intended usage is that the component that implements
+         * USB charger detection registers itself to the USB PIL layer
+         * by making this call from their own kernel extension entry
+         * point function (or an equivalent code that runs during
+         * bootup).
+         *
+         * @param aChargerDetector Reference to the Charger Detector
+         *   interface implemented by the registering PSL.
+         *
+         * @param aProperties Reference to an object describing the
+         *   static properties of the Charger Detector. The PIL layer
+         *   requires that the supplied reference remains valid
+         *   indefinitely, as the registering Charger Detector cannot
+         *   unregister.
+         *
+         * @lib usbperipheralpil.lib
+         */
+        IMPORT_C static void RegisterChargerDetector( MChargerDetectorIf&         aChargerDetector,
+                                                      TChargerDetectorProperties& aProperties );
+        };
+    };
+
+#endif //USB_CHARGER_DETECTION_SHAI_H
+// END of file
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usb_plat/usb_shai_api/inc/usb_common_shai.h	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,92 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+/** @file
+    @brief USB SHAI header for common types and constants
+    @version 0.2.0
+
+    This header specifies common types and constants used by both the
+    peripheral and host/OTG USB SHAIs. It is automatically included by
+    the USB Host and Peripheral SHAI headers and is not intended to be
+    directly included by SHAI implementations.
+
+    The file is versioned for the sake of the human reader, but a
+    compile-time constant to show the header version is not available,
+    as this header is not intended to be directly included by PSL
+    implementations. If a change in this header impacts the overall
+    USB SHAI interface (i.e. change other than documentation
+    improvements), the version of the impacted interfaces (USB Host
+    SHAI, USB OTG SHAI, and/or USB Peripheral SHAI) shall too be
+    changed to make the change visible to the PSL.
+
+    @publishedDeviceAbstraction
+*/
+
+
+#ifndef USB_COMMON_SHAI_H
+#define USB_COMMON_SHAI_H
+
+// System includes
+#include <kern_priv.h>
+
+/**
+ * @brief USB SHAI types and interfaces
+ *
+ * This namespace holds all USB SHAI related types, constants,
+ * classes, and functions.
+ */
+namespace UsbShai
+    {
+    // Data types
+
+    /**
+     * Enumeration specifying the available USB endpoint types.
+     */
+    enum TEndpointType
+        {
+        /** Endpoint type is control */
+        EEpTypeControl = 0,
+        
+        /** Endpoint type is bulk */
+        EEpTypeBulk,
+
+        /** Endpoint type is interrupt */
+        EEpTypeInterrupt,
+
+        /** Endpoint type is isochronous */
+        EEpTypeIsochronous
+        };
+
+    /**
+     * Enumeration specifying the available USB speeds.
+     */
+    enum TSpeed
+        {
+        /** The bus operates in low speed mode */
+        ELowSpeed = 0,
+            
+        /** The bus operates in full speed mode */
+        EFullSpeed,
+            
+        /** The bus operates in high speed mode */
+        EHighSpeed
+        };
+    };
+
+#endif // USB_COMMON_SHAI_H
+
+/* End of File */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usb_plat/usb_shai_api/inc/usb_host_shai.h	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,1290 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+/** @file
+    @brief USB Host SHAI header
+    @version 0.2.0
+
+    This header specifies the USB host SHAI.
+
+    @publishedDeviceAbstraction
+*/
+
+
+#ifndef USB_HOST_SHAI_H
+#define USB_HOST_SHAI_H
+
+// System includes
+#include <kern_priv.h>
+#include <usb/usb_common_shai.h> // Common types shared between the USB SHAIs
+
+/**
+ * This macro specifies the version of the USB Host SHAI header in
+ * binary coded decimal format. This allows the PSL layer to confirm a
+ * certain definition is available, if needed. This can for example
+ * make it possible for a new PSL to support compilation in an older
+ * environment with old USB SHAI version that is missing some new
+ * definitions.
+ */
+#define USB_HOST_SHAI_VERSION 0x020
+
+// The namespace is documented in file usb_common_shai.h, so it is not
+// repeated here
+namespace UsbShai
+    {
+    // Forward declarations
+
+    class MHostControllerIf;
+    class MHostTransferCallbackIf;
+    class MRootHubCallbackIf;
+    class MRootHubIf;
+
+    // Data types
+
+    /**
+     * An enumeration listing the host role electrical test modes
+     * supported. These correspond to the test modes specified in
+     * Section "6.4.1.1 Test Modes" of the "On-The-Go and Embedded
+     * Host Supplement to the USB Revision 2.0 Specification" Revision
+     * 2.0 (a.k.a. USB OTG 2.0).
+     *
+     * @see MHostControllerIf::EnterHostTestMode()
+     */
+    enum THostTestMode
+        {
+        /**
+         * Drive SE0 until host controller is reset. The call returns
+         * immediately after enabling the test mode.
+         */
+        ETestModeTestSE0NAK = 0,
+
+        /**
+         * Drive high-speed J until host controller is reset. The call
+         * returns immediately after enabling the test mode.
+         */
+        ETestModeTestJ,
+
+        /**
+         * Drive high-speed K until host controller is reset. The call
+         * returns immediately after enabling the test mode.
+         */
+        ETestModeTestK,
+
+        /**
+         * Send test packets until host controller is reset. The
+         * format of the required test packet is specified in Section
+         * "7.1.20 Test Mode Support" of the USB 2.0 specification.
+         *
+         * The call returns immediately after enabling the test
+         * mode.
+         */
+        ETestModeTestPacket,
+
+        /**
+         * Suspend and resume the port with 15 second delays to allow
+         * the operator to adjust test tool settings. The Host
+         * Controller PSL must perform the following test steps:
+         *
+         * 1. Allow SOFs to continue for 15 seconds.
+         *
+         * 2. Suspend the port under test.
+         *
+         * 3. Wait for 15 seconds.
+         *
+         * 4. Resume the port under test.
+         *
+         * This test mode is synchronous, i.e. the call returns after
+         * the test has been completed.
+         */
+        ETestModeHsHostPortSuspendResume,
+
+        /**
+         * Perform a single-step GetDescriptor(Device) transfer.  This
+         * is called after the USB Host Stack has enumerated a device
+         * with VID=0x1A0A and PID=0x0107. The Host Controller PSL
+         * must perform the following test steps:
+         *
+         * 1. Allow SOFs to continue for 15 seconds.
+         *
+         * 2. Send a complete GetDescriptor(Device) transfer
+         *
+         * This test mode is synchronous, i.e. the call returns after
+         * the test has been completed.
+         */
+        ETestModeSingleStepGetDeviceDescriptor,
+
+        /**
+         * Perform a single-step GetDescriptor(Device) transfer with a
+         * delayed data phase. This is called after the USB Host Stack
+         * has enumerated a device with VID=0x1A0A and PID=0x0108. The
+         * Host Controller PSL must perform the following test steps:
+         *
+         * 1. Send the SETUP packet for GetDescriptor(Device). The
+         *    device ACKs the packet as usual.
+         *
+         * 2. Allow SOFs to continue for 15 seconds.
+         *
+         * 3. Send the IN token for the data phase of
+         *    GetDescriptor(Device). The device responds with
+         *    the data.
+         *
+         * 4. Send the acknowledgement (zero-length OUT data) in
+         *    response to the data.
+         *
+         * This test mode is synchronous, i.e. the call returns after
+         * the test has been completed.
+         */
+        ETestModeSingleStepGetDeviceDescriptorData
+        };
+
+
+    // Class declaration
+
+    /**
+     * This class specifies a memory block that is used for USB
+     * transfers. The memory pointers and the buffer length are filled
+     * by the USB Host stack before issuing the transfer to the Host
+     * Controller PSL.
+     */
+    NONSHARABLE_CLASS( TUsbMemoryBlock )
+        {
+        public:
+        /**
+         * Linear (virtual) start address of the memory buffer. This
+         * address is always provided.
+         */
+        TLinAddr iLinAddr;
+
+        /**
+         * Physical start address of the memory buffer. This address
+         * is always provided, but it is the responsibility of the
+         * Host Controller PSL to guarantee that the memory is
+         * physically contiguous, if contiguous memory is needed. The
+         * PSL can guarantee this by implementing
+         * MHostControllerIf::ChunkCreate() to allocate physically
+         * contiguous memory.
+         *
+         * @see MHostControllerIf::ChunkCreate()
+         */
+        TPhysAddr iPhysAddr;
+
+        /**
+         * Pointer to an array of physical addresses each pointing to
+         * one physical page of the memory block. This address is
+         * always provided.
+         *
+         * The size of each page matches the size reported in
+         * THostControllerProperties::iControllerPageSize by the Host
+         * Controller PSL when it registered to the PIL.
+         */
+        TPhysAddr* iPhysPages;
+
+        /** The length of the memory buffer in bytes */
+        TUint iLength;
+        };
+
+
+    /**
+     * This class specifies the enumerated types for different endpoint
+     * configuration items and specifies the structure of the endpoint
+     * configuration. Instances of this class are used to specify the
+     * endpoint information when opening a pipe.
+     *
+     * @see MHostControllerIf::OpenPipe()
+     */
+    NONSHARABLE_CLASS( THostPipe )
+        {
+        public:
+        // These are flag constants that specify the values that can
+        // be bitwise OR'ed to the endpoint flags field iEndpointFlags
+        // to indicate some boolean parameters of the endpoint
+
+        /**
+         * This flag specifies whether the targeted endpoint is behind
+         * a hub that is performing transaction translation. This
+         * occurs when the attached device is a low/full-speed device
+         * attached to a high-speed hub.
+         *
+         * When this flag is set, the iHubAddr and iHubPort members
+         * specify the hub address and the port to which the targeted
+         * device is connected, and the iEndpointFlags flag
+         * KHubHasMultipleTTs specifies whether the hub has been
+         * configured to use multiple transaction translators.
+         */
+        static const TUint32 KHubTranslates = 0x00000001;
+
+        /**
+         * When the iEndpointFlags flag KHubTranslates is set, this
+         * flag is set if the hub has multiple transaction
+         * translators.
+         */
+        static const TUint32 KHubHasMultipleTTs = 0x00000002;
+
+        public: // Data
+        /**
+         * The type of the endpoint (control, bulk, interrupt,
+         * isochronous)
+         */
+        TEndpointType iType;
+
+        /** Maximum packet size to be used on this endpoint */
+        TUint iMaxPacketSize;
+
+        /** Flags specifying some boolean parameters of the endpoint */
+        TUint32 iEndpointFlags;
+
+        /**
+         * The speed (low, full, high) to use for this endpoint. This
+         * may differ from the current speed of the local port if the
+         * targeted device is a low-speed or full-speed device
+         * connected to a high-speed hub.
+         */
+        TSpeed iSpeed;
+
+        /**
+         * The polling interval specified as number of frames or
+         * microframes, depending on the speed. This is used for
+         * interrupt and isochronous endpoints only.
+         */
+        TUint iPollingInterval;
+
+        /**
+         * The USB address of the remote device that we are
+         * communicating with
+         */
+        TUint8 iRemoteAddr;
+
+        /**
+         * The remote endpoint number that we are communicating
+         * with. This is the physical endpoint number in the USB 2.0
+         * descriptor format, i.e. the most significant bit indicates
+         * the direction (1 for IN, 0 for OUT), and the least
+         * significant bits indicate the endpoint number.
+         */
+        TUint8 iRemoteEpNum;
+
+        /**
+         * For cases where the attached device is a low/full-speed
+         * device attached to a high-speed hub that does the necessary
+         * transaction translation, this member records the address of
+         * the hub doing the translation.
+         */
+        TUint8 iHubAddr;
+
+        /**
+         * For cases where the attached device is a low/full-speed
+         * device attached to a high-speed hub that does the necessary
+         * transaction translation, this member records the number of
+         * the port where the device is connected on the hub that does
+         * the transaction translation.
+         */
+        TUint8 iHubPort;
+        };
+
+
+    /**
+     * This class specifies the structure of the endpoint transfer
+     * requests. The USB Host Stack passes the Host Controller PSL a
+     * reference to an object of this class when setting up a new transfer
+     * with MHostPipeIf::StartTransfer().
+     */
+    NONSHARABLE_CLASS( THostTransfer )
+        {
+        public:
+        // These are public constants that specify the values that can
+        // be bitwise OR'ed to the request flags field iRequestFlags
+        // to indicate some boolean parameters of the transfer
+
+        /**
+         * When set, specifies that the transfer direction is IN,
+         * i.e. the host is reading from the connected device. This is
+         * needed for endpoint zero, which is bi-directional and
+         * cannot implicitly know the direction of the transfer.
+         *
+         * This bit is set or cleared by the USB Host stack before
+         * issuing a new transfer.
+         */
+        static const TUint32 KTransferDirIsIN = 0x00000001;
+
+        /**
+         * For OUT endpoint transfers, indicates whether the Host
+         * Controller PSL is required to force a short packet at the
+         * end of the transfer.
+         *
+         * When the bit is set, the Host Controller PSL must send a
+         * ZLP (Zero-Length Packet) after the last packet of the
+         * transfer, if and only if the last packet was a full packet,
+         * i.e. had the same size as the maximum packet size for the
+         * endpoint.
+         *
+         * This bit is set or cleared by the USB Host stack before
+         * issuing a new transfer.
+         */
+        static const TUint32 KOutForceShortPacket = 0x00000002;
+
+        /**
+         * For IN endpoint transfers, indicates whether the transfer
+         * was terminated with a ZLP (Zero-Length Packet).
+         *
+         * This bit is set by the Host Controller PSL before
+         * completing the transfer if the transfer ended due to a
+         * ZLP. Otherwise the bit is cleared by the Host Controller
+         * PSL.
+         */
+        static const TUint32 KInZlpReceived = 0x00000004;
+
+        /**
+         * Enumeration specifying the packet status values to be used
+         * for isochronous transfers.
+         */
+        enum TIsocPacketStatus
+            {
+            /** No error has occurred, transfer succesful */
+            ESuccess = 0,
+
+            /**
+             * Data error has occurred in a data transfer, i.e. the
+             * CRC did not match
+             */
+            EDataError,
+
+            /** Overrun has occurred */
+            EOverrun,
+
+            /** Underrun has occurred */
+            EUnderrun,
+            };
+
+        public: // Data
+        /**
+         * Pointer to the information of the pipe that this transfer
+         * is being made on. This is the same information that was
+         * used when opening the pipe that the transfer is being made
+         * on.
+         */
+        THostPipe* iPipeInfo;
+
+        /**
+         * A pointer to the callback interface to be used for
+         * indicating the completion of the transfer. This is set by
+         * the USB Host Stack before making a transfer request.
+         */
+        MHostTransferCallbackIf* iTransferCbIf;
+
+        /**
+         * Request flags specifying some boolean parameters for the
+         * transfer.
+         */
+        TUint32 iRequestFlags;
+
+        /**
+         * Memory block specifying the memory buffer used for the data
+         * transfer. This is filled by the USB Host Stack before
+         * making a transfer request.
+         *
+         * The memory block used here will be part of a chunk
+         * previously created by a call to
+         * MHostControllerIf::ChunkCreate() and the block will
+         * fullfill the alignment requirements reported by the call to
+         * MHostControllerIf::GetSizeAndAlignment().
+         *
+         * For control transfers, this specifies the buffer for the
+         * data stage and has zero length and NULL pointers if the
+         * transaction does not include a data stage.
+         */
+        TUsbMemoryBlock iDataBuffer;
+
+        /**
+         * For control transfers, this memory block specifies the
+         * contents of the setup packet to be sent. For other than
+         * control transfers, it is not used, and it has zero length
+         * and NULL pointers.
+         */
+        TUsbMemoryBlock iSetupBuffer;
+
+        /**
+         * For isochronous transfers, this sets the number of
+         * isochronous packets to send/receive. This is set by the
+         * USB Host Stack before making a transfer request.
+         */
+        TInt iNumIsocPackets;
+
+        /**
+         * The number of bytes successfully transferred during the
+         * data transfer. This is set by the Host Controller PSL
+         * before completing the transfer.
+         */
+        TUint iTransferLength;
+
+        /**
+         * The status code of a completed transfer. This is set by the
+         * Host Controller PSL before completing the request to the
+         * transfer callback interface.
+         */
+        TInt iStatus;
+
+        /**
+         * For isochronous transfers, a pointer to an array of
+         * iNumIsoPackets entries that specify the length of each
+         * packet in the transfer. For OUT transfers, the array is
+         * filled by the USB Host Stack and is read by the Host
+         * Controller PSL to decide the length for each packet. For IN
+         * transfers, the array is filled by the Host Controller PSL
+         * to record to length of each received packet.
+         */
+        TUint16* iIsocPacketLengths;
+
+        /**
+         * For isochronous transfers, a pointer to an array of
+         * iNumIsoPackets entries that specify the status of each
+         * packet in the transfer. The array is filled by the Host
+         * Controller PSL to record to success or failure of each
+         * received packet.
+         */
+        TIsocPacketStatus* iIsocPacketStatuses;
+        };
+
+
+    /**
+     * This class specifies the structure and contents of root hub
+     * information that is filled by the adaptation to let the USB Host
+     * Stack hub driver learn the capabilities of the root hub.
+     *
+     * @see MHostControllerIf::OpenRootHub
+     */
+    NONSHARABLE_CLASS( TRootHubInfo )
+        {
+        public: // Types and constants
+        /**
+         * A bitmask type used to indicate the static capabilities of
+         * the root hub.
+         */
+        typedef TUint32 TRootHubCaps;
+
+        /**
+         * Capability bit to indicate whether the root hub supports
+         * user-visible port indications such as LEDs.
+         *
+         * If the root hub supports this feature, the PSL shall set
+         * the corresponding bit in iCapabilities (by bitwise OR'ing
+         * this value). Otherwise the PSL shall clear the
+         * corresponding bit in iCapabilities.
+         */
+        static const TRootHubCaps KRootHubCapPortIndication = 0x00000001;
+
+        public: // Data
+        /**
+         * A bitmask specifying the static capabilities of this root
+         * hub. The PSL fills this field by bitwise OR'ing the
+         * TRootHubCaps capability bits corresponding to supported
+         * features.
+         */
+        TRootHubCaps iCapabilities;
+
+        /** Number of ports in this root hub */
+        TUint iNumberOfPorts;
+
+        /**
+         * Maximum number of milliamps of current that this root hub
+         * can supply to VBUS.
+         */
+        TUint iMaxSuppliedVbusCurrentMA;
+
+        /**
+         * Time taken by this root hub between starting to power up a
+         * port and power being good on that port. This is expressed
+         * in units of one millisecond.
+         */
+        TUint iTimePowerOnToPowerGoodMs;
+
+        /**
+         * The maximum speed supported by the root hub.
+         */
+        TSpeed iMaxSpeed;
+
+        /** Pointer to the root hub interface */
+        MRootHubIf* iRootHubIf;
+        };
+
+
+    /**
+     * An interface class used by the USB Host Stack to perform data
+     * transfers on a USB pipe. The Host Controller PSL must implement
+     * this interface and provide a pointer to a pipe-specific
+     * instance when the USB Host Stack creates the pipe by calling
+     * MHostControllerIf::OpenPipe().
+     *
+     * The USB Host Stack will call the functions of this interface
+     * from a DFC queued on the DFC queue supplied by the Host
+     * Controller in THostControllerProperties::iControllerDfcQueue when the
+     * Host Controller PSL registered.
+     *
+     * @see MHostControllerIf::OpenPipe()
+     */
+    NONSHARABLE_CLASS( MHostPipeIf )
+        {
+        public:
+        /**
+         * Close the USB pipe. This is called by the USB Host Stack
+         * when the pipe is no longer used and the Host Controller PSL
+         * may release any resources that were allocated for this
+         * instance, including deleting the object itself.
+         *
+         * @param aPipeInfo Information describing the target endpoint
+         *   of the pipe. This is the same information passed to
+         *   MHostControllerIf::OpenPipe() when creating the
+         *   pipe.
+         *
+         * @post After calling the function, the USB Host stack will
+         *   consider the invoked instance to have been deleted and will
+         *   no longer call any of the functions.
+         */
+        virtual void ClosePipeD( const THostPipe& aPipeInfo ) = 0;
+
+        /**
+         * Clear the data toggle bit of this pipe. This is used for
+         * interrupt and bulk pipes when the host stack needs to
+         * guarantee that the host controller will start the next
+         * interrupt or bulk transfer with data toggle value zero.
+         *
+         * @param aPipeInfo Information describing the target endpoint
+         *   of the pipe. This is the same information passed to
+         *   MHostControllerIf::OpenPipe() when creating the
+         *   pipe.
+         */
+        virtual void ClearDataToggle( const THostPipe& aPipeInfo ) = 0;
+
+        /**
+         * Start a transfer on this pipe.
+         *
+         * When the transfer is considered completed, the Host
+         * Controller PSL must update the transfer information object
+         * with the actual length and status of the transfer and then
+         * complete it to the callback interface by calling
+         * MHostTransferCallbackIf::CompleteTransfer(). The pointer to
+         * the callback interface is provided in the member
+         * THostTransfer::iTransferCbIf of the supplied aTransferInfo.
+         *
+         * The following rules shall be used by the Host Controller
+         * PSL to assess the completeness of a transfer:
+         *
+         * 1. A read or write transfer on a control pipe is completed
+         * when all the stages (two or three) of the control transfer
+         * have been completed successfully, or when an error
+         * occurs. It is the responsibility of the upper layers to
+         * guarantee that there is sufficient buffer space for a read
+         * request, so the buffer should not run out.
+         *
+         * 2. A read or write transfer on an isochronous pipe is
+         * completed when the number of isochronous packets specified
+         * in the member THostTransfer::iNumIsocPackets of the
+         * supplied aTransferInfo have been sent or received
+         * successfully, or if a fatal error occurs. It is the
+         * responsibility of the upper layers to guarantee that there
+         * is sufficient buffer space for a read request, so the
+         * buffer should not run out.
+         *
+         * 3. A read transfer on a bulk or interrupt pipe is completed
+         * when the buffer space is exhausted, a short packet (a
+         * packet smaller than the maximum packet size of the pipe) is
+         * received, or an error occurs.
+         *
+         * 4. A write transfer on a bulk or interrupt pipe is
+         * completed when the requested buffer has been fully sent, or
+         * an error occurs.
+         *
+         * @param aTransferInfo Information specifying the transfer to perform
+         *
+         * @return KErrNone if the transfer was started successfully,
+         *   otherwise a system-wide error code
+         */
+        virtual TInt StartTransfer( THostTransfer& aTransferInfo ) = 0;
+
+        /**
+         * Cancel a transfer that was previously started with
+         * StartTransfer(). The Host Controller PSL must flush any
+         * pending data (either received or about to be sent) and
+         * discard the transfer. The PSL must not attempt to complete
+         * the canceled transfer by calling
+         * MHostTransferCallbackIf::CompleteTransfer().
+         *
+         * @param aTransferInfo Information specifying the transfer to
+         *   cancel. This is the same information passed to
+         *   StartTransfer() when the transfer as started.
+         */
+        virtual void CancelTransfer( THostTransfer& aTransferInfo ) = 0;
+        };
+
+
+    /**
+     * An interface class used by the USB Host Stack hub driver to
+     * operate on the root hub ports. The Host Controller PSL must
+     * implement this interface and provide a pointer when the USB
+     * Host Stack opens the root hub by calling
+     * MHostControllerIf::OpenRootHub().
+     *
+     * The USB Host Stack will call the functions of this interface
+     * from a DFC queued on the DFC queue supplied by the Host
+     * Controller in THostControllerProperties::iControllerDfcQueue
+     * when the Host Controller PSL registered.
+     *
+     * @see MHostControllerIf::OpenRootHub()
+     */
+    NONSHARABLE_CLASS( MRootHubIf )
+        {
+        public:
+        /**
+         * Close the connection to the root hub. This is called by the
+         * USB Host Stack when the Host Controller is about to be
+         * deleted and the root hub is no longer used. The Host
+         * Controller PSL may release any resources that were
+         * allocated for this instance, including deleting the object
+         * itself.
+         *
+         * @post After calling the function, the USB Host stack will
+         *   consider the invoked instance to have been deleted and will
+         *   no longer call any of the functions.
+         */
+        virtual void CloseRootHubD() = 0;
+
+        /**
+         * Enable the power supply, i.e. raise VBUS, on the specified
+         * root hub port.
+         *
+         * If there are problems raising VBUS, the Host Controller PSL
+         * must report a VBUS error by notifying the root hub callback
+         * interface MRootHubCallbackIf of an over-current condition
+         * on the port.
+         *
+         * @param aPort The number of the root hub port to operate
+         *   on. For a root hub with N ports, the port numbers are in
+         *   range [1..N].
+         *
+         * @see MRootHubCallbackIf::OverCurrentDetected()
+         */
+        virtual void PowerOnPort( TUint aPort ) = 0;
+
+        /**
+         * Stop session (A-device only).
+         *
+         * @param aPort The number of the root hub port to operate
+         *   on. For a root hub with N ports, the port numbers are in
+         *   range [1..N].
+         */
+        virtual void PowerOffPort( TUint aPort ) = 0;
+
+        /**
+         * Reset the specified root hub port. The total reset length
+         * has to be at least 50 milliseconds and the reset signalling
+         * must follow the requirements specified in USB 2.0
+         * Specification Section 7.1.7.5 Reset Signaling.
+         *
+         * This function is synchronous and should return when the
+         * reset signalling on the port has completed.
+         *
+         * @param aPort The number of the root hub port to operate
+         *   on. For a root hub with N ports, the port numbers are in
+         *   range [1..N].
+         */
+        virtual void ResetPort( TUint aPort ) = 0;
+
+        /**
+         * Place the specified root hub port to the USB suspend state
+         * where it does not send SOF packets to the connected device.
+         *
+         * When all ports of the root hub have been suspended, the USB
+         * Host Stack will suspend the entire host controller by
+         * calling MHostControllerIf::SuspendController().
+         *
+         * When the root hub only has one port and SOFs cannot be
+         * gated on the port without suspending the whole controller,
+         * the Host Controller PSL should ignore the port-specific
+         * suspend and resume calls and instead suspend/resume the
+         * controller based on the controller-specific suspend and
+         * resume calls in MHostControllerIf.
+         *
+         * @param aPort The number of the root hub port to operate
+         *   on. For a root hub with N ports, the port numbers are in
+         *   range [1..N].
+         */
+        virtual void SuspendPort( TUint aPort ) = 0;
+
+        /**
+         * Resume the specified root hub port from the USB suspend
+         * state by driving the resume signalling on the port. The
+         * signalling must last at least 20 milliseconds and follow
+         * the requirements specified in USB 2.0 Specification Section
+         * 7.1.7.7 Resume Signaling. After the resume signalling has
+         * completed, the port must allow SOFs to be sent to the
+         * connected device again.
+         *
+         * Before resuming the first port of a completely suspended
+         * controller, the USB Host Stack will first resume the entire
+         * host controller by calling
+         * MHostControllerIf::ResumeController().
+         *
+         * When the root hub only has one port and SOFs cannot be
+         * gated on the port without suspending the whole controller,
+         * the Host Controller PSL should ignore the port-specific
+         * suspend and resume calls and instead suspend/resume the
+         * controller based on the controller-specific suspend and
+         * resume calls in MHostControllerIf.
+         *
+         * @param aPort The number of the root hub port to operate
+         *   on. For a root hub with N ports, the port numbers are in
+         *   range [1..N].
+         */
+        virtual void ResumePort( TUint aPort ) = 0;
+
+        /**
+         * Query whether a device (a hub or a function) is currently
+         * connected to the specified root hub port, and what speed it
+         * is.
+         *
+         * @param aPort The number of the root hub port to check for a
+         *   connected device on. For a root hub with N ports, the port
+         *   numbers are in range [1..N].
+         *
+         * @param aSpeed Variable to fill with the speed, if connected
+         *
+         * @return ETrue if a device is currently connected and aSpeed
+         *   has been set to the speed of the connected device. EFalse
+         *   otherwise.
+         */
+        virtual TBool IsDeviceConnected( TUint   aPort,
+                                         TSpeed& aSpeed ) = 0;
+        };
+
+
+    /**
+     * An interface class that needs to be implemented by each Host
+     * Controller PSL that registers to the USB stack.
+     *
+     * This interface is used by the USB Host Stack to do controller level
+     * operations like suspending and resuming the host controller. It is
+     * also used to open the root hub interface upon creating the SHAI
+     * Host Controller, and to open USB pipes to connected devices.
+     *
+     * The USB Host Stack will call the functions of this interface
+     * from a DFC queued on the DFC queue supplied by the Host
+     * Controller in THostControllerProperties::iControllerDfcQueue when the
+     * Host Controller PSL registered.
+     */
+    NONSHARABLE_CLASS( MHostControllerIf )
+        {
+        public:
+        /**
+         * Open a pipe to an endpoint on a remote USB peripheral.
+         *
+         * This function is called by the USB host stack when it wants
+         * to communicate with a certain endpoint on a discovered USB
+         * peripheral. The opened pipe is then used to read or write
+         * from/to the peripheral until the pipe is later closed by
+         * MHostPipeIf::ClosePipeD().
+         *
+         * @param aPipeInfo Information describing the target endpoint
+         *   that the USB host stack wants to create a pipe to. The
+         *   ownership of the info object remains with the USB host
+         *   stack and the Host Controller PSL must not refer to data
+         *   inside this after the function has returned. All
+         *   MHostPipeIf functions that operate on the pipe will be
+         *   passed the same pipe information so that the Host
+         *   Controller PSL does not necessarily need to take a copy.
+         *
+         * @param aPipe Upon success, set by the Host Controller PSL
+         *   to point to an instance that implements the SHAI pipe
+         *   interface for the opened pipe. This interface will then be
+         *   used by the USB Host Stack to perform transfers until the
+         *   pipe is eventually closed by the USB Host Stack calling
+         *   MHostPipeIf::ClosePipeD().
+         *
+         * @return KErrNone if successful, otherwise a system error code
+         */
+        virtual TInt OpenPipe( const THostPipe& aPipeInfo,
+                               MHostPipeIf*&    aPipe ) = 0;
+
+        /**
+         * Open the root hub for the Host Controller.
+         *
+         * This is called by the USB Host Stack after creating the
+         * Host Controller PSL to learn the capabilities of the
+         * respective root hub and to establish the communication
+         * between the hub driver in the USB Host Stack and the root
+         * hub ports controlled by the Host Controller PSL.
+         *
+         * @param aRootHubInfo Reference to a root hub information
+         *   object to be filled by the adaptation.
+         *
+         * @param aRootHubCbIf Reference to the callback interface of
+         *   the root hub driver in the USB stack. The root hub
+         *   implementation of the Host Controller PSL shall use this
+         *   interface to report events of this root hub.
+         *
+         * @return KErrNone if successful, otherwise a system error code
+         */
+        virtual TInt OpenRootHub( TRootHubInfo&       aRootHubInfo,
+                                  MRootHubCallbackIf& aRootHubCbIf ) = 0;
+
+        /**
+         * Start and enable the host controller. This is called prior
+         * to powering up any port of the root hub to allow to Host
+         * Controller PSL to perform any preparation that may be
+         * necessary to activate the controller. This may include
+         * actions such as enabling clocks or power to the host
+         * controller HW.
+         *
+         * This function is also used in an OTG environment when the
+         * host stack becomes enabled and the controller needs to be
+         * started and enabled for host use. If the HW platform shares
+         * resources such as clocks and power between the host and
+         * peripheral HW, it is probably easiest for the PSL to handle
+         * the role switch based on the
+         * MOtgControllerIf::SetControllerRole() call to the OTG
+         * Controller interface.
+         *
+         * @return KErrNone if the host controller was successfully started,
+         *         otherwise a system-wide error code.
+         *
+         * @see usb_otg_shai.h, MOtgControllerIf::SetControllerRole()
+         */
+        virtual TInt StartHostController() = 0;
+
+        /**
+         * Disable and stop the host controller. This is called after
+         * powering down all ports of the root hub to allow to Host
+         * Controller PSL to release any HW resources needed by the
+         * controller. This may include actions such as disabling
+         * clocks or power to the host controller HW.
+         *
+         * This function is also used in an OTG environment when the
+         * host stack becomes disabled and the host HW resources can
+         * be released. If the HW platform shares resources such as
+         * clocks and power between the host and peripheral HW, it is
+         * probably easiest for the PSL to handle the role switch
+         * based on the MOtgControllerIf::SetControllerRole() call to
+         * the OTG Controller interface.
+         *
+         * @return KErrNone if the host controller was successfully started,
+         *         otherwise a system-wide error code.
+         *
+         * @see usb_otg_shai.h, MOtgControllerIf::SetControllerRole()
+         */
+        virtual TInt StopHostController() = 0;
+        
+        /**
+         * Place the host controller to the USB suspend state where it
+         * does not send SOF packets.
+         */
+        virtual void SuspendController() = 0;
+
+        /**
+         * Resume the host controller from the USB suspend state by
+         * driving the resume signalling towards the root hub. The
+         * signalling must last at least 20 milliseconds and follow
+         * the requirements specified in USB 2.0 Specification Section
+         * 7.1.7.7 Resume Signaling. After the resume signalling has
+         * completed, the controller must allow SOFs to be sent to the
+         * connected device again.
+         */
+        virtual void ResumeController() = 0;
+
+        /**
+         * Force the controller into a specific high-speed host test
+         * mode. This function needs to be implemented only by Host
+         * Controller PSLs for high-speed capable controllers. The
+         * function will only be called when the controller is
+         * operating in high-speed mode and a special test device has
+         * been enumerated.
+         *
+         * When called, the Host Controller PSL shall synchronously
+         * run the selected test as specified for each tests in the
+         * documentation of THostTestMode.
+         *
+         * @param aTestMode Specifies the test mode to enter
+         *
+         * @param aDefaultPipe Information of the default pipe (the
+         *   control pipe to endpoint zero) of the connected test
+         *   device.
+         *
+         * @return KErrNone if the specified test mode was entered
+         *   successfully, otherwise a system-wide error
+         */
+        virtual TInt EnterHostTestMode( THostTestMode    aTestMode,
+                                        const THostPipe& aDefaultPipe ) = 0;
+
+        /**
+         * Get the size and alignment requirements for the Host
+         * Controller. The reference parameters are both input and
+         * output. Upon input, they describe the values requested by
+         * the client, but they may be increased by this function if
+         * the Host Controller requires additional memory or has some
+         * alignment requirements.
+         *
+         * @param aType The type of the endpoint that the memory will
+         *   be used for.
+         *
+         * @param aAlignment Output for required alignment in bytes
+         *
+         * @param aSize Input/output for buffer size (may be increased
+         *   in this function)
+         *
+         * @param aMaxPackets Input/output for maximum number of
+         *   packets in the transfer (may be increased in this function)
+         *
+         * @return KErrNone if successful, otherwise a system-wide
+         *   error code
+         */
+        virtual TInt GetSizeAndAlignment( TEndpointType aType,
+                                          TUint&        aAlignment,
+                                          TInt&         aSize,
+                                          TInt&         aMaxPackets ) = 0;
+
+        /**
+         * Creates a shared chunk and commits memory to it. The memory
+         * allocated with this function will later be used when making
+         * data transfers with this Host Controller (see
+         * THostTransfer::iDataBuffer).
+         *
+         * The adaptation shall create a chunk by calling
+         * Kern::ChunkCreate(), and then commit memory to it with one
+         * of the Commit functions Kern::ChunkCommit(),
+         * Kern::ChunkCommitContiguous(), and Kern::ChunkCommitPhysical().
+         *
+         * This task is delegated to the adaptation so that it can
+         * allocate the correct type of memory. For example, if the
+         * Host Controller requires the memory to be physically
+         * contiguous, the implementation of this function must commit
+         * contiguous memory to the chunk.
+         *
+         * @param aChunk Output handle to the chunk that was created.
+         *   The adaptation must pass this value as the aChunk argument
+         *   to the Kern::ChunkCreate() call.
+         *
+         * @param aOffset The offset (in bytes) from start of chunk,
+         *   which indicates the start of the memory region to be
+         *   committed. This will be a multiple of the MMU page
+         *   size. The adaptation must pass this value as the aOffset
+         *   argument to the used Commit call.
+         *
+         * @param aSize Number of bytes to commit. This will be a
+         *   multiple of the MMU page size. The adaptation must pass
+         *   this value as the aSize argument to the used Commit call.
+         *
+         * @param aInfo At input, specifies the chunk properties
+         *   requested by the upper layers. The adaptation is allowed
+         *   to change the attributes in aInfo.iMapAttr to match the
+         *   requirements of the Host Controller. The adaptation must
+         *   pass this value as the aInfo argument to the
+         *   Kern::ChunkCreate() call. If the adaptation commits
+         *   cached memory, it is the responsibility of the adaptation
+         *   to deal with cache synchronization when making data
+         *   transfers. If the adaptation needs special cleanup when
+         *   the chunk is deleted, the adaptation can set a cleanup
+         *   DFC pointer in aInfo.iDestroyedDfc.
+         *
+         * @param aPhysicalAddress On success, will be set to the
+         *   physical address of the chunk as referenced by the HC
+         *
+         * @return KErrNone if successful, otherwise a system-wide
+         *   error code
+         *
+         * @see System documentation for Kern::ChunkCreate(),
+         *   Kern::ChunkCommit(), Kern::ChunkCommitContiguous(), and
+         *   Kern::ChunkCommitPhysical()
+         */
+        virtual TInt ChunkCreate( DChunk*&          aChunk,
+                                  TUint             aOffset,
+                                  TUint             aSize,
+                                  TChunkCreateInfo& aInfo,
+                                  TPhysAddr&        aPhysicalAddress ) = 0;
+
+        /**
+         * Maps virtual to physical addresses. If the memory addresses
+         * used by the host controller are different to the ones of
+         * the main memory bus (e.g. due to memory mapping or use of
+         * different address spaces), this method is used to translate
+         * from kernel physical addresses to host controller physical
+         * addresses.
+         *
+         * @param aPhysicalAddressList On entering, the list of
+         *   physical addresses as used kernel-side, on successful
+         *   return it contains the list of physical addresses as
+         *   referenced by the HC
+         *
+         * @param aPhysicalAddressListSize Number of elements in
+         *   aPhysicalAddressList
+         *
+         * @return KErrNone if successful, otherwise a system-wide
+         *   error code
+         */
+        virtual TInt MapPhysicalAddresses( TPhysAddr*& aPhysicalAddressList, 
+                                           TInt        aPhysicalAddressListSize ) = 0;
+        };
+
+
+    /**
+     * An interface class implemented by the USB stack to allow the
+     * host controller to report events to the root hub. This includes
+     * notifications of a device being connected or disconnected on a
+     * port, and other port conditions such as seeing a remote wakeup
+     * signalling, an error on the port (such as babble from a
+     * peripheral), or VBUS over-current.
+     *
+     * It is required that the Host Controller PSL calls these
+     * functions in the context of the DFC queue supplied by the Host
+     * Controller PSL in
+     * THostControllerProperties::iControllerDfcQueue when the Host
+     * Controller PSL registered.
+     */
+    NONSHARABLE_CLASS( MRootHubCallbackIf )
+        {
+        public:
+        /**
+         * A constant to specify an unknown port. In those port
+         * notifications where this is explicitly specified to be OK,
+         * this value is allowed to be used as the port number where
+         * the real port number is unknown.
+         */
+        static const TUint KPortUnknown = 0;
+
+        /**
+         * Informs the root hub that a device (a hub or function) has
+         * been connected to the specified root hub port.
+         *
+         * The Host Controller PSL uses this function to inform device
+         * connection also during HNP role switch when the remote
+         * device connects in peripheral role.
+         *
+         * @param aPort The number of the root hub port that the event
+         *   occurred on. For a root hub with N ports, the port numbers
+         *   are in range [1..N].
+         */
+        virtual void DeviceConnected( TUint aPort ) = 0;
+
+        /**
+         * Informs the root hub that a device (a hub or function) has
+         * been disconnected from the specified root hub port.
+         *
+         * The Host Controller PSL uses this function to inform device
+         * disconnection also during HNP role switch when the remote
+         * peripheral disconnects to start the role switch.
+         *
+         * The Host Controller PSL must report device disconnection by
+         * calling this function even if the port is currently
+         * suspended. A disconnection that is part of an HNP role
+         * switch will always occur in suspended state, and even a
+         * normal peripheral may be physically disconnected at any
+         * time.
+         *
+         * @param aPort The number of the root hub port that the event
+         *   occurred on. For a root hub with N ports, the port numbers
+         *   are in range [1..N].
+         */
+        virtual void DeviceDisconnected( TUint aPort ) = 0;
+
+        /**
+         * Informs the root hub that a device connected to the
+         * specified root hub port has requested remote wakeup.
+         *
+         * @param aPort The number of the root hub port that the event
+         *   occurred on. For a root hub with N ports, the port numbers
+         *   are in range [1..N].
+         */
+        virtual void RemoteWakeupRequested( TUint aPort ) = 0;
+
+        /**
+         * Informs the root hub that a port error (such as babble) has
+         * been detected on the specified root hub port. The
+         * adaptation is expected to disable the port that has caused
+         * the error condition.
+         *
+         * @param aPort The number of the root hub port that the event
+         *   occurred on. For a root hub with N ports, the port numbers
+         *   are in range [1..N].
+         */
+        virtual void PortErrorDetected( TUint aPort ) = 0;
+
+        /**
+         * Informs the root hub that an over-current condition has
+         * been detected on the specified port.
+         *
+         * It may not always be possible to see which port out of
+         * several caused the overcurrent. In this case the Host
+         * Controller PSL may use the port number
+         * MRootHubCallbackIf::KPortUnknown.
+         *
+         * @param aPort The number of the root hub port that the event
+         *   occurred on, if known. For a root hub with N ports, the
+         *   port numbers are in range [1..N]. If the exact port is
+         *   not known, the Host Controller PSL root hub may report
+         *   the port number MRootHubCallbackIf::KPortUnknown.
+         */
+        virtual void OverCurrentDetected( TUint aPort ) = 0;
+        };
+
+
+    /**
+     * An interface class implemented by the USB Host Stack to allow the
+     * host controller to complete transfers to the USB Host Stack.
+     *
+     * It is required that the Host Controller PSL calls these
+     * functions in the context of the DFC queue supplied by the Host
+     * Controller PSL in THostControllerProperties::iControllerDfcQueue when
+     * the Host Controller PSL registered.
+     */
+    NONSHARABLE_CLASS( MHostTransferCallbackIf )
+        {
+        public:
+        /**
+         * Complete a transfer request that had been set up with
+         * MHostPipeIf::StartTransfer().
+         *
+         * @param aTransferInfo The transfer information that
+         *   identifies the transfer that has completed
+         */
+        virtual void CompleteTransfer( const THostTransfer& aTransferInfo ) = 0;
+        };
+
+
+    /**
+     * This class specifies the static information provided by a Host
+     * Controller PSL when registering to the USB Host stack.
+     *
+     * The PSL should prepare for the possibility that members may be
+     * added to the end of this class in later SHAI versions if new
+     * information is needed to support new features. The PSL should
+     * not use this class as a direct member in an object that is not
+     * allowed to grow in size due to binary compatibility reasons.
+     *
+     * @see UsbHostPil::RegisterHostController()
+     */
+    NONSHARABLE_CLASS( THostControllerProperties )
+        {
+        public: // Types and constants
+        /**
+         * A bitmask type used to indicate the static capabilities of
+         * the Host Controller.
+         */
+        typedef TUint32 THostCaps;
+
+        public:
+        /**
+         * Inline constructor for the Host Controller properties
+         * object. This is inline rather than an exported function to
+         * prevent a binary break in a case where an older PSL binary
+         * might provide the constructor a smaller object due to the
+         * PSL being compiled against an older version of the SHAI
+         * header. When it's inline, the function is always in sync
+         * with the object size.
+         *
+         * We slightly violate the coding conventions which say that
+         * inline functions should be in their own file. We don't want
+         * to double the number of USB SHAI headers just for sake of a
+         * trivial constructor.
+         */
+        inline THostControllerProperties() :
+            iCapabilities(0),
+            iControllerDfcQueue(NULL),
+            iControllerPageSize(0)
+            {
+            };
+
+        public: // Data
+        /**
+         * A bitmask specifying the static capabilities of this Host
+         * Controller. No capabilities are specified at the moment and
+         * the PSL shall fill this field with a zero value.
+         *
+         * The field is added for sake of future proofing the binary
+         * compatibility of the Host SHAI. By having a field reserved
+         * for capability bits, we can later specify bits to indicate
+         * added virtual functions or extension to this controller
+         * properties structure. The PIL layer can then at runtime
+         * confirm the existence of the new functions or fields and
+         * safely support an older binary, if we choose to.
+         */
+        THostCaps iCapabilities;
+
+        /**
+         * Pointer to a DFC queue that will be used for DFCs of this
+         * controller.
+         *
+         * A stand-alone (one not associated with an OTG-port) Host
+         * Controller PSL must supply a pointer to a dedicated DFC
+         * queue that has been created for this controller. Both the
+         * PSL itself and the PIL layer must queue their DFCs for this
+         * controller in this DFC queue to ensure the code is running
+         * in the same context.
+         *
+         * A Host Controller PSL that is part of an OTG port will be
+         * registered by the OTG PSL. In this case, the DFC queue
+         * supplied here must be the same DFC queue as the one
+         * supplied in the properties of the OTG Controller.
+         */
+        TDfcQue* iControllerDfcQueue;
+
+        /**
+         * The page size used by this Host Controller. The host stack
+         * will fill scatter-gather lists with pages of this size. If
+         * the Host Controller does not have specific page
+         * requirements itself, the registering Host Controller PSL
+         * must supply here the CPU MMU page size that can be obtained
+         * by the call Kern::RoundToPageSize(1).
+         */
+        TInt iControllerPageSize;
+        };
+
+
+    /**
+     * A static class implemented by the USB Host PIL layer to allow
+     * the host controller PSL to register to the PIL layer.
+     */
+    NONSHARABLE_CLASS( UsbHostPil )
+        {
+        public:
+        /**
+         * Registration function to be used by a stand-alone (non-OTG
+         * port) Host Controller PSL to register itself to the PIL
+         * layer. Host Controllers that are part of an OTG-port are
+         * registered by the OTG Controller PSL (see usb_otg_shai.h,
+         * function UsbOtgPil::RegisterOtgController).
+         *
+         * The intended usage is that each stand-alone Host Controller
+         * PSL is a kernel extension that registers itself to the USB
+         * Host PIL layer by making this call from their own kernel
+         * extension entry point function (or an equivalent code that
+         * runs during bootup).
+         *
+         * @param aHostControllerIf Reference to the Host Controller
+         *   interface implemented by the registering PSL.
+         *
+         * @param aProperties Reference to an object describing the
+         *   static properties of the Host Controller. The PIL layer
+         *   requires that the supplied reference remains valid
+         *   indefinitely, as a Host Controller cannot unregister.
+         *
+         * @lib usbotghostpil.lib
+         */
+        IMPORT_C static void RegisterHostController(
+            MHostControllerIf&               aHostControllerIf,
+            const THostControllerProperties& aProperties );
+        };
+    };
+
+#endif // USB_HOST_SHAI_H
+
+/* End of File */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usb_plat/usb_shai_api/inc/usb_otg_shai.h	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,626 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+/** @file
+    @brief USB OTG SHAI header
+    @version 0.2.0
+
+    This header specifies the USB OTG SHAI.
+
+    @publishedDeviceAbstraction
+*/
+
+
+#ifndef USB_OTG_SHAI_H
+#define USB_OTG_SHAI_H
+
+// System includes
+#include <kern_priv.h>
+#include <usb/usb_common_shai.h> // Common types shared between the USB SHAIs
+
+/**
+ * This macro specifies the version of the USB OTG SHAI header in
+ * binary coded decimal format. This allows the PSL layer to confirm a
+ * certain definition is available, if needed. This can for example
+ * make it possible for a new PSL to support compilation in an older
+ * environment with old USB SHAI version that is missing some new
+ * definitions.
+ */
+#define USB_OTG_SHAI_VERSION 0x020
+
+// The namespace is documented in file usb_common_shai.h, so it is not
+// repeated here
+namespace UsbShai
+    {
+    // Forward declarations
+
+    class MOtgControllerIf;
+    class MOtgObserverIf;
+    class MPeripheralControllerIf;
+    class TPeripheralControllerProperties;
+    class MHostControllerIf;
+    class THostControllerProperties;
+
+    // Data types
+
+    /**
+     * Enumeration listing the possible states of the ID pin. Due to a
+     * dependency between OTG and USB Battery Charging, this
+     * enumeration lists also the special states introduced as part of
+     * the Battery Charging Specification version 1.1.
+     *
+     * An OTG Controller PSL for a system that does not support
+     * Accessory Charger Adapter (ACA) will always report only
+     * EIdStateRidFloat or EIdStateRidGnd. An OTG Controller PSL that
+     * supports ACA is required to report the ID pin state accurately
+     * in order for the OTG State Machine to understand why VBUS
+     * appears high even though we should default to the host role and
+     * should normally drive VBUS ourselves (in case of RID_A).
+     *
+     * Reporting an ACA state via the ID pin notification mechanism is
+     * not a substitute for reporting port type detection via the USB
+     * Charger Detection SHAI that is documented separately in
+     * usb_charger_detection_shai.h. When ACA is supported, it is
+     * required that the Charger Detector PSL guarantees that the OTG
+     * Observer gets notified of the ID pin state before reporting the
+     * port type to the Charger Detector Observer.
+     *
+     * @see usb_charger_detection_shai.h
+     */
+    enum TIdPinState
+        {
+        /** ID pin is grounded */
+        EIdStateRidGnd = 0,
+
+        /** ID pin is floating */
+        EIdStateRidFloat,
+
+        /**
+         * ID pin is in the RID_A range, as specified in Battery
+         * Charging 1.1 specification
+         */
+        EIdStateRidA,
+
+        /**
+         * ID pin is in the RID_B range, as specified in Battery
+         * Charging 1.1 specification
+         */
+        EIdStateRidB,
+
+        /**
+         * ID pin is in the RID_C range, as specified in Battery
+         * Charging 1.1 specification
+         */
+        EIdStateRidC
+        };
+
+    /**
+     * Enumeration listing the reported states of VBUS on the OTG
+     * port.
+     *
+     * The threshold for Session Valid comparison is VOTG_SESS_VLD as
+     * defined in the "On-The-Go and Embedded Host Supplement to the
+     * USB Revision 2.0 Specification", Table 4-1 Electrical
+     * Characteristics. The voltage level for a compliant
+     * implementation can be anywhere between 0.8 V and 4.0 V.
+     */
+    enum TVbusState
+        {
+        /** VBUS is below the OTG Session Valid threshold */
+        EVbusStateNoSession = 0,
+
+        /**
+         * VBUS is above the OTG Session Valid threshold, but below
+         * the requirements of AVbusValid.
+         */
+        EVbusStateSessionValid,
+
+        /**
+         * When operating as the A-device and driving VBUS, indicates
+         * that the VBUS is in regulation, as defined in "On-The-Go
+         * and Embedded Host Supplement to the USB Revision 2.0
+         * Specification" Section 4.2.1, "VBUS Output Voltage and
+         * Current".
+         *
+         * When a VBUS session has been started as the A-device, the
+         * OTG Controller PSL is required to report a VBUS level of
+         * EVbusStateAVbusValid when VBUS has successfully risen to
+         * allow the OTG State Machine to transition out of the
+         * a_wait_vrise state.
+         *
+         * After VBUS has been successfully raised when operating as
+         * the A-device, the PSL reporting a VBUS level less than
+         * EVbusStateAVbusValid is considered as a report of a VBUS
+         * error (over-current) situation and will result in ending
+         * the session immediately.
+         */
+        EVbusStateAVbusValid
+        };
+
+    /**
+     * Enumeration listing the state of the OTG 2.0 state machine.
+     *
+     * The states match those defined in the "On-The-Go and Embedded
+     * Host Supplement to the USB Revision 2.0 Specification" for the
+     * OTG A-device and B-device states.
+     */
+    enum TOtgState
+        {
+        /** The OTG state is b_idle */
+        EOtgStateBIdle = 0,
+
+        /** The OTG state is b_peripheral */
+        EOtgStateBPeripheral,
+
+        /** The OTG state is b_wait_acon */
+        EOtgStateBWaitAcon,
+
+        /** The OTG state is b_host */
+        EOtgStateBHost,
+
+        /** The OTG state is a_idle */
+        EOtgStateAIdle,
+
+        /** The OTG state is a_wait_vrise */
+        EOtgStateAWaitVrise,
+
+        /** The OTG state is a_wait_bcon */
+        EOtgStateAWaitBcon,
+
+        /** The OTG state is a_host */
+        EOtgStateAHost,
+
+        /** The OTG state is a_suspend */
+        EOtgStateASuspend,
+
+        /** The OTG state is a_peripheral */
+        EOtgStateAPeripheral,
+
+        /** The OTG state is a_wait_vfall */
+        EOtgStateAWaitVfall,
+
+        /** The OTG state is a_vbus_err */
+        EOtgStateAVbusErr
+        };
+
+    /**
+     * Enumeration listing the roles that our device can be in.
+     */
+    enum TOtgRole
+        {
+        /**
+         * Our device is idle, i.e. we are not operating in either the
+         * peripheral or the host role. This role indicates that
+         * neither the host controller nor the peripheral controller
+         * needs to be activated and the PSL is free to power down the
+         * controllers.
+         */
+        EOtgRoleIdle = 0,
+
+        /** Our device is operating in the peripheral role */
+        EOtgRolePeripheral,
+    
+        /** Our device is operating in the host role */
+        EOtgRoleHost
+        };
+
+    // Class declaration
+
+    /**
+     * An interface class that needs to be implemented by each OTG
+     * Controller PSL that registers to the USB stack.
+     *
+     * The USB OTG Stack will call the functions of this interface
+     * from a DFC queued on the DFC queue supplied by the OTG
+     * Controller PSL in TOtgControllerProperties::iControllerDfcQueue
+     * when the OTG Controller PSL registered.
+     */
+    NONSHARABLE_CLASS( MOtgControllerIf )
+        {
+        public:
+        /**
+         * Called by the OTG stack to set the observer callback
+         * interface to be used by the OTG Controller PSL to report
+         * events.
+         *
+         * When the observer pointer is set to non-NULL value, the OTG
+         * Controller PSL is required to immediately report the
+         * current VBUS and ID states to the observer to get the
+         * status of the OTG stack up to date.
+         *
+         * @param aObserver Pointer to the observer interface to use,
+         *   or NULL when the OTG stack is being unloaded.
+         */
+        virtual void SetOtgObserver( MOtgObserverIf* aObserver ) = 0;
+
+        /**
+         * When operating as the B-peripheral, the OTG stack calls
+         * this function to indicate that the upper layers are
+         * requesting our device to become the B-host. This means that
+         * our OTG device will need start the HNP signalling by
+         * disconnecting from the bus and allowing the A-device to
+         * connect as the peripheral. The signalling shall be started
+         * when the host has suspended the bus, which may already be
+         * the case or happen later.
+         *
+         * This function call is only relevant for OTG controllers
+         * that implement the HNP signalling in hardware and require
+         * an explicit request from SW to start the HNP role switch.
+         * If the OTG controller is under SW control by the Host and
+         * Peripheral Controller PSLs, the OTG Controller PSL should
+         * ignore this call. The HNP signalling in the SW-controlled
+         * case will be handled as normal calls to disconnect as
+         * peripheral and then start the host controller.
+         *
+         * For all controller types, the Host Controller PSL and the
+         * Peripheral Controller PSL associated with the OTG port are
+         * required to report events as they normally would when
+         * operating as the default role. For the Host Controller PSL,
+         * this includes notifying device connection, disconnection,
+         * and other relevant events via MRootHubCallbackIf. For the
+         * Peripheral Controller PSL, this includes notifying bus
+         * state events such as reset, suspend, and resume via
+         * MUsbPeripheralPilCallbackIf::DeviceEventNotification.
+         *
+         * The OTG Controller PSL is not required to perform any
+         * monitoring of HNP success or failure, or report that to the
+         * PIL layer. The PSL is only responsible for making the
+         * normal host and peripheral notifications mentioned above,
+         * and the PIL can see the HNP success or failure from those
+         * notifications.
+         */
+        virtual void SetBHnpRequest() = 0;
+
+        /**
+         * When operating as the B-device, the OTG stack calls this
+         * function to request the PSL to drive SRP signalling on the
+         * bus by pulsing the D+ dataline. The OTG Controller PSL may
+         * synchronously drive the 5..10 millisecond pulse before
+         * returning, but it may also do it asynchronously.
+         *
+         * The OTG PIL layer guarantees that the initial conditions
+         * for driving SRP are satisfied before the PIL calls this
+         * function. That is, the PIL guarantees that sufficient time
+         * has elapsed since the end of the previous VBUS session (if
+         * any) and the bus has been idle long enough.
+         *
+         * No special report from the OTG Controller PSL is required
+         * in either success or fail case. In a success case, the
+         * A-device will raise VBUS and the OTG state machine gets
+         * this as a normal VBUS notifications from the OTG Controller
+         * PSL. In a fail case, a timer in the upper layers will
+         * expire, indicating to upper layers that the SRP was not
+         * successful.
+         */
+        virtual void SignalBSrp() = 0;
+
+        /**
+         * Called by the OTG state machine to indicate a change in the
+         * required controller role.
+         *
+         * Whether the PSL needs to do any actions depends on the HW.
+         * For controllers that require special configuration in
+         * changing a role (other than just starting the peripheral
+         * controller or the host controller normally), the OTG
+         * Controller should do that special configuration when it
+         * gets this call.
+         *
+         * When changing a role, the OTG state machine will first
+         * disable the stack for the previous role, causing that stack
+         * to issue a stop request to the respective controller
+         * PSL. The OTG state machine will then call this function
+         * SetControllerRole() to set the controller role to the
+         * target role. Following this, the OTG state machine will
+         * enable the stack for the target role, causing that stack to
+         * issue a start request to the respective controller PSL.
+         *
+         * @param aControllerRole The OTG role to set our device to
+         *
+         * @return KErrNone if the OTG Controller successfully set the
+         *   role or required no actions. Otherwise a system-wide
+         *   error code.
+         */
+        virtual TInt SetControllerRole( TOtgRole aControllerRole ) = 0;
+        };
+
+
+    /**
+     * An interface class implemented by the USB stack to allow the
+     * OTG controller to report events to the USB stack. This includes
+     * events like VBUS rising and falling, ID pin becoming grounded
+     * or floating, and SRP being detected.
+     *
+     * It is required that the OTG Controller PSL calls these
+     * functions in the context of the DFC queue supplied by the OTG
+     * Controller PSL in TOtgControllerProperties::iControllerDfcQueue
+     * when the OTG Controller PSL registered.
+     */
+    NONSHARABLE_CLASS( MOtgObserverIf )
+        {
+        public:
+        /**
+         * Notify the current ID-pin state to the OTG stack. This
+         * needs to be called by the OTG Controller PSL everytime
+         * there is a change in the ID pin level. Redundant
+         * notifications that don't change the previously reported
+         * state are silently ignored, so the function is safe to call
+         * without worrying about extra calls.
+         *
+         * When USB Battery Charging is supported on the OTG-capable
+         * port, there is a dependency between normal USB
+         * functionality and USB Battery Charging (see
+         * usb_charger_detection_shai.h and specifically the
+         * description of class MChargerDetectorIf). In this case it
+         * is the responsibility of the OTG Controller PSL to
+         * communicate with the Charger Detector PSL (which it may
+         * implement itself) with respect to VBUS and ID pin events.
+         *
+         * For ID pin events that indicate connection to an Accessory
+         * Charger Adapter, it is required that the port type is first
+         * notified to the Charger Detector PSL Observer, followed by
+         * notifying the ID pin state to the OTG Observer (via this
+         * function).
+         *
+         * @param aIdPinState The current ID-pin state
+         */
+        virtual void NotifyIdPinState( TIdPinState aIdPinState ) = 0;
+
+        /**
+         * Notify the current VBUS state to the OTG stack. This needs
+         * to be called by the OTG Controller PSL everytime there is a
+         * change in the VBUS level. Redundant notifications that
+         * don't change the previously reported state are silently
+         * ignored, so the function is safe to call without worrying
+         * about extra calls.
+         *
+         * When USB Battery Charging is supported on the OTG-capable
+         * port, there is a dependency between normal USB
+         * functionality and USB Battery Charging (see
+         * usb_charger_detection_shai.h and specifically the
+         * description of class MChargerDetectorIf). In this case it
+         * is the responsibility of the OTG Controller PSL to
+         * communicate with the Charger Detector PSL (which it may
+         * implement itself) with respect to VBUS and ID pin events.
+         *
+         * When VBUS rises on the OTG-capable port that is currently
+         * the B-device and fully supports Battery Charging
+         * Specification Revision 1.1, the Charger Detector PSL and
+         * the OTG Controller PSL need to together guarantee that Data
+         * Contact Detect is completed and the port type detected
+         * before reporting VBUS rising. When the port type is known,
+         * the port type needs to be notified to the Charger Detector
+         * PSL Observer, followed by notifying the VBUS state to the
+         * OTG Observer (via this function).
+         *
+         * Where Data Contact Detect is not supported, the VBUS rise
+         * event needs to be notified to the OTG Observer (via this
+         * function) immediately and charger detection needs to
+         * proceed in parallel with the upper layers preparing the USB
+         * personality. This is necessary in order to ensure that we
+         * can fulfill the requirement to connect to the bus within a
+         * second, while still making as long as possible charger
+         * detection cycle to minimize the changes of false detections
+         * due to datalines not making contact yet.
+         *
+         * The OTG Controller PSL, the Peripheral Controller PSL and
+         * the Charger Detector PSL need to together guarantee that
+         * the peripheral controller does not attempt to connect to
+         * the bus while charger detection is still on-going. When
+         * detection has been completed and upper layers have
+         * indicated readiness to connect to the bus (see
+         * MPeripheralControllerIf::PeripheralConnect(), the
+         * Peripheral Controller PSL must connect to the bus.
+         *
+         * @param aVbusState The current VBUS state
+         */
+        virtual void NotifyVbusState( TVbusState aVbusState ) = 0;
+
+        /**
+         * When operating as the A-device with VBUS low, notify the
+         * OTG stack that SRP signalling has been detected on the
+         * bus. The OTG Controller must detect the SRP signalling from
+         * dataline pulsing, as specified in the "On-The-Go and
+         * Embedded Host Supplement to the USB Revision 2.0
+         * Specification".
+         */
+        virtual void NotifySrpDetected() = 0;
+
+        /**
+         * This function is called by the OTG Controller PSL to report
+         * that it has detected the attachment of a device (A or B)
+         * that is malfunctioning in a low-level way that prevents
+         * attempting communication with the connected device. Such
+         * cases may include but are not necessarily limited to:
+         *
+         * 1. A B-device that drives its upstream VBUS. To prevent
+         * damage to the VBUS charge pump in our A-device, it may be
+         * necessary to prevent VBUS from being raised by our device.
+         *
+         * 2. A B-device that presents a single-ended one (both
+         * datalines high) on the bus.
+         *
+         * The detection of such malfunctioning devices is left to the
+         * OTG Controller PSL, as this type of malfunctions are
+         * low-level problems not necessarily detectable with the
+         * standard inputs available to the OTG state machine.
+         *
+         * To ensure that the OTG state machine stays in an idle
+         * state, the OTG Controller PSL should report ID floating and
+         * VBUS low prior to reporting the bad device attachment by
+         * calling this function. When the bad device is detached, the
+         * OTG Controller PSL can resume reporting ID and VBUS state
+         * truthfully, and must call NotifyBadDeviceDetached() to
+         * allow the upper layers to see the error condition has been
+         * cleared.
+         *
+         * @see NotifyBadDeviceDetached()
+         */
+        virtual void NotifyBadDeviceAttached() = 0;
+
+        /**
+         * This function is called by the OTG Controller PSL to report
+         * that a previously detected bad device has been detached.
+         * See NotifyBadDeviceAttached() for description of this
+         * functionality.
+         *
+         * @see NotifyBadDeviceAttached()
+         */
+        virtual void NotifyBadDeviceDetached() = 0;
+        };
+
+
+    /**
+     * This class specifies the information provided by an OTG
+     * Controller PSL when registering to the USB OTG stack.
+     *
+     * The PSL should prepare for the possibility that members may be
+     * added to the end of this class in later SHAI versions if new
+     * information is needed to support new features. The PSL should
+     * not use this class as a direct member in an object that is not
+     * allowed to grow in size due to binary compatibility reasons.
+     *
+     * @see UsbOtgPil::RegisterOtgController()
+     */
+    NONSHARABLE_CLASS( TOtgControllerProperties )
+        {
+        public: // Types and constants
+        /**
+         * A bitmask type used to indicate the static capabilities of
+         * the OTG Controller.
+         */
+        typedef TUint32 TOtgCaps;
+
+        public:
+        /**
+         * Inline constructor for the OTG Controller properties
+         * object. This is inline rather than an exported function to
+         * prevent a binary break in a case where an older PSL binary
+         * might provide the constructor a smaller object due to the
+         * PSL being compiled against an older version of the SHAI
+         * header. When it's inline, the function is always in sync
+         * with the object size.
+         *
+         * We slightly violate the coding conventions which say that
+         * inline functions should be in their own file. We don't want
+         * to double the number of USB SHAI headers just for sake of a
+         * trivial constructor.
+         */
+        inline TOtgControllerProperties() :
+            iCapabilities(0),
+            iControllerDfcQueue(NULL)
+            {
+            };
+
+        public: // Data
+        /**
+         * A bitmask specifying the static capabilities of this OTG
+         * Controller. No capabilities are specified at the moment and
+         * the PSL shall fill this field with a zero value.
+         *
+         * The field is added for sake of future proofing the binary
+         * compatibility of the OTG SHAI. By having a field reserved
+         * for capability bits, we can later specify bits to indicate
+         * added virtual functions or extension to this controller
+         * properties structure. The PIL layer can then at runtime
+         * confirm the existence of the new functions or fields and
+         * safely support an older binary, if we choose to.
+         */
+        TOtgCaps iCapabilities;
+
+        /**
+         * Pointer to a DFC queue that will be used for DFCs of this
+         * controller and the associated peripheral and host
+         * controllers.
+         *
+         * The OTG Controller must supply a pointer to a dedicated DFC
+         * queue that has been created for this OTG Controller PSL.
+         * Both the OTG Controller PSL itself and the OTG stack must
+         * queue their DFCs for this controller in this DFC queue to
+         * ensure the code is running in the same context.
+         *
+         * Furthermore, it is the responsibility of the OTG Controller
+         * PSL that registers to ensure that the Peripheral and Host
+         * Controller PSLs that are registered at the same time use
+         * the same DFC Queue in their respective properties object.
+         */
+        TDfcQue* iControllerDfcQueue;
+        };
+
+
+    /**
+     * A static class implemented by the USB OTG PIL layer to allow
+     * the OTG controller PSL to register to the PIL layer.
+     */
+    NONSHARABLE_CLASS( UsbOtgPil )
+        {
+        public:
+        /**
+         * Registration function to be used by the OTG Controller PSL
+         * to register itself and the associated peripheral and host
+         * controller PSLs to the PIL layer.
+         *
+         * The intended usage is that OTG Controller PSL (of which
+         * only one can exists in a given system) is a kernel
+         * extension that registers itself and the associated
+         * peripheral and host controller PSLs to the USB PIL layer by
+         * making this call from its kernel extension entry point
+         * function (or an equivalent code that runs during bootup).
+         *
+         * @param aOtgControllerIf Reference to the OTG Controller
+         *   interface implemented by the registering PSL.
+         *
+         * @param aOtgProperties Reference to an object describing the
+         *   static properties of the OTG Controller. The PIL layer
+         *   requires that the supplied reference remains valid
+         *   indefinitely, as an OTG Controller cannot unregister.
+         *
+         * @param aPeripheralControllerIf Reference to the Peripheral
+         *   Controller interface implemented by the PSL controlling the
+         *   Peripheral Controller associated with the registering OTG
+         *   port.
+         *
+         * @param aPeripheralProperties Reference to an object
+         *   describing the static properties of the Peripheral
+         *   Controller. The PIL layer requires that the supplied
+         *   reference remains valid indefinitely, as the registering
+         *   OTG Controller cannot unregister.
+         *
+         * @param aHostControllerIf Reference to the Host Controller
+         *   interface implemented by the PSL controlling the Host
+         *   Controller associated with the registering OTG port.
+         *
+         * @param aHostProperties Reference to an object describing the
+         *   static properties of the Host Controller. The PIL layer
+         *   requires that the supplied reference remains valid
+         *   indefinitely, as the registering OTG Controller cannot
+         *   unregister.
+         *
+         * @lib usbotghostpil.lib
+         */
+        IMPORT_C static void RegisterOtgController(
+            MOtgControllerIf&                      aOtgControllerIf,
+            const TOtgControllerProperties&        aOtgProperties,
+            MPeripheralControllerIf&               aPeripheralControllerIf, 
+            const TPeripheralControllerProperties& aPeripheralProperties,
+            MHostControllerIf&                     aHostControllerIf,
+            const THostControllerProperties&       aHostProperties );
+        };
+    };
+
+#endif // USB_OTG_SHAI_H
+
+/* End of File */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usb_plat/usb_shai_api/inc/usb_peripheral_shai.h	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,1181 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+/** @file
+    
+    @brief USB Peripheral SHAI header
+    
+    @version 0.3.0
+ 
+    Abstract interface for USB Peripheral Controller.
+ 
+    @publishedDeviceAbstraction
+  
+ */
+ 
+#ifndef USB_PERIPHERAL_SHAI_H
+#define USB_PERIPHERAL_SHAI_H
+
+// System includes
+#include <kern_priv.h>
+#include <usb/usb_common_shai.h> // Common types shared between the USB SHAIs
+#include <usb/usb_peripheral_shai_shared.h> // Common types shared with upper layers
+
+/**
+ * This macro specifies the version of the USB Peripheral SHAI header
+ * in binary coded decimal format. This allows the PSL layer to
+ * confirm a certain definition is available, if needed. This can for
+ * example make it possible for a new PSL to support compilation in an
+ * older environment with old USB SHAI version that is missing some
+ * new definitions.
+ */
+#define USB_PERIPHERAL_SHAI_VERSION 0x030
+
+// The namespace is documented in file usb_common_shai.h, so it is not
+// repeated here
+namespace UsbShai
+    {
+    /** 
+     * Masks defined for TUsbPeripheralEndpointCaps.iSizes.
+     *
+     * Zero means this endpoint is not available (= no size).
+     */
+    const TUint KUsbEpNotAvailable = 0x00000000;
+    
+    /**    
+     * Max packet size is continuously variable up to some size specified.
+     * (Interrupt and Isochronous endpoints only.)
+     */
+    const TUint KUsbEpSizeCont     = 0x00000001;
+    
+    /** Max packet size 8 bytes is supported */
+    const TUint KUsbEpSize8        = 0x00000008;
+    
+    /** Max packet size 16 bytes is supported */
+    const TUint KUsbEpSize16       = 0x00000010;
+    
+    /** Max packet size 32 bytes is supported */
+    const TUint KUsbEpSize32       = 0x00000020;
+    
+    /** Max packet size 64 bytes is supported */
+    const TUint KUsbEpSize64       = 0x00000040;
+    
+    /** Max packet size 128 bytes is supported */
+    const TUint KUsbEpSize128      = 0x00000080;
+    
+    /** Max packet size 256 bytes is supported */
+    const TUint KUsbEpSize256      = 0x00000100;
+    
+    /** Max packet size 512 bytes is supported */
+    const TUint KUsbEpSize512      = 0x00000200;
+    
+    /** Max packet size 1023 bytes is supported */
+    const TUint KUsbEpSize1023     = 0x00000400;
+    
+    /** Max packet size 1024 bytes is supported */
+    const TUint KUsbEpSize1024     = 0x00000800;
+    
+    /** 
+     * Test Mode Selectors (Set/ClearFeature)
+     * Refer to usb specification 2.0, Chapter 9.4.9, table 9-7
+     */
+    enum TUsbTestModeSelector
+        {
+        EUsbTestSelector_Test_J = 0x01,
+        EUsbTestSelector_Test_K,
+        EUsbTestSelector_Test_SE0_NAK,
+        EUsbTestSelector_Test_Packet,
+        EUsbTestSelector_Test_Force_Enable
+        };
+    
+    /** 
+     * Transfer direction of a USB transfer request.
+     * @see TUsbPeripheralRequest
+     */
+    enum TTransferDirection 
+        {
+        EControllerNone,        
+        EControllerRead,
+        EControllerWrite
+        };
+
+    /** 
+     * Enumeration listing the event codes that are passed from PSL to
+     * PIL to indicate peripheral events
+     */
+    enum TUsbPeripheralEvent
+        {
+        /** The USB Suspend bus state has been detected.
+         *
+         * When the Peripheral Controller PSL is part of an
+         * OTG-capable port, the PSL shall report this event also when
+         * operating as the A-peripheral, in which case this final
+         * suspend event starts the HNP role switch back to A-host.
+         */
+        EUsbEventSuspend,
+        
+        /** USB Resume signaling has been detected. */
+        EUsbEventResume,
+        
+        /** A USB Reset condition has been detected. */
+        EUsbEventReset,
+        
+        /**
+         * VBUS level has risen above the B-session valid threshold. This
+         * is only relevant for a stand-alone peripheral controllers
+         * (those not associated with an OTG port). For an OTG port, the
+         * VBUS state is reported to PIL layer by the OTG Controller PSL.
+         */
+        EUsbEventVbusRisen,
+        
+        /**
+         * VBUS level has fallen below the B-session valid threshold. This
+         * is only relevant for a stand-alone peripheral controllers
+         * (those not associated with an OTG port). For an OTG port, the
+         * VBUS state is reported to PIL layer by the OTG Controller PSL.
+         */
+        EUsbEventVbusFallen
+        };   
+
+    typedef TUint32 TUsbPeripheralPacketArray;
+
+    /** 
+     * @brief  A USB transfer request.
+     * 
+     * This class will be constructed in PIL or upper layer, and be
+     * passed down to PSL. After the request was done, PSL layer will
+     * modify corresponding members (like data length, packet info
+     * etc.) and re-pass it back to PIL via interface
+     * MUsbPeripheralPilCallbackIf::EndpointRequestComplete().
+     * 
+     */
+    NONSHARABLE_CLASS(TUsbPeripheralRequest)
+        {
+    public:    
+        /**
+         * This class doesn't need a destructor because it has nothing to be
+         * freed, closed, destroyed. It 'owns' nothing.
+         */
+        IMPORT_C TUsbPeripheralRequest(TInt aRealEpNum);
+        
+    public:
+        /** The 'real' endpoint number this request to be bind to. */
+        TInt iRealEpNum;
+        
+        /** 
+         * Start address of this buffer. Filled-in by PIL.
+         *
+         * PSL needs to put received data in this buffer if it's a read request.
+         * PSL needs to get data from this buffer if it is a write request.
+         */
+        TUint8* iBufferStart;
+        
+        /** Physical address of buffer start (used for DMA). */
+        TUintPtr iBufferAddr;
+        
+        /** Length in bytes to be read/write. Filled-in by PIL. */
+        TInt iLength;
+
+        /** 
+         * Number of bytes transmitted (if it is a write);
+         * This value need to be updated by PSL. 
+         */
+        TUint iTxBytes;
+        
+        /** 
+         * Number of packets received (if it is a read); 
+         * This value need to be updated by PSL.
+         */
+        TUint iRxPackets;
+        
+        /** 
+         * This is a re-interpretation of what's inside in buffer iBufferStart.
+         * It is designed to be that the first packet always contains all the
+         * bytes received. So only the following scenario are possible:
+         *
+         * 1. Nothing, iRxPackets is zero, no packet received.
+         * 
+         * 2. 1 data Packet, iRxPackets is one.
+         *    iPacketIndex[0] is the offset against iBufferStart of where the
+         *    first byte of received data begins.
+         *    iPacketSize[0] is the size (in bytes) of the received data.
+         * 
+         * 3. 1 data packet, and one ZLP packet, iRxPackets is two.
+         *    iPacketIndex[0] is the offset against iBufferStart of where the
+         *    first byte of received data begins.
+         *    iPacketSize[0] is the size (in bytes) of the data packet.
+         *    
+         *    iPacketIndex[1] is the offset of the ZLP packet.
+         *    iPacketSize[1] is always set to zero since ZLP contains no data.
+         * 
+         */
+        TUsbPeripheralPacketArray* iPacketIndex;
+        
+        /** Array of packet sizes. Details see iPacketIndex */
+        TUsbPeripheralPacketArray* iPacketSize;
+        
+        /**
+         * Indicates the transfer direction of this request.
+         * Note, SetupEndpointRead/Write likewise functions already point out 
+         * the transfer direction, PSL may select to use it or not.
+         */
+        TTransferDirection iTransferDir;
+            
+        /** 
+         * For EControllerWrite (IN) transfers, it is used to Indicates that if 
+         * a Zero Length Packet is required at the end of this transfer.
+         * It will be set to ETrue if ZLP is needed, EFalse otherwise.
+         */
+        TBool iZlpReqd;
+        
+        /** 
+         * The error code upon completion of the request;
+         * PSL need to set it to KErrNone if no errors, Set it to other 
+         * system error codes otherwise.
+         */
+        TInt iError;
+        };
+        
+    /** 
+     * Peripheral controller capabilities.
+     * 
+     * PSL should use those values to fill in data member iControllerCaps in
+     * structure TPeripheralControllerProperties.
+     *
+     * @see TPeripheralControllerProperties.
+     */
+    typedef TUint32 TDeviceCaps;
+    
+    /**
+     * Indicates whether peripheral controller hardware supports USB High-speed.
+     * This capability affects driver functionality and behavior throughout the 
+     * implementation.
+     * 
+     * Set this bit if this peripheral controller supports USB High-speed;
+     * Clear it otherwise.
+     */
+    const TDeviceCaps KDevCapHighSpeed = 0x00000001;
+    
+    /** 
+     * Indicates whether the peripheral controller supports hardware acceleration
+     * for setting the device address, i.e. automatically setting device address
+     * on conclusion of status phase of SET_ADDRESS.
+     *
+     * If this capability is supported PIL will call SetDeviceAddress() before
+     * sending a zero byte status packet.
+     *
+     * Set this bit if hardware acceleration is supported.
+     * Clear it otherwise.
+     */
+    const TDeviceCaps KDevCapSetAddressAcceleration = 0x00000002;
+    
+    /**
+     * Indicates whether controller support Session Request Protocol.
+     *
+     * Set this bit if SRP is supported.
+     * Clear it otherwise.
+     */
+    const TDeviceCaps KDevCapSrpSupport = 0x00000004;
+    
+    /**
+     * Indicates whether controller support Host Negotiation Protocol.
+     *
+     * Set this bit if HNP is supported.
+     * Clear it otherwise.
+     */
+    const TDeviceCaps KDevCapHnpSupport = 0x00000008;
+    
+    /**
+     * Indicates whether controller support Remote wakeup
+     * 
+     * Set this bit if remote wakeup is supported.
+     * Clear it otherwise.
+     */
+    const TDeviceCaps KDevCapRemoteWakeupSupport = 0x00000010;
+
+    /** 
+     * Configuration data from PSL to PIL when register a controller through
+     * interface UsbPeripheralPil::RegisterPeripheralController().
+     */
+    NONSHARABLE_CLASS(TPeripheralControllerProperties)
+        {
+        public:
+        TPeripheralControllerProperties();
+        
+        public: // Data
+        /**
+         * A bitmap used to Indicates the capabilities of this controller.
+         * PSL should set the corresponding bit to '1' if one capability is
+         * supported by this controller.
+         */
+        TDeviceCaps iControllerCaps;
+
+        /**
+         * Pointer to a DFC queue that will be used for DFCs of this controller.
+         *
+         * A stand-alone (one not associated with an OTG-port) peripheral PSL 
+         * implementation must supply a pointer to a dedicated DFC queue that 
+         * has been created for this controller. Both the PSL itself and the PIL
+         * layer must queue their DFCs for this controller in this DFC queue to
+         * ensure the code is running in the same context.
+         *
+         * A peripheral PSL that is part of an OTG port will be registered by 
+         * the OTG PSL. In this case, the DFC queue supplied here must be the 
+         * same DFC queue as the one supplied in the properties of the OTG 
+         * Controller.
+         */
+        TDfcQue* iDfcQueue;
+        
+        /** 
+         * Describe the capabilities of all endpoint owned by this controller.
+         *
+         * Note that there might be gaps in the array, because the endpoints 
+         * must be numbered by using the 'real endpoint' numbering scheme.
+         *
+         * An example of end point capability array:
+         *
+         * @code
+         * static const TUsbPeripheralEndpointCaps DevEndpointCaps[KTotalEps] =
+         * {
+         * // MaxSize mask  ,   Types&Dir                      , High  ,Reserved
+         *                                                       speed?
+         * {KEp0MaxPktSzMask,(KUsbEpTypeControl | KUsbEpDirOut), ETrue ,0 , 0},
+         * {KEp0MaxPktSzMask,(KUsbEpTypeControl | KUsbEpDirIn ), ETrue ,0 , 0},
+         *      
+         * {KUsbEpNotAvailable,KUsbEpNotAvailable              , ETrue ,0 , 0},
+         *      
+         * {KBlkMaxPktSzMask,(KUsbEpTypeBulk | KUsbEpDirIn )   , ETrue ,0 , 0},
+         * {KBlkMaxPktSzMask,(KUsbEpTypeBulk | KUsbEpDirOut)   , ETrue ,0 , 0}
+         * };
+         * @endcode
+         *
+         * For endpoint maxinum packet size on USB2.0 High-speed, PSL should
+         * provide the overlaid values for both full speed and high speed, as 
+         * PIL can deduce the appropriate values for either speed.
+         *
+         */
+        const TUsbPeripheralEndpointCaps* iDeviceEndpointCaps;
+        
+        /** 
+         * Set by the PSL to indicate the number of entries in 
+         * iDeviceEndpointCaps array.
+         * Be noted that this value include the ones that are marked as 
+         * KUsbEpNotAvailable in table iDeviceEndpointCaps.
+         */
+        TInt iDeviceTotalEndpoints;
+        
+        /** 
+         * Maximum size of ep0 packet.
+         * @see USB spec 2.0, chapter 9, table 9-8.
+         */
+        TUint8  iMaxEp0Size;
+        
+        /** 
+         * Device Release number in binary-coded decimal.
+         * @see USB spec 2.0, chapter 9, table 9-8.
+         */
+        TUint16  iDeviceRelease;
+        };
+    
+    /** 
+     * Enumeration of stages within a control transfer
+     * 
+     * Possible stages defined in USB spec include:
+     * 1. setup -> status in
+     * 2. setup -> data in -> status out
+     * 3. setup -> data out -> status in
+     */
+    enum TControlStage
+        {
+        /** 
+         * Control transfer always start with a setup stage in which a setup
+         * packet is expected.         
+         */
+        EControlTransferStageSetup,
+        
+        /** The stage that a data packet is expected from be received */
+        EControlTransferStageDataOut,
+        
+        /**
+         * Status in stage can either following a Setup stage (if no data stage)
+         * or following a data out stage.
+         */
+        EControlTransferStageStatusIn,
+                
+        /** 
+         * Depends on the request type of a setup packet, a data in stage maybe 
+         * followed after a setup packet.
+         *
+         * Within this stage we expect upper/ourself to send some data to host.
+         */
+        EControlTransferStageDataIn,
+        
+        /**
+         * This is an optional stage, some controller will silently swallow
+         * Status out packet and not able to report it.
+         * PIL has consider this situation when control transfer state machine
+         * is introduced.
+         */
+        EControlTransferStageStatusOut,
+               
+        EControlTransferStageMax
+        };
+    
+    /** 
+     * Packet types in control transfers.
+     * 
+     * PSL need to tell PIL about the types of each packet it received.
+     * @see MUsbPeripheralPilCallbackIf::Ep0RequestComplete().
+     */
+    enum TControlPacketType
+        {
+        /** Indicates a setup packet */
+        EControlPacketTypeSetup,
+        
+        /** Indicates a data out packet */
+        EControlPacketTypeDataOut,
+        
+        /** 
+         * Indicates a status in packet.
+         * optional, PSL can select not to complete this packet.
+         */
+        EControlPacketTypeStatusIn,
+        
+        /** Indicates a data in packet */
+        EControlPacketTypeDataIn,
+        
+        /** 
+         * Indicates that a status out packet.
+         * optional, PSL can select not to complete this packet.
+         */
+        EControlPacketTypeStatusOut,
+
+        };
+    
+    /** 
+     * @brief Interface for PSL to do callback to PIL
+     * 
+     * This is the interface that a PSL need talk with PIL in order to:
+     * 1. Pass device event (reset/suspend/resume/vbus high/vbus low etc) to PIL.
+     * 2. Complete a read/write request to PIL.
+     * 3. Query control transfer stage from PIL.
+     * 3. Other functions like SetAdress/Handle HNP/Get remote wake up etc.
+     *
+     * This interface already been implemented and exported via library 
+     * usbperipheralpil.lib. PSL need to add this library as a dependency in 
+     * you PSL .mmp file.
+     *
+     * @lib  usbperipheralpil.lib
+     */
+    NONSHARABLE_CLASS(MUsbPeripheralPilCallbackIf)
+        {
+        public:
+        /** 
+         * Used to synchronize the Ep0 Stage machine between PSL and PIL.
+         * Accepts a SETUP packet and returns the next Ep0 Stage.
+         *
+         * This function will NOT lead anything to be changed at PIL, it is 
+         * functioning by parsing the supplied buffer only.
+         *
+         * @param aSetupBuf The SETUP packet received by PSL.
+         * @return The next Ep0 Stage at PIL if PIL receive this setup packet.
+         *
+         */
+        virtual TControlStage EnquireEp0NextStage(const TUint8* aSetupBuf) const = 0;
+        
+        /** 
+         * This function gets called by PSL upon completion of a pending 
+         * endpoint zero data transfer request.
+         *
+         * @param aRealEndpoint Either 0 for Ep0 OUT (= Read)
+         *                      or 1 for Ep0 IN (= Write).
+         * @param aCount The number of bytes received or transmitted.
+         * @param aError The error code of the completed transfer request. 
+         *               KErrNone if no error.
+         *               KErrCancel if transfer was cancelled.
+         *               KErrPrematureEnd if a premature end was encountered.
+         * @param aPktType The type of the packet that being completed.
+         * 
+         * @return KErrNone if no error during transfer completion processing;
+         *  KErrGeneral if request was a read & a Setup packet was received &
+         *  the recipient for that packet couldn't be found (invalid packet: Ep0
+         *  has been stalled); KErrNotFound if the request was a read & the 
+         *  recipient for that packet (Setup or data) _was_ * found - however no
+         *  read had been set up by that recipient (this case should be used by 
+         *  PSL to disable Ep0 interrupt at that point and give the upper layer 
+         *  software time to set up a new Ep0 read; once the 'missing' read was 
+         *  set up either Ep0DataReceiveProceed or Ep0ReadSetupPktProceed of 
+         *  MPeripheralControllerIf class  will be called by PIL).
+         */
+        virtual TInt Ep0RequestComplete(TInt aRealEndpoint, 
+                                        TInt aCount, 
+                                        TInt aError, 
+                                        TControlPacketType aPktType) = 0;
+    
+        /** 
+         * PSL call this function upon completion of a pending data transfer 
+         * request. This function isn't to be used for endpoint zero completions
+         * (use Ep0RequestComplete instead).
+         * 
+         * @param aCallback A pointer to a data transfer request callback 
+         *        structure which was previously passed to PSL in a 
+         *        SetupEndpointWrite() or SetupEndpointRead() call.
+         * 
+         */
+        virtual void EndpointRequestComplete(TUsbPeripheralRequest* aCallback) = 0;
+        
+        /**
+         * This function gets called by PSL upon detection of either of the 
+         * following events:
+         *   - USB Reset,
+         *   - USB Suspend event,
+         *   - USB Resume signaling,
+         *
+         * When the Peripheral Controller PSL is part of an
+         * OTG-capable port, the PSL shall report the above events
+         * also when operating as the A-peripheral, including
+         * reporting the final suspend event that starts the HNP role
+         * switch back to A-host.
+         *
+         * In addition to the events above, a stand-alone peripheral
+         * controller PSL (one not associated with an OTG port) is
+         * required to report the following events:
+         *   - VBUS rising above the session valid threshold
+         *   - VBUS falling below the session valid threshold
+         * 
+         * When the peripheral controller is part of an OTG port, the
+         * PIL layer receives VBUS notifications via the OTG stack,
+         * and the peripheral PSL is not expected to report them via
+         * this interface.
+         *
+         * When USB Battery Charging is supported on the
+         * peripheral-only port, there is a dependency between normal
+         * USB functionality and USB Battery Charging (see
+         * usb_charger_detection_shai.h and specifically the
+         * description of class MChargerDetectorIf). In this case it
+         * is the responsibility of the Peripheral Controller PSL to
+         * communicate with the Charger Detector PSL (which it may
+         * implement itself) with respect to VBUS events.
+         *
+         * When VBUS rises on the peripheral-only port that fully
+         * supports Battery Charging Specification Revision 1.1, the
+         * Charger Detector PSL and the Peripheral Controller PSL need
+         * to together guarantee that Data Contact Detect is completed
+         * and the port type detected before notifying VBUS rising.
+         * When the port type is known, the port type needs to be
+         * notified to the Charger Detector PSL Observer, followed by
+         * notifying a VBUS rising event to the Peripheral Controller
+         * PIL callback interface (via this function).
+         *
+         * Where Data Contact Detect is not supported, the VBUS rise
+         * event needs to be notified to the Peripheral Controller PIL
+         * callback interface (via this function) immediately and
+         * charger detection needs to proceed in parallel with the
+         * upper layers preparing the USB personality. This is
+         * necessary in order to ensure that we can fulfill the
+         * requirement to connect to the bus within a second, while
+         * still making as long as possible charger detection cycle to
+         * minimize the changes of false detections due to datalines
+         * not making contact yet.
+         *
+         * The Peripheral Controller PSL and the Charger Detector PSL
+         * need to together guarantee that the peripheral controller
+         * does not attempt to connect to the bus while charger
+         * detection is still on-going. When detection has been
+         * completed and upper layers have indicated readiness to
+         * connect to the bus (see MPeripheralControllerIf::PeripheralConnect(),
+         * the Peripheral Controller PSL must connect to the bus.
+         *
+         * @param aEvent An enum denoting the event that has occurred.
+         *        
+         * @return KErrArgument if the event is not recognized, KErrNone
+         *         otherwise
+         */
+        virtual TInt DeviceEventNotification(TUsbPeripheralEvent aEvent) = 0;
+        
+        /** 
+         * This function should be called by PSL once the peripheral 
+         * controller (and thus the USB device) is in the Address state.
+         */
+        virtual void MoveToAddressState() = 0;
+        
+        /** 
+         * This function should be called by PSL after reception of an Ep0
+         * SET_FEATURE request with a feature selector of either {b_hnp_enable,
+         * a_hnp_support, a_alt_hnp_support}, but ONLY when that Setup packet is
+         * not handed up to PIL (for instance because it is auto-decoded and
+         * 'swallowed' by the peripheral controller hardware).
+         * 
+         * @param aHnpState A bitmask indicating the present state of the three
+         * OTG feature selectors as follows:
+         * 
+         * bit.0 == a_alt_hnp_support
+         * bit.1 == a_hnp_support
+         * bit.2 == b_hnp_enable
+         *
+         * @see TUsbHnpCaps
+         * 
+         */
+        virtual void HandleHnpRequest(TInt aHnpState) = 0;       
+        
+        /**
+         * Returns the current USB device state.
+         * 
+         * 'USB device state' here refers to the device states as defined 
+         * in chapter 9 of the USB specification.
+         * 
+         * @return The current USB device state, or EUsbPeripheralStateUndefined
+         *         if peripheral stack is disabled.
+         *
+         */
+        virtual TUsbPeripheralState DeviceStatus() const = 0;
+        
+        };
+    
+    /** 
+     * MPeripheralControllerIf
+     * @brief Abstract class for USB peripheral Chipset API.
+     * @version   0.2.
+     *
+     * PSL driver need to implement all those virtual functions in this class.
+     *    
+     * Four Steps to create a vendor specific usb peripheral PDD.
+     *
+     *    Step 1: Derive a new class from MUsbPeripheralControllerIf and 
+     *            implement all interfaces defined. 
+     *              
+     *    Step 2: Create a new instance (we call it inst_of_psl) of the new class.
+     *            Prepare the configuration data defined by structure
+     *            TUsbPeripheralControllerProps (let's call it cfg_data )
+     *
+     *    Step 3: Call UsbPeripheralPil::RegisterPeripheralController(inst_of_psl,cfg_data).
+     *                        
+     *    Step 4: Member function SetPilCallbackInterface() will be called. 
+     *            An instance of MUsbPeripheralPilCallbackIf will be passed to 
+     *            PSL via this call. Record it since PSL need to reuse it later 
+     *            for any PIL functionality callback.
+     *            
+     *    That's all.
+     *    
+     *    dynamic view of PDD creation.
+     *            PIL will be compiled and linked alone.
+     *            PSL will be compiled alone and linked against a new lib named
+     *            usbperipheralpil.lib.
+     *
+     *    For PSL vendors, the following stuff are provided:
+     *            usb_peripheral_shai.h & usb_peripheral_shai_shared.h which is 
+     *            used for PSL to implement against.
+     *            usbperipheralpil.lib which is used for PSL to link against.
+     *
+     */
+    NONSHARABLE_CLASS(MPeripheralControllerIf)
+        {
+        public: 
+        /** 
+         * This function will be called once and only once by PIL when a PSL
+         * registered itself to PIL by calling 
+         * UsbPeripheralPil::RegisterPeripheralController().
+         *
+         * PSL is expected to store the callback interface pointer so that make 
+         * it possible to reporting events back to PIL layer.
+         *
+         * For stand-alone peripheral controllers (controllers not associated 
+         * with an OTG port),the Peripheral Controller PSL is required to report
+         * a EUsbEventVbusRisen event by calling MUsbPeripheralPilCallbackIf::
+         * DeviceEventNotification() if VBUS is already high at the point this 
+         * function is called.
+         *
+         * @param aPilCallbackIf A reference to PIL callback interface which
+                  a PSL must use to report events.
+         */
+        virtual void SetPilCallbackInterface(MUsbPeripheralPilCallbackIf& aPilCallbackIf) = 0;
+        
+        /**
+         * Sets endpoint zero's RX buffer.
+         * This buffer is maintains at PIL and always exists.
+         *
+         * @param aBuffer the buffer address
+         * @param aBufferLen the length of the buffer.
+         *        
+         */
+        virtual void SetEp0RxBuffer(TUint8* aBuffer, TInt aBufferLen) = 0;
+        
+        /** 
+         * Determines the speed mode that this controller is operating at.
+         *
+         * @return one of the speed mode defined by TSpeed.
+         * @see TSpeed.
+         */
+        virtual TSpeed DeviceOperatingSpeed() = 0;
+        
+        /** 
+         * Forces the peripheral controller into a non-idle state to perform a 
+         * USB remote wakeup operation.
+         *
+         * PIL layer will make sure the following preconditions are meet before
+         * calling this function:
+         *   1. we're already in suspended state for at least 5ms (Twtrsm).
+         *   2. remote wakeup had been enabled by host.
+         *
+         * @return KErrNone if successful, otherwise one of the system-wide 
+         *         error codes.
+         */
+        virtual TInt SignalRemoteWakeup() = 0;
+
+        /** 
+         * This function will be called by PIL upon decoding a SET_ADDRESS
+         * request. PIL will make sure that a status packet will be sent before
+         * calling this function as USB spec required if capability of 
+         * KDevCapSetAddressAcceleration is not support by hardware; Otherwise
+         * SetAddress call will go ahead of status packet.
+         * @see KDevCapSetAddressAcceleration
+         *
+         * @param aAddress A valid USB device address that was received with the
+         *        SET_ADDRESS request.
+         *
+         * @return KErrNone if address was set successfully or if controller's 
+         *         address cannot be set manually. otherwise one of the system-
+         *         wide error codes.
+         */
+        virtual TInt SetDeviceAddress(TInt aAddress) = 0;
+        
+        /** 
+         * Configures (enables) an endpoint (incl. Ep0) for data transmission or
+         * reception.
+         *
+         * @param aRealEndpoint The number of the endpoint to be configured.
+         * @param aEndpointInfo A properly filled-in endpoint info structure.
+         *
+         * @return KErrNone if endpoint successfully configured; KErrArgument if
+         *         endpoint number or endpoint info invalid; otherwise one of 
+         *         the system-wide error codes.
+         */
+        virtual TInt ConfigureEndpoint(TInt aRealEndpoint, 
+                                     const TUsbPeripheralEndpointInfo& aEndpointInfo) = 0;
+        
+        /** 
+         * De-configures (disables) an endpoint (incl. Ep0).
+         *
+         * @param aRealEndpoint The number of the endpoint to be disabled.
+         *
+         * @return KErrNone if endpoint successfully de-configured; KErrArgument
+         *         if endpoint number invalid; otherwise one of the system-wide 
+         *         error codes.
+         */
+        virtual TInt DeConfigureEndpoint(TInt aRealEndpoint) = 0;
+        
+        /** 
+         * Queries the use of and endpoint resource.
+         *
+         * @param aRealEndpoint The number of the endpoint.
+         * @param aResource The endpoint resource to be queried.
+         *        they are one of the following currently:
+         *           KUsbEndpointInfoFeatureWord1_DMA.
+         *           KUsbEndpointInfoFeatureWord1_DoubleBuffering.
+         *
+         * @return ETrue if the specified resource is in use at the endpoint, 
+         *         EFalse if not.
+         */
+        virtual TBool QueryEndpointResource(TInt aRealEndpoint, TUint32 aResource) const = 0;
+        
+        /** 
+         * Sets up a read request on an endpoint (excl. Ep0) for data reception.
+         * 
+         * PIL will construct a read request as aCallback, and use this function
+         * to setup and indicate the readiness for reading data from end point.
+         * 
+         * PSL need to update related data member of aCallback and complete this
+         * request by calling EndpointRequestComplete() when request is done.
+         * 
+         * @see TUsbPeripheralRequest
+         *
+         * @param aRealEndpoint The number of the endpoint to be used.
+         * @param aCallback A properly filled-in (by PIL) request callback.
+         *
+         * @return KErrNone if read successfully set up; KErrArgument if endpoint
+         *         number is invalid. otherwise one of the system-wide error 
+         *         codes.
+         */
+        virtual TInt SetupEndpointRead(TInt aRealEndpoint, TUsbPeripheralRequest& aCallback) = 0;
+        
+        /** 
+         * Sets up a write request on an endpoint (excl. Ep0) for transmission.
+         *
+         * PIL will contruct a write request as aCallback, and use this function
+         * to pass down it to PSL.
+         * 
+         * PSL need to update related data member of aCallback and complete this
+         * request by calling EndpointRequestComplete() when data is transmitted
+         * or any error found.
+         * @see TUsbPeripheralRequest
+         *
+         * @param aRealEndpoint The number of the endpoint to be used.
+         * @param aCallback A properly filled-in request callback.
+         *
+         * @return KErrNone if write successfully set up; KErrArgument if 
+         *         endpoint number is invalid; otherwise one of the system-wide 
+         *         error codes.
+         */
+        virtual TInt SetupEndpointWrite(TInt aRealEndpoint, TUsbPeripheralRequest& aCallback) = 0;
+        
+        /** 
+         * Cancels a read request on an endpoint (excl. Ep0).
+         *
+         * Note that endpoint 0 read requests are never cancelled by PIL, so
+         * there is also no CancelEndpointZeroRead() function.
+         *
+         * @param aRealEndpoint The number of the endpoint to be used.
+         *
+         * @return KErrNone if read successfully cancelled; KErrArgument if 
+         *         endpoint number is invalid; otherwise one of the system-wide 
+         *         error codes.
+         */
+        virtual TInt CancelEndpointRead(TInt aRealEndpoint) = 0;
+        
+        /** 
+         * Cancels a write request on an endpoint (incl. Ep0).
+         *
+         * PIL calls this function also to cancel endpoint zero write requests.
+         *
+         * @param aRealEndpoint The number of the endpoint to be used.
+         *
+         * @return KErrNone if write successfully cancelled; KErrArgument if 
+         *         endpoint number is invalid; otherwise one of the system-wide 
+         *         error codes.
+         */
+        virtual TInt CancelEndpointWrite(TInt aRealEndpoint) = 0;
+        
+        /** 
+         * Same as SetupEndpointRead(), but for endpoint zero only.
+         *
+         * No callback structure is used here as reading to ep0 (host may at any
+         * time send a SETUP packet) must be ready even before upper application
+         * is ready. So, a buffer will be passed down to PSL by 
+         * MPeripheralControllerIf::SetEp0RxBuffer() during PIL construction,
+         * this will benefits the PSL to have a buffer always available for this
+         * purpose.
+         *
+         * PSL must complete this request by EndpointRequestComplete()
+         *
+         * @return KErrNone if read successfully set up; otherwise one of the 
+         *         system-wide error codes.
+         */
+        virtual TInt SetupEndpointZeroRead() = 0;
+        
+        /** 
+         * Same as SetupEndpointWrite(), but for endpoint zero only.
+         *
+         * No callback is used here as this function is only used by
+         * PIL layer only and no user side request exists for it.
+         *
+         * @param aBuffer This points to the beginning of the data to be sent.
+         * @param aLength The number of bytes to be sent.
+         * @param aZlpReqd ETrue if a ZLP is must be sent after the data.
+         *
+         * PSL must complete this request by EndpointRequestComplete()
+         *
+         * @return KErrNone if write successfully set up; otherwise one of the 
+         *         system-wide error codes.
+         */
+        virtual TInt SetupEndpointZeroWrite(const TUint8* aBuffer, 
+                                            TInt aLength, 
+                                            TBool aZlpReqd = EFalse) = 0;
+        
+        /** 
+         * Sets up on Ep0 for the transmission of a single zero-length packet.
+         *
+         * @return KErrNone if ZLP successfully set up; otherwise one of the 
+         *         system-wide error codes.
+         */
+        virtual TInt SendEp0ZeroByteStatusPacket() = 0;
+        
+        /** 
+         * Stalls an endpoint (incl. Ep0).
+         *
+         * Not applicable to Isochronous endpoints.
+         *
+         * @param aRealEndpoint The number of the endpoint to be stalled.
+         *
+         * @return KErrNone if endpoint successfully stalled; KErrArgument if 
+         *         endpoint number is invalid; otherwise one of the system-wide 
+         *         error codes.
+         */
+        virtual TInt StallEndpoint(TInt aRealEndpoint) = 0;
+        
+        /** 
+         * Clears the stall condition on an endpoint (incl. Ep0).
+         *
+         * Not applicable to Isochronous endpoints.
+         *
+         * @param aRealEndpoint The number of the endpoint to be stalled.
+         *
+         * @return KErrNone if endpoint successfully de-stalled; KErrArgument if
+         *         endpoint number invalid; otherwise one of the system-wide 
+         *         error codes.
+         */
+        virtual TInt ClearStallEndpoint(TInt aRealEndpoint) = 0;
+        
+        /**
+         * Resets the data toggle bit for an endpoint (incl. Ep0).
+         *
+         * Isochronous endpoints don't use data toggles.
+         *
+         * @param aRealEndpoint The number of the endpoint to be used.
+         *
+         * @return KErrNone if data toggle successfully reset; KErrArgument if 
+         *         endpoint number invalid; otherwise one of the system-wide 
+         *         error codes.
+         */
+        virtual TInt ResetDataToggle(TInt aRealEndpoint) = 0;
+        
+        /** 
+         * Returns the frame number of the last received SOF packet.
+         *
+         * @return The (11-bit) frame number of the last received SOF packet.
+         *
+         */
+        virtual TInt SynchFrameNumber() const = 0;
+        
+        /** 
+         * Stores the (11-bit) frame number that should be sent in response to
+         * the next SYNCH_FRAME request(s).
+         *
+         * @param aFrameNumber The (11-bit) frame number to be set
+         */
+        virtual void SetSynchFrameNumber(TInt aFrameNumber) = 0;
+        
+        /** 
+         * Starts peripheral controller.
+         *
+         * This initializes the device controller hardware before any other 
+         * operation can be performed. 
+         * Tasks to be carried out here might include:
+         *     - resetting the whole peripheral controller design
+         *     - enabling the peripheral controller's clock
+         *     - binding & enabling the peripheral controller (primary) interrupt
+         *     - write meaningful values to some general controller registers
+         *     - enabling the USB Reset interrupt
+         *     - enabling the peripheral controller proper (for instance by 
+         *       setting an Enable bit).
+         *
+         * This function is also used in an OTG environment when the
+         * peripheral stack becomes enabled and the controller needs
+         * to be started and enabled for peripheral use. If the HW
+         * platform shares resources such as clocks and power between
+         * the host and peripheral HW, it is probably easiest for the
+         * PSL to handle the role switch based on the
+         * MOtgControllerIf::SetControllerRole() call to the OTG
+         * Controller interface.
+         *
+         * @return KErrNone if the controller was successfully started;
+         *         otherwise one of the system-wide error codes.
+         *
+         * @see usb_otg_shai.h, MOtgControllerIf::SetControllerRole()
+         */
+        virtual TInt StartPeripheralController() = 0;
+    
+        /** 
+         * Stops the peripheral controller.
+         *
+         * This basically makes undone what happened in StartPeripheralController(). 
+         * Tasks to be carried out here might include:
+         * - disabling peripheral controller proper.
+         * - disabling the USB Reset interrupt.
+         * - disabling & unbinding the peripheral controller (primary) interrupt.
+         * - disabling the peripheral controller's clock.
+         *
+         * This function is also used in an OTG environment when the peripheral 
+         * stack becomes disabled and the peripheral hardware resources can be 
+         * released. If the hardware platform shares resources such as clocks 
+         * and power between the host and peripheral hardware, it is probably 
+         * easiest for the PSL to handle the role switch based on the
+         * MOtgControllerIf::SetControllerRole() call to the OTG Controller 
+         * interface.
+         *
+         * @return KErrNone if peripheral controller successfully stopped;
+         *         otherwise one of the system-wide error codes.
+         *
+         * @see usb_otg_shai.h, MOtgControllerIf::SetControllerRole()
+         */         
+        virtual TInt StopPeripheralController() = 0;
+    
+        /** 
+         * This function is used to indicate that upper layers are ready to 
+         * start operating as peripheral and want to connect to the USB bus
+         * if possible.
+         *
+         * Since this functionality is not part of the USB specification it
+         * has to be explicitly supported, either by the peripheral controller
+         * itself or by the hardware platform.
+         *
+         * This call merely reports the upper layer readiness to connect, and
+         * it is the responsiblity of the PSL to assess when all prerequisites
+         * for connection are satisfied and physically connect when they are.
+         * These prerequisites include:
+         *
+         *  1. Upper layer readiness has been indicated by calling 
+         *     PeripheralConnect().
+         *
+         *  2. The peripheral controller has been started and enabled
+         *     by StartPeripheralController().
+         *
+         * The connection readiness assessment responsibility is delegated to the
+         * PSL because the physical connection may sometimes be handled by a HW
+         * state machine, thus making the correct SW-controlled connection time
+         * HW-specific.
+         *
+         * @return KErrNone if peripheral controller successfully connected;
+         *         otherwise one of the system-wide error codes.
+         */
+        virtual TInt PeripheralConnect() = 0;
+    
+        /** 
+         * Called to indicate that upper layers no longer want to operate as the
+         * peripheral and we must disconnect from the USB bus.
+         *
+         * Since this functionality is not part of the USB specification it
+         * has to be explicitly supported, either by the peripheral controller
+         * itself or by the hardware platform.
+         *
+         * @return KErrNone if controller is successfully disconnected;
+         *         otherwise one of the system-wide error codes.
+         */
+        virtual TInt PeripheralDisconnect() = 0;       
+        
+        /**
+         * Implements anything peripheral controller might required by following
+         * bus resume signal.
+         *
+         * This function gets called by PIL after it has been notified (by
+         * PSL) about the Suspend condition.
+         */
+        virtual void Suspend() = 0;
+        
+        /**
+         * Implements anything peripheral controller might required by following
+         * bus resume signal.
+         *
+         * This function gets called by PIL after it has been notified (by
+         * PSL) about the Resume event.
+         */
+        virtual void Resume() = 0;
+        
+        /**          
+         * Implements anything peripheral controller might required by following
+         * bus resume signal.
+         *
+         * This function gets called by PIL after it has been notified (by
+         * PSL) about the Reset event.
+         */
+        virtual void Reset() = 0;
+        
+        /** 
+         * PIL call this function to signal PSL that it has finished processing
+         * a received Setup packet (on Ep0) and that PSL can now prepare 
+         * itself for the next Ep0 reception.
+         *
+         * The reason for having this function is that the situation where no 
+         * Ep0 read has been set up by user and thus a received Setup packet
+         * cannot immediately be delivered to user. Once user however 
+         * sets up an Ep0 read, PIL then completes the request and eventually 
+         * calls this function. We can implement some sort of flow-control by
+         * this way.
+         */
+        virtual void Ep0ReadSetupPktProceed() = 0;
+        
+        /** 
+         * PIL call this function to signal PSL that it has finished processing 
+         * a received Ep0 data packet and that PSL can now prepare itself for 
+         * the next Ep0 reception.
+         *
+         * The reason for having this function is that the situation where no 
+         * Ep0 read has been set up by user and thus a received Setup packet
+         * cannot immediately be delivered to user. Once user however 
+         * sets up an Ep0 read, PIL then completes the request and eventually 
+         * calls this function. We can implement some sort of flow-control by
+         * this way.
+         */
+        virtual void Ep0ReadDataPktProceed() = 0;
+        
+        /** 
+         * Puts controller into a specific test mode (during HS operation only).
+         *
+         * 9.4.9 Set Feature: "The transition to test mode must be complete no
+         * later than 3 ms after the completion of the status stage of the 
+         * request." (The status stage will have been completed immediately 
+         * before this function gets called.)
+         *
+         * @param aTestSelector The specific test mode selector.
+         *
+         * @return KErrNone if the specified test mode was entered successfully;
+         *         otherwise one of the system-wide error codes.
+         */
+        virtual TInt EnterTestMode(TUsbTestModeSelector aTestSelector) = 0;
+        };
+
+   
+    /**
+     * This static class provides the interface which PSL implementation shall 
+     * use to register itself to PIL layer.
+     */
+    NONSHARABLE_CLASS(UsbPeripheralPil)
+        {
+        public:
+        /**
+         * Registration function to be used by a stand-alone (non-OTG
+         * port) Peripheral Controller PSL to register itself to the
+         * PIL layer. Peripheral Controllers that are part of an
+         * OTG-port are registered by the OTG Controller PSL (see
+         * usb_otg_shai.h, function UsbOtgPil::RegisterOtgController).
+         *
+         * The intended usage is that each stand-alone Peripheral
+         * Controller PSL is a kernel extension that registers itself
+         * to the USB Peripheral PIL layer by making this call from
+         * their own kernel extension entry point function (or an
+         * equivalent code that runs during bootup).
+         *
+         * When the PSL makes this call, PIL layer will call 
+         * SetPilCallbackInterface() function of the supplied Peripheral 
+         * Controller interface to supply the PSL a reference to PIL 
+         * callback interface to be used for reporting peripheral events.
+         *
+         * @param aPeripheralControllerIf Reference to the Peripheral
+         *   Controller interface implemented by the registering PSL.
+         *
+         * @param aProperties Reference to an object describing the
+         *   static properties of the Peripheral Controller. PIL
+         *   layer requires that the supplied reference remains valid
+         *   indefinitely, as a Peripheral Controller cannot unregister.
+         *
+         * @lib usbperipheralpil.lib
+         */
+        IMPORT_C static void RegisterPeripheralController(MPeripheralControllerIf& aPeripheralControllerIf, 
+                                                      const TPeripheralControllerProperties& aProperties );
+    
+        private:
+        /**
+         *  No instance of this class need to be created
+         */
+        UsbPeripheralPil();
+        };
+    };
+
+#include <usb/usb_peripheral_shai.inl>
+    
+#endif // USB_PERIPHERAL_SHAI_H
+
+// End of File
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usb_plat/usb_shai_api/inc/usb_peripheral_shai.inl	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,36 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+#ifndef USB_PERIPHERAL_SHAI_INL
+#define USB_PERIPHERAL_SHAI_INL
+
+//
+// inline constructor for TPeripheralControllerProperties.
+// The responsibility of this constructor is to reset all
+// data member of TPeripheralControllerProperties to zero.
+//
+inline UsbShai::TPeripheralControllerProperties::TPeripheralControllerProperties():
+    iControllerCaps(0),
+    iDfcQueue(NULL),
+    iDeviceEndpointCaps(NULL),
+    iDeviceTotalEndpoints(0),
+    iMaxEp0Size(0),
+    iDeviceRelease(0)
+    {
+    }
+ 
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usb_plat/usb_shai_api/inc/usb_peripheral_shai_shared.h	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,200 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+/** @file
+
+    @brief USB Peripheral SHAI header shared part.
+
+    Some Non-kernel USB code will also use structure defined in this
+    header.  Since usb_peripheral_shai.h always need to include
+    <kern_priv.h> which is not visible to non-kernel layers, a
+    separated header is needed.
+    
+    This header is the one that defined all common structures used by
+    kernel & non-kernel layers software.
+    
+    Peripheral SHAI header always include this header automatically.
+    
+    @publishedDeviceAbstraction
+*/
+
+#ifndef USB_PERIPHERAL_SHAI_SHARED_H
+#define USB_PERIPHERAL_SHAI_SHARED_H
+
+// The namespace is documented in file usb_common_shai.h, so it is not
+// repeated here
+namespace UsbShai
+    {
+    /** 
+     * Bitmaps for TUsbPeripheralEndpointCaps.iSupportedTypesAndDir.
+     * Endpoint supports Control transfer type.
+     */
+    const TUint KUsbEpTypeControl     = 0x00000001;
+    const TUint KUsbEpTypeIsochronous = 0x00000002;
+    const TUint KUsbEpTypeBulk        = 0x00000004;
+    const TUint KUsbEpTypeInterrupt   = 0x00000008;
+
+    /** Endpoint supports IN transfers. */
+    const TUint KUsbEpDirIn           = 0x80000000;
+    /** Endpoint supports OUT transfers. */
+    const TUint KUsbEpDirOut          = 0x40000000;
+    /** Endpoint supports bidirectional (Control) transfers only.*/
+    const TUint KUsbEpDirBidirect     = 0x20000000;
+    
+    /**
+     * Indicates that whether DMA is preferred to be applied for this endpoint.
+     *
+     * Upper application will declare whether DMA is expected to be used for
+     * this endpoint if there is one available (PSL knows about it) when setup
+     * an interface.
+     * 
+     * PSL can ignore this request if NO DMA is available.
+     *
+     * PIL may query whether a DMA is really applied via interface 
+     * MPeripheralControllerIf::QueryEndpointResource() later.
+     *
+     * @see TUsbPeripheralEndpointInfo::iFeatureWord1.
+     */
+    const TUint KUsbEndpointInfoFeatureWord1_DMA             = 0x00000001;
+
+    /**
+     * Indicates that whether double buffering is preferred to be applied for 
+     * this endpoint. 
+     *
+     * Upper application will declare whether double buffering is expected to 
+     * be used for this endpoint if there is one available (PSL knows about it)
+     * when setup an interface.
+     * 
+     * PSL can ignore this request if NO double buffering is possible.
+     * 
+     * PIL may query whether a double buffering is really applied via interface 
+     * MPeripheralControllerIf::QueryEndpointResource() later.
+     *
+     * @see TUsbPeripheralEndpointInfo::iFeatureWord1.
+     */
+    const TUint KUsbEndpointInfoFeatureWord1_DoubleBuffering = 0x00000002;
+    
+    /** 
+     * These are states that are described in the USB standard.
+     */
+    enum TUsbPeripheralState
+        {
+        EUsbPeripheralStateUndefined,  // 0
+        EUsbPeripheralStateAttached,   // 1
+        EUsbPeripheralStatePowered,    // 2
+        EUsbPeripheralStateDefault,    // 3
+        EUsbPeripheralStateAddress,    // 4
+        EUsbPeripheralStateConfigured, // 5
+        EUsbPeripheralStateSuspended,  // 6
+        EUsbPeripheralNoState = 0xff   // 255 (used as a place holder)
+        };
+    
+    /** 
+     * Endpoint capabilities as reported by the PSL driver.
+     */
+    class TUsbPeripheralEndpointCaps
+        {
+        public:
+        /** The supported maximum packet sizes. */
+        TUint iSizes;
+        
+        /** 
+         * The supported endpoint types and directions.
+         * see the bitmap definition for type and dir inside this header.
+         */
+        TUint iTypesAndDir;
+        
+        /** set it to ETrue if it is a 'high-speed, high bandwidth' endpoint. */
+        TBool iHighBandwidth;
+        
+        /** 
+         * Reserved for future use. 
+         * PSL must set those reserved ram to zero to keep binary compatibility
+         * with new (in furture) PIL binary which may utilize some of the 
+         * reserved space.
+         */
+        TUint32 iReserved[2];
+        };
+    
+    /**
+     * The desired endpoint capabilities.
+     * @see MPeripheralControllerIf::ConfigureEndpoint.
+     */
+    class TUsbPeripheralEndpointInfo
+        {
+        public:
+        /** 
+         * Endpoint type.
+         *(mask: UsbShai::KUsbEpTypeControl, etc., but used as value).
+         */
+        TUint iType;
+        
+        /** Direction (mask: UsbShai::KUsbEpDirIn, etc., but used as value). */
+        TUint iDir;
+        
+        /** Maximum packet size (literal, no mask). */
+        TInt iSize;
+        
+        /** 
+         * Interval for polling full-speed interrupt and isochronous endpoints.
+         * Expressed either directly in milliseconds with a valid range 1..255
+         * (interrupt), or for use as 'value' in the expression of 
+         * interval=2^(value-1) with a valid range 1..16 (isochronous).
+         */
+        TInt iInterval;
+        
+        /** 
+         * Interval for polling high-speed interrupt and isochronous endpoints,
+         * or to specify the NAK rate for high-speed control and bulk OUT
+         * endpoints. Expressed either for use as 'value' in the expression
+         * interval=2^(value-1) with a valid range 1..16 (interrupt and 
+         * isochronous), or directly as the maximum NAK rate with a valid range
+         * 0..255 (control and bulk).
+         */
+        TInt iInterval_Hs;
+        
+        /**
+         * The number of additional transactions per frame to be scheduled(0..2)
+         * (A value greater than zero is only valid for high-speed high bandwidth
+         * interrupt and isochronous endpoints. Also note that there are endpoint
+         * size restrictions associated with additional transactions - see 9.6.6.).
+         */
+        TInt iTransactions;
+        
+        /** 
+         * The number of extra bytes that the standard endpoint descriptor
+         * should be extended by. In almost all cases, this should be 0 (zero).
+         */    
+        TInt iExtra;
+        
+        /** 
+         * 32 flag bits indicating miscellaneous endpoint features.
+         * Currently defined are:
+         * - KUsbEndpointInfoFeatureWord1_DMA which means apply DMA to this 
+         *   endpoint if available.
+         * - KUsbEndpointInfoFeatureWord1_DoubleBuffering which means apply 
+         *   double buffering to this endpoint if available.
+         */
+        TUint32 iFeatureWord1;
+        
+        /** Reserved for future use. */
+        TUint32 iReserved;
+        };
+    }
+#endif //USB_PERIPHERAL_SHAI_SHARED_H
+
+// End of files
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/ldd/perildd/group/base_e32_drivers_usbcli.mrp	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,17 @@
+# component name "USB Client Driver"
+
+component	base_e32_drivers_usbcli
+
+
+source	\sf\os\kernelhwsrv\kernel\eka\drivers\usbc
+source	\sf\os\kernelhwsrv\kernel\eka\drivers\usbcc
+source	\sf\os\kernelhwsrv\kernel\eka\drivers\usbcsc
+
+binary	\sf\os\kernelhwsrv\kernel\eka\drivers\usbc all
+exports	\sf\os\kernelhwsrv\kernel\eka\drivers\usbc
+
+notes_source	\component_defs\release.src
+
+
+ipr E
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/ldd/perildd/group/bld.inf	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,39 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// bld.inf
+// USB Client Driver
+// 
+//
+
+/**
+ @file
+*/
+PRJ_PLATFORMS
+
+BASEDEFAULT
+
+PRJ_MMPFILES
+
+#if defined(GENERIC_MARM) || defined(WINS) || defined(GENERIC_X86)
+#if !defined(MARM_THUMB) && !defined(MARM_ARMI)
+
+#if !defined(WINS) 
+#if !defined(X86)
+usbc
+#endif
+#endif
+
+
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/ldd/perildd/group/usbc.mmp	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,35 @@
+// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32/drivers/usbc/usbc.mmp
+// 
+//
+
+
+#include <kernel/kern_ext.mmh>
+
+OS_LAYER_SYSTEMINCLUDE
+
+
+
+target            usbcshai.ldd
+targettype        ldd
+
+sourcepath      ../src
+source            d_usbc.cpp usbdma.cpp
+
+library            usbperipheralpil.lib
+
+uid             0 0x101F8928
+VENDORID        0x70000001
+capability        all
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/ldd/perildd/src/d_usbc.cpp	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,3233 @@
+// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32/drivers/usbc/d_usbc.cpp
+// LDD for USB Device driver stack:
+// The channel object.
+// 
+//
+
+/**
+ @file d_usbc.cpp
+ @internalTechnology
+*/
+
+#include <usb/usbc.h>
+
+
+_LIT(KUsbLddName, "Usbc");
+
+static const TInt KUsbRequestCallbackPriority = 2;
+
+
+// Quick sanity check on endpoint properties
+static TBool ValidateEndpoint(const TUsbcEndpointInfo* aEndpointInfo)
+    {
+    const TUint dir = aEndpointInfo->iDir;
+    const TInt size = aEndpointInfo->iSize;
+    if (size <= 0)
+        return EFalse;
+
+    switch (aEndpointInfo->iType)
+        {
+    case UsbShai::KUsbEpTypeControl:
+        if (dir != UsbShai::KUsbEpDirBidirect || size > 64)
+            return EFalse;
+        break;
+    case UsbShai::KUsbEpTypeIsochronous:
+        if ((dir != UsbShai::KUsbEpDirIn && dir != UsbShai::KUsbEpDirOut) || size > 1024)
+            return EFalse;
+        break;
+    case UsbShai::KUsbEpTypeBulk:
+        if ((dir != UsbShai::KUsbEpDirIn && dir != UsbShai::KUsbEpDirOut) || size > 512)
+            return EFalse;
+        break;
+    case UsbShai::KUsbEpTypeInterrupt:
+        if ((dir != UsbShai::KUsbEpDirIn && dir != UsbShai::KUsbEpDirOut) || size > 1024)
+            return EFalse;
+        break;
+    default:
+        return EFalse;
+        }
+    return ETrue;
+    }
+
+
+/** Real entry point from the Kernel: return a new driver.
+ */
+DECLARE_STANDARD_LDD()
+    {
+    return new DUsbcLogDevice;
+    }
+
+
+/** Create a channel on the device.
+
+    @internalComponent
+*/
+TInt DUsbcLogDevice::Create(DLogicalChannelBase*& aChannel)
+    {
+    aChannel = new DLddUsbcChannel;
+    return aChannel ? KErrNone : KErrNoMemory;
+    }
+
+
+DUsbcLogDevice::DUsbcLogDevice()
+      {
+      iParseMask = KDeviceAllowUnit;
+      iUnitsMask = 0xffffffff;                                // Leave units decision to the Controller
+      iVersion = TVersion(KUsbcMajorVersion, KUsbcMinorVersion, KUsbcBuildVersion);
+      }
+
+
+TInt DUsbcLogDevice::Install()
+    {
+    // Only proceed if we have the Controller underneath us
+    if (!DUsbClientController::UsbcControllerPointer())
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("LDD Install: USB Controller Not Present"));
+        return KErrGeneral;
+        }
+    return SetName(&KUsbLddName);
+    }
+
+
+//
+// Return the USB controller capabilities.
+//
+void DUsbcLogDevice::GetCaps(TDes8& aDes) const
+    {
+    TPckgBuf<TCapsDevUsbc> b;
+    b().version = iVersion;
+    Kern::InfoCopy(aDes, b);
+    }
+
+
+//
+// Constructor
+//
+DLddUsbcChannel::DLddUsbcChannel()
+    : iValidInterface(EFalse),
+      iAlternateSettingList(NULL),
+      iCompleteAllCallbackInfo(this, DLddUsbcChannel::EmergencyCompleteDfc, KUsbRequestCallbackPriority),
+      iStatusChangePtr(NULL),
+      iStatusCallbackInfo(this, DLddUsbcChannel::StatusChangeCallback, KUsbRequestCallbackPriority),
+      iEndpointStatusChangePtr(NULL),
+      iEndpointStatusCallbackInfo(this, DLddUsbcChannel::EndpointStatusChangeCallback,
+                                  KUsbRequestCallbackPriority),
+      iOtgFeatureChangePtr(NULL),
+      iOtgFeatureCallbackInfo(this, DLddUsbcChannel::OtgFeatureChangeCallback, KUsbRequestCallbackPriority),
+      iNumberOfEndpoints(0),
+      iDeviceState(UsbShai::EUsbPeripheralStateUndefined),
+      iOwnsDeviceControl(EFalse),
+      iAlternateSetting(0),
+      iDeviceStatusNeeded(EFalse),
+      iChannelClosing(EFalse)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("*** DLddUsbcChannel::DLddUsbcChannel CTOR"));
+    iClient = &Kern::CurrentThread();
+    iClient->Open();
+    for (TInt i = 1; i <= KMaxEndpointsPerClient; i++)
+        {
+        iEndpoint[i] = NULL;
+        }
+    for (TInt i = 1; i < KUsbcMaxRequests; i++)
+        {
+        iRequestStatus[i] = NULL;
+        }
+    }
+
+
+DLddUsbcChannel::~DLddUsbcChannel()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcChannel::~DLddUsbcChannel()"));
+    if (iController)
+        {
+        iController->DeRegisterClient(this);
+        iStatusCallbackInfo.Cancel();
+        iEndpointStatusCallbackInfo.Cancel();
+        iOtgFeatureCallbackInfo.Cancel();
+        iCompleteAllCallbackInfo.Cancel();
+        AbortInterface();
+        DestroyAllInterfaces();
+        if (iOwnsDeviceControl)
+            {
+            iController->ReleaseDeviceControl(this);
+            iOwnsDeviceControl = EFalse;
+            }
+        DestroyEp0();
+        delete iStatusFifo;
+        Kern::DestroyClientRequest(iStatusChangeReq);
+        Kern::DestroyClientRequest(iEndpointStatusChangeReq);
+        Kern::DestroyClientRequest(iOtgFeatureChangeReq);
+
+        Kern::DestroyVirtualPinObject(iPinObj1);
+        Kern::DestroyVirtualPinObject(iPinObj2);
+        Kern::DestroyVirtualPinObject(iPinObj3);
+
+        for (TInt i = 0; i < KUsbcMaxRequests; i++)
+            {
+            Kern::DestroyClientBufferRequest(iClientAsynchNotify[i]->iBufferRequest);
+            delete iClientAsynchNotify[i];
+            }
+        }
+    Kern::SafeClose((DObject*&)iClient, NULL);
+    }
+
+
+inline TBool DLddUsbcChannel::ValidEndpoint(TInt aEndpoint)
+    {
+    return (aEndpoint <= iNumberOfEndpoints && aEndpoint >= 0);
+    }
+
+
+//
+// Create channel
+//
+TInt DLddUsbcChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& aVer)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("LDD DoCreateL 1 Ver = %02d %02d %02d",
+                                    aVer.iMajor, aVer.iMinor, aVer.iBuild));
+    if (!Kern::CurrentThreadHasCapability(ECapabilityCommDD,
+                                          __PLATSEC_DIAGNOSTIC_STRING("Checked by USBC.LDD (USB Driver)")))
+        {
+        return KErrPermissionDenied;
+        }
+
+    iController = DUsbClientController::UsbcControllerPointer();
+
+    if (!iController)
+        {
+        return KErrGeneral;
+        }
+
+    iStatusFifo = new TUsbcDeviceStatusQueue;
+    if (iStatusFifo == NULL)
+        {
+        return KErrNoMemory;
+        }
+
+      if (!Kern::QueryVersionSupported(TVersion(KUsbcMajorVersion, KUsbcMinorVersion, KUsbcBuildVersion), aVer))
+        {
+        return KErrNotSupported;
+        }
+
+    // set up the correct DFC queue
+    SetDfcQ(iController->DfcQ(0));                            // sets the channel's dfc queue
+    #ifdef DFC_REALTIME_STATE
+        iDfcQ.SetRealtimeState(ERealtimeStateOn);
+    #endif
+    iCompleteAllCallbackInfo.SetDfcQ(iDfcQ);
+    iStatusCallbackInfo.SetDfcQ(iDfcQ);                        // use the channel's dfcq for this dfc
+    iEndpointStatusCallbackInfo.SetDfcQ(iDfcQ);                // use the channel's dfcq for this dfc
+    iOtgFeatureCallbackInfo.SetDfcQ(iDfcQ);
+    iMsgQ.Receive();                                        //start up the message q
+    TInt r = iController->RegisterClientCallback(iCompleteAllCallbackInfo);
+    if (r != KErrNone)
+        return r;
+    r = iController->RegisterForStatusChange(iStatusCallbackInfo);
+    if (r != KErrNone)
+        return r;
+    r = iController->RegisterForEndpointStatusChange(iEndpointStatusCallbackInfo);
+    if (r != KErrNone)
+        return r;
+    r = iController->RegisterForOtgFeatureChange(iOtgFeatureCallbackInfo);
+    if (r != KErrNone)
+        return r;
+
+    r = Kern::CreateClientDataRequest(iStatusChangeReq);
+    if (r != KErrNone)
+        return r;
+    r = Kern::CreateClientDataRequest(iEndpointStatusChangeReq);
+    if (r != KErrNone)
+        return r;
+    r = Kern::CreateClientDataRequest(iOtgFeatureChangeReq);
+    if (r != KErrNone)
+        return r;
+    
+    Kern::CreateVirtualPinObject(iPinObj1);
+    Kern::CreateVirtualPinObject(iPinObj2);
+    Kern::CreateVirtualPinObject(iPinObj3);
+
+    for (TInt i = 0; i < KUsbcMaxRequests; i++)
+        {
+            iClientAsynchNotify[i] = new TClientAsynchNotify;
+            if(iClientAsynchNotify[i] == NULL)
+                return KErrNoMemory;
+            r = Kern::CreateClientBufferRequest(iClientAsynchNotify[i]->iBufferRequest,1,TClientBufferRequest::EPinVirtual);
+            if (r != KErrNone)
+                {
+                delete iClientAsynchNotify[i];
+                iClientAsynchNotify[i]=NULL;
+                return r;
+                }
+        }
+    
+    return r;
+    }
+
+
+
+void DLddUsbcChannel::CompleteBufferRequest(DThread* aThread, TInt aReqNo, TInt aReason)
+{
+    iRequestStatus[aReqNo]=NULL;
+    Kern::QueueBufferRequestComplete(aThread, iClientAsynchNotify[aReqNo]->iBufferRequest, aReason);
+}
+
+
+TClientBuffer * DLddUsbcChannel::GetClientBuffer(TInt aEndpoint)
+{
+    return iClientAsynchNotify[aEndpoint]->iClientBuffer;
+}
+
+//Runs in client thread
+TInt DLddUsbcChannel::SendMsg(TMessageBase * aMsg)
+{
+    TThreadMessage& m=* (TThreadMessage*)aMsg;
+    TInt id = m.iValue;
+    
+    TInt r = KErrNone;
+    //Cancel Request
+    if (id == KMaxTInt)
+        {
+            r = DLogicalChannel::SendMsg(aMsg);
+            return r;
+        }
+    if (id < 0)
+        {
+        // DoRequest
+        TRequestStatus* pS = (TRequestStatus*) m.Ptr0();
+        r = PreSendRequest(aMsg,~id, pS, m.Ptr1(), m.Ptr2());
+        if (r == KErrNone)
+            {
+            r = DLogicalChannel::SendMsg(aMsg);
+            }
+        }
+    else
+        {
+        //SendControl
+        r = SendControl(aMsg);
+        }
+    return r;
+}
+
+
+TInt DLddUsbcChannel::PreSendRequest(TMessageBase * aMsg,TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
+{
+    TInt r = KErrNone;
+    if (aReqNo >= KUsbcMaxRequests)
+    {
+        Kern::RequestComplete(aStatus, KErrNotSupported);
+        return KErrNotSupported;
+    }
+    if (aReqNo > KUsbcMaxEpNumber)//DoOtherAsyncReq
+    {
+        switch (aReqNo)
+        {
+            case RDevUsbcClient::ERequestEndpointStatusNotify:
+                iEndpointStatusChangeReq->Reset();
+                iEndpointStatusChangeReq->SetStatus(aStatus);
+                iEndpointStatusChangeReq->SetDestPtr(a1);
+            break;
+            case RDevUsbcClient::ERequestOtgFeaturesNotify:
+                iOtgFeatureChangeReq->Reset();
+                iOtgFeatureChangeReq->SetStatus(aStatus);
+                iOtgFeatureChangeReq->SetDestPtr(a1);
+            break;
+            case RDevUsbcClient::ERequestAlternateDeviceStatusNotify:
+                iStatusChangeReq->Reset();
+                iStatusChangeReq->SetStatus(aStatus);
+                iStatusChangeReq->SetDestPtr(a1);
+            break;
+            case RDevUsbcClient::ERequestReEnumerate://WE use bufferrequest to complete even tho we dont add any buffers
+                iClientAsynchNotify[aReqNo]->Reset();
+                r=iClientAsynchNotify[aReqNo]->iBufferRequest->StartSetup(aStatus);
+                if (r != KErrNone)
+                    return r;
+                iClientAsynchNotify[aReqNo]->iBufferRequest->EndSetup();
+            break;
+        }
+    }
+    else //DoTransferAsyncReq
+    {
+            if(a1 == NULL)
+                return KErrArgument;
+            iClientAsynchNotify[aReqNo]->Reset();
+            r=iClientAsynchNotify[aReqNo]->iBufferRequest->StartSetup(aStatus);
+            if (r != KErrNone)
+                return r;
+            kumemget(&iTfrInfo,a1,sizeof(TEndpointTransferInfo));
+            r=iClientAsynchNotify[aReqNo]->iBufferRequest->AddBuffer(iClientAsynchNotify[aReqNo]->iClientBuffer, iTfrInfo.iDes);
+            if (r != KErrNone)
+                return r;
+            iClientAsynchNotify[aReqNo]->iBufferRequest->EndSetup();
+            TThreadMessage& m=*(TThreadMessage*)aMsg;
+            m.iArg[1] = (TAny*)&iTfrInfo; //Use Channel owned TransfereInfo structure 
+    }
+    return KErrNone;
+}
+
+
+void DLddUsbcChannel::HandleMsg(TMessageBase* aMsg)
+    {
+    TThreadMessage& m = *(TThreadMessage*)aMsg;
+    TInt id = m.iValue;
+    if (id == (TInt) ECloseMsg)
+        {
+        iChannelClosing = ETrue;
+        m.Complete(KErrNone, EFalse);
+        return;
+        }
+    else if (id == KMaxTInt)
+        {
+        // Cancel request
+        TInt mask = m.Int0();
+        TInt b = 1;
+        for(TInt reqNo = 0; reqNo < KUsbcMaxRequests; reqNo++)
+            {
+            TRequestStatus* pS = iRequestStatus[reqNo];
+            if ((mask & b) && (pS != NULL))
+                {
+                DoCancel(reqNo);
+                }
+            b <<= 1;
+            }
+        m.Complete(KErrNone, ETrue);
+        return;
+        }
+
+    if (id < 0)
+        {
+        // DoRequest
+        TRequestStatus* pS = (TRequestStatus*) m.Ptr0();
+        DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
+        m.Complete(KErrNone, ETrue);
+        }
+    else
+        {
+        // DoControl
+        TInt r = DoControl(id, m.Ptr0(), m.Ptr1());
+        m.Complete(r, ETrue);
+        }
+    }
+
+
+//
+// Overriding DObject virtual
+//
+TInt DLddUsbcChannel::RequestUserHandle(DThread* aThread, TOwnerType /*aType*/)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcChannel::RequestUserHandle"));
+    // The USB client LDD is not designed for a channel to be shared between
+    // threads. It saves a pointer to the current thread when it is opened, and
+    // uses this to complete any asynchronous requests.
+    // It is therefore not acceptable for the handle to be duplicated and used
+    // by another thread:
+    if (aThread == iClient)
+        {
+        return KErrNone;
+        }
+    else
+        {
+        return KErrAccessDenied;
+        }
+    }
+
+
+//
+// Asynchronous requests - overriding pure virtual
+//
+void DLddUsbcChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
+    {
+    // Check on request status
+    __KTRACE_OPT(KUSB, Kern::Printf("DoRequest 0x%08x", aReqNo));
+        TInt r = KErrNone;
+        if (iRequestStatus[aReqNo] != NULL)
+            {
+            DestroyAllInterfaces();
+            PanicClientThread(ERequestAlreadyPending);
+            }
+        else
+            {
+            TBool needsCompletion;
+            iRequestStatus[aReqNo] = aStatus;
+
+            if (aReqNo > KUsbcMaxEpNumber)
+                {
+                r = DoOtherAsyncReq(aReqNo, a1, a2, needsCompletion);
+                if (needsCompletion)
+                    {
+                    switch (aReqNo)
+                    {
+                        case RDevUsbcClient::ERequestEndpointStatusNotify:
+                            iRequestStatus[aReqNo]=NULL;
+                            Kern::QueueRequestComplete(iClient,iEndpointStatusChangeReq,r);
+                        break;
+                        case RDevUsbcClient::ERequestOtgFeaturesNotify:
+                            iRequestStatus[aReqNo]=NULL;
+                            Kern::QueueRequestComplete(iClient,iOtgFeatureChangeReq,r);
+                        break;
+                        case RDevUsbcClient::ERequestAlternateDeviceStatusNotify:
+                            iRequestStatus[aReqNo]=NULL;
+                            Kern::QueueRequestComplete(iClient,iStatusChangeReq,r);
+                        break;
+                        case RDevUsbcClient::ERequestReEnumerate:
+                            iRequestStatus[aReqNo]=NULL;
+                            Kern::QueueBufferRequestComplete(iClient, iClientAsynchNotify[aReqNo]->iBufferRequest, r);
+                        break;
+                    }
+                  }
+                }
+            else
+                {
+                r = DoTransferAsyncReq(aReqNo, a1, a2, needsCompletion);
+                if (needsCompletion)
+                    {
+                    //Kern::RequestComplete(iClient, iRequestStatus[aReqNo], r);
+                    CompleteBufferRequest(iClient, aReqNo, r);
+                    }
+                }
+            }
+    }
+
+
+
+TInt DLddUsbcChannel::DoOtherAsyncReq(TInt aReqNo, TAny* a1, TAny* a2, TBool& aNeedsCompletion)
+    {
+    // The general assumption is that none of these will complete now.
+    // However, those that make this function return something other than
+    // KErrNone will get completed by the calling function.
+    // So, 1) If you are returning KErrNone but really need to complete because
+    //        completion criteria can be met (for example, sufficient data is
+    //        available in the buffer) and then set aNeedsCompletion = ETrue.
+    //     2) Do NOT complete here AT ALL.
+    //
+    aNeedsCompletion = EFalse;
+    TInt r = KErrNone;
+
+    switch (aReqNo)
+        {
+    case RDevUsbcClient::ERequestAlternateDeviceStatusNotify:
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlReqDeviceStatusNotify"));
+        if (a1 != NULL)
+            {
+            iDeviceStatusNeeded = ETrue;
+            iStatusChangePtr = a1;
+            aNeedsCompletion = AlternateDeviceStateTestComplete();
+            }
+        else
+            r = KErrArgument;
+        break;
+        }
+    case RDevUsbcClient::ERequestReEnumerate:
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("ERequestReEnumerate"));
+        // If successful, this will complete via the status notification.
+        r = iController->ReEnumerate();
+        break;
+        }
+    case RDevUsbcClient::ERequestEndpointStatusNotify:
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("ERequestEndpointStatusNotify"));
+        if (a1 != NULL)
+            {
+            iEndpointStatusChangePtr = a1;
+            }
+        else
+            r = KErrArgument;
+        break;
+            }
+    case RDevUsbcClient::ERequestOtgFeaturesNotify:
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("ERequestOtgFeaturesNotify"));
+        if (a1 != NULL)
+            {
+            iOtgFeatureChangePtr = a1;
+            }
+        else
+            r = KErrArgument;
+        break;
+        }
+    default:
+        r = KErrNotSupported;
+        }
+
+    aNeedsCompletion = aNeedsCompletion || (r != KErrNone);
+
+    return r;
+    }
+
+
+TInt DLddUsbcChannel::DoTransferAsyncReq(TInt aEndpointNum, TAny* a1, TAny* a2, TBool& aNeedsCompletion)
+    {
+    // The general assumption is that none of these will complete now.
+    // however, those that are returning something other than KErrNone will get completed
+    // by the calling function.
+    // So,    1) if you are returning KErrNone but really need to complete because completion criteria can be met
+    //            (for example, sufficient data is available in the buffer) and then set aNeedsCompletion=ETrue..
+    //        2) Do NOT complete here AT ALL.
+    //
+    aNeedsCompletion = EFalse;
+    TInt r = KErrNone;
+    TUsbcEndpoint* pEndpoint = NULL;
+    TUsbcEndpointInfo* pEndpointInfo = NULL;
+    TEndpointTransferInfo* pTfr = NULL;
+
+    if (aEndpointNum == 0)
+        {
+        // ep0 requests
+        if (!(iValidInterface || iOwnsDeviceControl))
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("DoRequest rejected: not configured (Ep0)"));
+            r = KErrUsbInterfaceNotReady;
+            goto exit;
+            }
+        }
+    else
+        {
+        // other eps
+        if (!(iValidInterface && (iDeviceState == UsbShai::EUsbPeripheralStateConfigured ||
+                                  iDeviceState == UsbShai::EUsbPeripheralStateSuspended))
+           )
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("DoRequest rejected not configured (Ep %d)", aEndpointNum));
+            r = KErrUsbInterfaceNotReady;
+            goto exit;
+            }
+        }
+
+    if (!ValidEndpoint(aEndpointNum))
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: DoRequest Read: in error complete"));
+        r = KErrUsbEpNotInInterface;
+        goto exit;
+         }
+
+    if (a1 == NULL)
+        {
+        r = KErrArgument;
+        goto exit;
+        }
+    pTfr = (TEndpointTransferInfo *)a1;
+
+    if (pTfr->iTransferSize < 0)
+        {
+        r = KErrArgument;
+        goto exit;
+        }
+    pEndpoint = iEndpoint[aEndpointNum];
+    if (!pEndpoint)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: DoRequest Read: in error complete"));
+        r = KErrUsbEpNotInInterface;
+        goto exit;
+        }
+
+    pEndpointInfo = pEndpoint->EndpointInfo();
+    __KTRACE_OPT(KUSB, Kern::Printf("DoRequest %d", aEndpointNum));
+
+    switch (pTfr->iTransferType)
+        {
+
+    case ETransferTypeReadData:
+    case ETransferTypeReadPacket:
+    case ETransferTypeReadUntilShort:
+    case ETransferTypeReadOneOrMore:
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("DoRequest Read"));
+        if (pEndpoint->iDmaBuffers->RxIsActive())
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("**** ReadReq ep%d RxActive", aEndpointNum));
+            }
+        else
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("**** ReadReq ep%d RxInActive", aEndpointNum));
+            }
+
+        if (pEndpointInfo->iDir != UsbShai::KUsbEpDirOut &&
+            pEndpointInfo->iDir != UsbShai::KUsbEpDirBidirect)
+            {
+            // Trying to do the wrong thing
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: DoRequest Read: in error complete"));
+            r = KErrUsbEpBadDirection;
+            break;
+            }
+        // Set the length of data to zero now to catch all cases
+        TPtrC8 pZeroDesc(NULL, 0);
+        r=Kern::ThreadBufWrite(iClient,iClientAsynchNotify[aEndpointNum]->iClientBuffer, pZeroDesc, 0, 0,iClient);
+        if (r != KErrNone)
+            PanicClientThread(r);
+        pEndpoint->SetTransferInfo(pTfr);
+        if (pEndpoint->iDmaBuffers->IsReaderEmpty())
+            {
+            pEndpoint->SetClientReadPending(ETrue);
+            }
+        else
+            {
+            if (pTfr->iTransferType == ETransferTypeReadPacket)
+                {
+                __KTRACE_OPT(KUSB, Kern::Printf("DoRequest Read packet: data available complete"));
+                r = pEndpoint->CopyToClient(iClient,iClientAsynchNotify[aEndpointNum]->iClientBuffer);
+                aNeedsCompletion = ETrue;
+                break;
+                }
+            else if (pTfr->iTransferType == ETransferTypeReadData)
+                {
+                if (pTfr->iTransferSize <= pEndpoint->RxBytesAvailable())
+                    {
+                    __KTRACE_OPT(KUSB, Kern::Printf("DoRequest Read data: data available complete"));
+                    r = pEndpoint->CopyToClient(iClient,iClientAsynchNotify[aEndpointNum]->iClientBuffer);
+                    aNeedsCompletion = ETrue;
+                    break;
+                    }
+                else
+                    {
+                    pEndpoint->SetClientReadPending(ETrue);
+                    }
+                }
+            else if (pTfr->iTransferType == ETransferTypeReadOneOrMore)
+                {
+                if (pEndpoint->RxBytesAvailable() > 0)
+                    {
+                    __KTRACE_OPT(KUSB, Kern::Printf("DoRequest Read data: data available complete"));
+                    r = pEndpoint->CopyToClient(iClient,iClientAsynchNotify[aEndpointNum]->iClientBuffer);
+                    aNeedsCompletion = ETrue;
+                    break;
+                    }
+                else
+                    {
+                    pEndpoint->SetClientReadPending(ETrue);
+                    }
+                }
+            else if (pTfr->iTransferType == ETransferTypeReadUntilShort)
+                {
+                TInt nRx = pEndpoint->RxBytesAvailable();
+                TInt maxPacketSize = pEndpoint->EndpointInfo()->iSize;
+                if( (pTfr->iTransferSize <= nRx) ||
+                    (nRx < maxPacketSize) ||
+                    pEndpoint->iDmaBuffers->ShortPacketExists())
+                    {
+                    __KTRACE_OPT(KUSB, Kern::Printf("DoRequest Read data: data available complete"));
+                    r = pEndpoint->CopyToClient(iClient,iClientAsynchNotify[aEndpointNum]->iClientBuffer);
+                    aNeedsCompletion = ETrue;
+                    }
+                else
+                    {
+                    pEndpoint->SetClientReadPending(ETrue);
+                    }
+                }
+            }
+        r = pEndpoint->TryToStartRead(EFalse);
+        if (r != KErrNone)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("DoRequest Read: couldn't start read"));
+            r = KErrNone;                                    // Reader full isn't a userside error;
+            }
+        break;
+        }
+
+    case ETransferTypeWrite:
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("DoRequest Write 1"));
+        if (pEndpointInfo->iDir != UsbShai::KUsbEpDirIn &&
+            pEndpointInfo->iDir != UsbShai::KUsbEpDirBidirect)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: DoRequest Write: wrong direction complete"));
+            r = KErrUsbEpBadDirection;
+            break;
+            }
+        __KTRACE_OPT(KUSB, Kern::Printf("DoRequest Write 2"));
+
+
+        TInt desLength=iClientAsynchNotify[aEndpointNum]->iClientBuffer->Length();
+        
+        if (desLength < pTfr->iTransferSize)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: DoRequest Write: user buffer too short"));
+            r = KErrUsbTransferSize;
+            break;
+            }
+
+        __KTRACE_OPT(KUSB, Kern::Printf("DoRequest Write 3 length=%d maxlength=%d",
+                                        pTfr->iTransferSize, desLength));
+        // Zero length writes are acceptable
+        pEndpoint->SetClientWritePending(ETrue);
+        r = pEndpoint->TryToStartWrite(pTfr);
+        if (r != KErrNone)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: DoRequest Write: couldn't start write"));
+            pEndpoint->SetClientWritePending(EFalse);
+            }
+        break;
+        }
+
+    default:
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: DoTransferAsyncReq: pTfr->iTransferType = %d not supported",
+                                          pTfr->iTransferType));
+        r = KErrNotSupported;
+        break;
+        }
+ exit:
+    aNeedsCompletion = aNeedsCompletion || (r != KErrNone);
+    return r;
+    }
+
+
+//
+// Cancel an outstanding request - overriding pure virtual
+//
+TInt DLddUsbcChannel::DoCancel(TInt aReqNo)
+    {
+    TInt r = KErrNone;
+    __KTRACE_OPT(KUSB, Kern::Printf("DoCancel: 0x%x", aReqNo));
+    if (aReqNo <= iNumberOfEndpoints)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("DoCancel endpoint: 0x%x", aReqNo));
+        iEndpoint[aReqNo]->CancelTransfer(iClient,iClientAsynchNotify[aReqNo]->iClientBuffer);
+        }
+    else if (aReqNo == RDevUsbcClient::ERequestAlternateDeviceStatusNotify)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("DoCancel: ERequestAlternateDeviceStatusNotify 0x%x", aReqNo));
+        iDeviceStatusNeeded = EFalse;
+        iStatusFifo->FlushQueue();
+        if (iStatusChangePtr)
+            {
+            iStatusChangeReq->Data()=iController->GetDeviceStatus();
+            iStatusChangePtr = NULL;
+
+            if (iStatusChangeReq->IsReady())
+                {
+                iRequestStatus[aReqNo] = NULL;
+                Kern::QueueRequestComplete(iClient, iStatusChangeReq, KErrCancel);
+                }
+                return KErrNone;
+            }
+        }
+    else if (aReqNo == RDevUsbcClient::ERequestReEnumerate)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("DoCancel ERequestReEnumerate: 0x%x", aReqNo));
+        }
+    else if (aReqNo == RDevUsbcClient::ERequestEndpointStatusNotify)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("DoCancel ERequestEndpointStatusNotify: 0x%x", aReqNo));
+        CancelNotifyEndpointStatus();
+        if (iEndpointStatusChangeReq->IsReady())
+            {
+            iRequestStatus[aReqNo] = NULL;
+            Kern::QueueRequestComplete(iClient, iEndpointStatusChangeReq, KErrCancel);
+            }
+        return KErrNone;
+        }
+    else if (aReqNo == RDevUsbcClient::ERequestOtgFeaturesNotify)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("DoCancel ERequestOtgFeaturesNotify: 0x%x", aReqNo));
+        CancelNotifyOtgFeatures();
+        if (iOtgFeatureChangeReq->IsReady())
+            {
+            iRequestStatus[aReqNo] = NULL;
+            Kern::QueueRequestComplete(iClient, iOtgFeatureChangeReq, KErrCancel);
+            }
+        }
+    else
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("DoCancel Unknown! 0x%x", aReqNo));
+        }
+
+        if (r == KErrNone)
+            r = KErrCancel;
+
+        CompleteBufferRequest(iClient, aReqNo, r);
+    return r;
+    }
+
+
+void DLddUsbcChannel::CancelNotifyEndpointStatus()
+    {
+    if (iEndpointStatusChangePtr)
+        {
+        TUint epBitmap = 0;
+        for (TInt i = 0; i <= iNumberOfEndpoints; i++)
+            {
+            TInt v = iController->GetEndpointStatus(this, iEndpoint[i]->RealEpNumber());
+            TUint b;
+            (v == EEndpointStateStalled) ? b = 1 : b = 0;
+            epBitmap |= b << i;
+            }
+        iEndpointStatusChangeReq->Data()=epBitmap;
+        iEndpointStatusChangePtr = NULL;
+        }
+    }
+
+
+void DLddUsbcChannel::CancelNotifyOtgFeatures()
+    {
+    if (iOtgFeatureChangePtr)
+        {
+        TUint8 features;
+        iController->GetCurrentOtgFeatures(features);
+     iOtgFeatureChangeReq->Data()=features;
+        iOtgFeatureChangePtr = NULL;
+        }
+    }
+
+TInt DLddUsbcChannel::PinMemory(TDesC8 *aDes, TVirtualPinObject *aPinObj)
+    {
+    TInt r = KErrNone;
+    TInt  len,mlen;
+    
+    const TUint8*p = Kern::KUDesInfo(*aDes, len,mlen);
+    r=Kern::PinVirtualMemory(aPinObj, (TLinAddr) p, len);
+    return r;
+    }
+
+//Called in Client thread context
+TInt DLddUsbcChannel::SendControl(TMessageBase* aMsg)
+    {
+    TThreadMessage& m=*(TThreadMessage*)aMsg;
+    const TInt fn=m.iValue;
+    TAny *const a1=m.Ptr0();
+    TAny *const a2=m.Ptr1();
+    TInt  kern_param;
+    TEndpointDescriptorInfo epi;
+    TUsbcIfcInfo ifc;
+    TCSDescriptorInfo desInfo;
+    TInt r = KErrNone;
+
+    switch (fn)
+        {
+        
+    case RDevUsbcClient::EControlDeviceStatus:
+    case RDevUsbcClient::EControlGetAlternateSetting:
+        m.iArg[0] = &kern_param;              // update message to point to kernel-side buffer
+        break;
+
+    case RDevUsbcClient::EControlQueryReceiveBuffer:
+    case RDevUsbcClient::EControlEndpointStatus:
+        m.iArg[1] = &kern_param;              // update message to point to kernel-side buffer
+        break;
+
+    case RDevUsbcClient::EControlEndpointCaps:
+    case RDevUsbcClient::EControlDeviceCaps:
+    case RDevUsbcClient::EControlGetDeviceDescriptor:
+    case RDevUsbcClient::EControlSetDeviceDescriptor:
+    case RDevUsbcClient::EControlGetDeviceDescriptorSize:
+    case RDevUsbcClient::EControlGetConfigurationDescriptor:
+    case RDevUsbcClient::EControlGetConfigurationDescriptorSize:
+    case RDevUsbcClient::EControlGetDeviceQualifierDescriptor:
+    case RDevUsbcClient::EControlSetDeviceQualifierDescriptor:
+    case RDevUsbcClient::EControlGetOtherSpeedConfigurationDescriptor:
+    case RDevUsbcClient::EControlSetOtherSpeedConfigurationDescriptor:
+    case RDevUsbcClient::EControlGetStringDescriptorLangId:
+    case RDevUsbcClient::EControlGetManufacturerStringDescriptor:
+    case RDevUsbcClient::EControlSetManufacturerStringDescriptor:
+    case RDevUsbcClient::EControlGetProductStringDescriptor:
+    case RDevUsbcClient::EControlSetProductStringDescriptor:
+    case RDevUsbcClient::EControlGetSerialNumberStringDescriptor:    
+    case RDevUsbcClient::EControlSetSerialNumberStringDescriptor:
+    case RDevUsbcClient::EControlGetConfigurationStringDescriptor:
+    case RDevUsbcClient::EControlSetConfigurationStringDescriptor:
+    case RDevUsbcClient::EControlSetOtgDescriptor:
+    case RDevUsbcClient::EControlGetOtgDescriptor:
+    case RDevUsbcClient::EControlGetOtgFeatures:
+        r=PinMemory((TDesC8 *) a1, iPinObj1);
+        if(r!=KErrNone)
+            {
+            PanicClientThread(r);
+            return r;
+            }
+        break;
+
+    case RDevUsbcClient::EControlGetInterfaceDescriptor:
+    case RDevUsbcClient::EControlGetInterfaceDescriptorSize:
+    case RDevUsbcClient::EControlSetInterfaceDescriptor:
+    case RDevUsbcClient::EControlGetCSInterfaceDescriptor:
+    case RDevUsbcClient::EControlGetCSInterfaceDescriptorSize:
+    case RDevUsbcClient::EControlGetStringDescriptor:
+    case RDevUsbcClient::EControlSetStringDescriptor:
+        r=PinMemory((TDesC8 *) a2, iPinObj1);
+        if(r!=KErrNone)
+            {
+            PanicClientThread(r);
+            return r;
+            }
+        break;
+
+    case RDevUsbcClient::EControlGetEndpointDescriptor:
+    case RDevUsbcClient::EControlGetEndpointDescriptorSize:
+    case RDevUsbcClient::EControlSetEndpointDescriptor:
+    case RDevUsbcClient::EControlGetCSEndpointDescriptor:
+    case RDevUsbcClient::EControlGetCSEndpointDescriptorSize:
+        if(a1!=NULL)
+            {
+            r=Kern::PinVirtualMemory(iPinObj1, (TLinAddr)a1, sizeof(epi));
+            if(r!=KErrNone)
+                {
+                PanicClientThread(r);
+                return r;
+                }
+            kumemget(&epi, a1, sizeof(epi));
+            r=PinMemory((TDesC8 *) epi.iArg, iPinObj2);
+            if(r!=KErrNone)
+                {
+                Kern::UnpinVirtualMemory(iPinObj1);
+                PanicClientThread(r);
+                return r;
+                }
+            }
+        break;
+
+    case RDevUsbcClient::EControlSetInterface:
+        if(a2!=NULL)
+            {
+            r=Kern::PinVirtualMemory(iPinObj1, (TLinAddr)a2, sizeof(ifc));
+            if(r!=KErrNone)
+                {
+                PanicClientThread(r);
+                return r;
+                }    
+            kumemget(&ifc, a2, sizeof(ifc));                
+            r=PinMemory((TDesC8 *) ifc.iInterfaceData, iPinObj2);
+            if(r!=KErrNone)
+                {
+                Kern::UnpinVirtualMemory(iPinObj1);
+                PanicClientThread(r);
+                return r;
+                }
+            }
+        break;
+
+    case RDevUsbcClient::EControlSetCSInterfaceDescriptor:
+    case RDevUsbcClient::EControlSetCSEndpointDescriptor:
+        if(a1!=NULL)
+            {
+            r=Kern::PinVirtualMemory(iPinObj1, (TLinAddr)a1, sizeof(desInfo));
+            if(r!=KErrNone)
+                {
+                PanicClientThread(r);
+                return r;
+                }
+            kumemget(&desInfo, a1, sizeof(desInfo));
+            r=PinMemory((TDesC8 *) desInfo.iArg, iPinObj2);
+            if(r!=KErrNone)
+                {
+                Kern::UnpinVirtualMemory(iPinObj1);
+                PanicClientThread(r);
+                return r;
+                }
+            }
+        break;
+    }
+
+
+    //Send Message and wait for synchronous complete    
+    r = DLogicalChannel::SendMsg(aMsg);
+    
+    
+    
+    switch (fn)
+        {
+    case RDevUsbcClient::EControlDeviceStatus:
+    case RDevUsbcClient::EControlGetAlternateSetting:
+        umemput32(a1, &kern_param, sizeof(kern_param));
+        break;
+
+    case RDevUsbcClient::EControlQueryReceiveBuffer:
+    case RDevUsbcClient::EControlEndpointStatus:
+        umemput32(a2, &kern_param, sizeof(kern_param));
+        break;
+
+    case RDevUsbcClient::EControlDeviceCaps:
+    case RDevUsbcClient::EControlEndpointCaps:
+    case RDevUsbcClient::EControlGetDeviceDescriptor:
+    case RDevUsbcClient::EControlSetDeviceDescriptor:
+    case RDevUsbcClient::EControlGetDeviceDescriptorSize:
+    case RDevUsbcClient::EControlGetConfigurationDescriptor:
+    case RDevUsbcClient::EControlGetConfigurationDescriptorSize:
+    case RDevUsbcClient::EControlGetDeviceQualifierDescriptor:
+    case RDevUsbcClient::EControlSetDeviceQualifierDescriptor:
+    case RDevUsbcClient::EControlGetOtherSpeedConfigurationDescriptor:
+    case RDevUsbcClient::EControlSetOtherSpeedConfigurationDescriptor:
+    case RDevUsbcClient::EControlGetStringDescriptorLangId:
+    case RDevUsbcClient::EControlGetManufacturerStringDescriptor:
+    case RDevUsbcClient::EControlSetManufacturerStringDescriptor:
+    case RDevUsbcClient::EControlGetProductStringDescriptor:
+    case RDevUsbcClient::EControlSetProductStringDescriptor:
+    case RDevUsbcClient::EControlGetSerialNumberStringDescriptor:    
+    case RDevUsbcClient::EControlSetSerialNumberStringDescriptor:
+    case RDevUsbcClient::EControlGetConfigurationStringDescriptor:
+    case RDevUsbcClient::EControlSetConfigurationStringDescriptor:
+    case RDevUsbcClient::EControlSetOtgDescriptor:
+    case RDevUsbcClient::EControlGetOtgDescriptor:
+    case RDevUsbcClient::EControlGetOtgFeatures:
+        if(a1!=NULL)
+            {
+            Kern::UnpinVirtualMemory(iPinObj1);
+            }
+        break;
+
+    case RDevUsbcClient::EControlGetInterfaceDescriptor:
+    case RDevUsbcClient::EControlGetInterfaceDescriptorSize:
+    case RDevUsbcClient::EControlSetInterfaceDescriptor:
+    case RDevUsbcClient::EControlGetCSInterfaceDescriptor:
+    case RDevUsbcClient::EControlGetCSInterfaceDescriptorSize:
+    case RDevUsbcClient::EControlGetStringDescriptor:
+    case RDevUsbcClient::EControlSetStringDescriptor:
+        if(a2!=NULL)
+            {
+            Kern::UnpinVirtualMemory(iPinObj1);
+            }
+        break;
+    
+    case RDevUsbcClient::EControlGetEndpointDescriptor:
+    case RDevUsbcClient::EControlGetEndpointDescriptorSize:
+    case RDevUsbcClient::EControlSetEndpointDescriptor:
+    case RDevUsbcClient::EControlGetCSEndpointDescriptor:
+    case RDevUsbcClient::EControlGetCSEndpointDescriptorSize:
+    case RDevUsbcClient::EControlSetCSInterfaceDescriptor:
+    case RDevUsbcClient::EControlSetCSEndpointDescriptor:
+        if(a1!=NULL)
+            {
+            Kern::UnpinVirtualMemory(iPinObj1);
+            Kern::UnpinVirtualMemory(iPinObj2);
+            }
+        break;
+
+    case RDevUsbcClient::EControlSetInterface:
+        if(a2!=NULL)
+            {
+            Kern::UnpinVirtualMemory(iPinObj1);
+            Kern::UnpinVirtualMemory(iPinObj2);
+            }
+        break;
+        }
+
+    return r;
+    }
+
+
+TInt DLddUsbcChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DoControl: %d", aFunction));
+
+    TInt r = KErrNone;
+    TInt ep;
+    TUsbcEndpoint* pEndpoint;
+    TPtrC8 pZeroDesc(NULL, 0);
+    TEndpointDescriptorInfo epInfo;
+    TUsbcIfcInfo ifcInfo;
+    TCSDescriptorInfo desInfo;
+    TUsbcEndpointResource epRes;
+    TInt bandwidthPriority;
+
+    switch (aFunction)
+        {
+    case RDevUsbcClient::EControlEndpointZeroRequestError:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointZeroRequestError"));
+        r = KErrNone;
+        if (iOwnsDeviceControl || (iValidInterface && iDeviceState == UsbShai::EUsbPeripheralStateConfigured))
+            {
+            iController->Ep0Stall(this);
+            }
+        else
+            {
+            if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured)
+                r = KErrUsbDeviceNotConfigured;
+            else
+                r = KErrUsbInterfaceNotReady;
+            }
+        break;
+
+    case RDevUsbcClient::EControlGetAlternateSetting:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetAlternateSetting"));
+        if (iValidInterface && iDeviceState == UsbShai::EUsbPeripheralStateConfigured)
+            {
+            r = iController->GetInterfaceNumber(this, *(TInt*)a1);
+            }
+        else
+            {
+            if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured)
+                r = KErrUsbDeviceNotConfigured;
+            else
+                r = KErrUsbInterfaceNotReady;
+            }
+        break;
+
+    case RDevUsbcClient::EControlDeviceStatus:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceStatus"));
+        *(TInt*)a1 = iController->GetDeviceStatus();
+        break;
+
+    case RDevUsbcClient::EControlEndpointStatus:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointStatus"));
+        if (iValidInterface && ValidEndpoint((TInt) a1))
+            {
+            pEndpoint = iEndpoint[(TInt)a1];
+            if (pEndpoint == NULL)
+                r = KErrNotSupported;
+            else
+                {
+                *(TInt*)a2 = iController->GetEndpointStatus(this, iEndpoint[(TInt)a1]->RealEpNumber());
+                }
+            }
+        else
+            {
+            if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured)
+                r = KErrUsbDeviceNotConfigured;
+            else
+                r = KErrUsbInterfaceNotReady;
+            }
+        break;
+
+    case RDevUsbcClient::EControlQueryReceiveBuffer:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlQueryReceiveBuffer"));
+        if (iValidInterface && ValidEndpoint((TInt) a1))
+            {
+            pEndpoint=iEndpoint[(TInt) a1];
+            if (pEndpoint == NULL)
+                r = KErrNotSupported;
+            else if (pEndpoint->EndpointInfo()->iDir != UsbShai::KUsbEpDirIn)
+                {
+                __KTRACE_OPT(KUSB, Kern::Printf("  bytes = %d", pEndpoint->RxBytesAvailable()));
+                *(TInt*)a2 = pEndpoint->RxBytesAvailable();
+                }
+            }
+        else
+            {
+            if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured)
+                r = KErrUsbDeviceNotConfigured;
+            else
+                r = KErrUsbInterfaceNotReady;
+            }
+        break;
+
+    case RDevUsbcClient::EControlEndpointCaps:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointCaps"));
+        r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
+        if (r != KErrNone)
+            PanicClientThread(r);
+        iController->EndpointCaps(this, *((TDes8*) a1));
+        break;
+
+    case RDevUsbcClient::EControlDeviceCaps:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceCaps"));
+        r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
+        if (r != KErrNone)
+            PanicClientThread(r);
+        iController->DeviceCaps(this, *((TDes8*) a1));
+        break;
+
+    case RDevUsbcClient::EControlSendEp0StatusPacket:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSendEp0StatusPacket"));
+        iController->SendEp0StatusPacket(this);
+        break;
+
+    case RDevUsbcClient::EControlHaltEndpoint:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlHaltEndpoint"));
+        if (iValidInterface && ValidEndpoint((TInt) a1))
+            {
+            r = iController->HaltEndpoint(this, iEndpoint[(TInt)a1]->RealEpNumber());
+            }
+        else
+            {
+            if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured)
+                r = KErrUsbDeviceNotConfigured;
+            else
+                r = KErrUsbInterfaceNotReady;
+            }
+        break;
+
+    case RDevUsbcClient::EControlClearHaltEndpoint:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlClearHaltEndpoint"));
+        if (iValidInterface && ValidEndpoint((TInt) a1))
+            {
+            r = iController->ClearHaltEndpoint(this, iEndpoint[(TInt)a1]->RealEpNumber());
+            }
+        else
+            {
+            if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured)
+                r = KErrUsbDeviceNotConfigured;
+            else
+                r = KErrUsbInterfaceNotReady;
+            }
+        break;
+
+    case RDevUsbcClient::EControlDumpRegisters:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlDumpRegisters"));
+        iController->DumpRegisters();
+        break;
+
+    case RDevUsbcClient::EControlReleaseDeviceControl:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlReleaseDeviceControl"));
+        iController->ReleaseDeviceControl(this);
+        iOwnsDeviceControl = EFalse;
+        break;
+
+    case RDevUsbcClient::EControlEndpointZeroMaxPacketSizes:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointZeroMaxPacketSizes"));
+        r = iController->EndpointZeroMaxPacketSizes();
+        break;
+
+    case RDevUsbcClient::EControlSetEndpointZeroMaxPacketSize:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetEndpointZeroMaxPacketSize"));
+        r = iController->SetEndpointZeroMaxPacketSize(reinterpret_cast<TInt>(a1));
+        break;
+
+    case RDevUsbcClient::EControlGetEndpointZeroMaxPacketSize:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetEndpointZeroMaxPacketSize"));
+        r = iController->Ep0PacketSize();
+        break;
+
+    case RDevUsbcClient::EControlGetDeviceDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetDeviceDescriptor"));
+        r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
+        if (r != KErrNone)
+            PanicClientThread(r);
+        r = iController->GetDeviceDescriptor(iClient, *((TDes8*) a1));
+        break;
+
+    case RDevUsbcClient::EControlSetDeviceDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceDescriptor"));
+        if (a1 != NULL)
+            r = iController->SetDeviceDescriptor(iClient, *((TDes8*) a1));
+        else
+            r = KErrArgument;
+        break;
+
+    case RDevUsbcClient::EControlGetDeviceDescriptorSize:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetDeviceDescriptorSize"));
+        if (a1 != NULL)
+            r = iController->GetDeviceDescriptorSize(iClient, *((TDes8*) a1));
+        else
+            r = KErrArgument;
+        break;
+
+    case RDevUsbcClient::EControlGetConfigurationDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetConfigurationDescriptor"));
+        r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0 , 0, iClient);
+        if (r != KErrNone)
+            PanicClientThread(r);
+        r = iController->GetConfigurationDescriptor(iClient, *((TDes8*) a1));
+        break;
+
+    case RDevUsbcClient::EControlGetConfigurationDescriptorSize:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetConfigurationDescriptorSize"));
+        if (a1 != NULL)
+            {
+            r = iController->GetConfigurationDescriptorSize(iClient, *((TDes8*) a1));
+            }
+        else
+            r = KErrArgument;
+        break;
+
+    case RDevUsbcClient::EControlSetConfigurationDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetConfigurationDescriptor"));
+        r = iController->SetConfigurationDescriptor(iClient, *((TDes8*) a1));
+        break;
+
+    case RDevUsbcClient::EControlGetInterfaceDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetInterfaceDescriptor"));
+        r = iController->GetInterfaceDescriptor(iClient, this, (TInt) a1, *((TDes8*) a2));
+        break;
+
+    case RDevUsbcClient::EControlGetInterfaceDescriptorSize:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetInterfaceDescriptorSize"));
+        r = iController->GetInterfaceDescriptorSize(iClient, this, (TInt) a1, *(TDes8*) a2);
+        break;
+
+    case RDevUsbcClient::EControlSetInterfaceDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetInterfaceDescriptor"));
+        r = iController->SetInterfaceDescriptor(iClient, this, (TInt) a1, *((TDes8*) a2));
+        break;
+
+    case RDevUsbcClient::EControlGetEndpointDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetEndpointDescriptor"));
+        r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
+        if (r != KErrNone)
+            PanicClientThread(r);
+        ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
+        r = iController->GetEndpointDescriptor(iClient, this, epInfo.iSetting,
+                                               ep, *(TDes8*) epInfo.iArg);
+        break;
+
+    case RDevUsbcClient::EControlGetEndpointDescriptorSize:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetEndpointDescriptorSize"));
+        r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
+        if (r != KErrNone)
+            PanicClientThread(r);
+        ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
+        r = iController->GetEndpointDescriptorSize(iClient, this, epInfo.iSetting,
+                                                   ep, *(TDes8*) epInfo.iArg);
+        break;
+
+    case RDevUsbcClient::EControlSetEndpointDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetEndpointDescriptor"));
+        r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
+        if (r != KErrNone)
+            PanicClientThread(r);
+        ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
+        r = iController->SetEndpointDescriptor(iClient, this, epInfo.iSetting,
+                                               ep, *(TDes8*)epInfo.iArg);
+        break;
+
+    case RDevUsbcClient::EControlGetDeviceQualifierDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetDeviceQualifierDescriptor"));
+        r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
+        if (r != KErrNone)
+            PanicClientThread(r);
+        r = iController->GetDeviceQualifierDescriptor(iClient, *((TDes8*) a1));
+        break;
+
+    case RDevUsbcClient::EControlSetDeviceQualifierDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceQualifierDescriptor"));
+        if (a1 != NULL)
+            r = iController->SetDeviceQualifierDescriptor(iClient, *((TDes8*) a1));
+        else
+            r = KErrArgument;
+        break;
+
+    case RDevUsbcClient::EControlGetOtherSpeedConfigurationDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetOtherSpeedConfigurationDescriptor"));
+        r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0 , 0, iClient);
+        if (r != KErrNone)
+            PanicClientThread(r);
+        r = iController->GetOtherSpeedConfigurationDescriptor(iClient, *((TDes8*) a1));
+        break;
+
+    case RDevUsbcClient::EControlSetOtherSpeedConfigurationDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetOtherSpeedConfigurationDescriptor"));
+        r = iController->SetOtherSpeedConfigurationDescriptor(iClient, *((TDes8*) a1));
+        break;
+
+
+    case RDevUsbcClient::EControlGetCSInterfaceDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSInterfaceDescriptor"));
+        r = iController->GetCSInterfaceDescriptorBlock(iClient, this, (TInt) a1, *((TDes8*) a2));
+        break;
+
+    case RDevUsbcClient::EControlGetCSInterfaceDescriptorSize:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSInterfaceDescriptorSize"));
+        r = iController->GetCSInterfaceDescriptorBlockSize(iClient, this, (TInt) a1, *(TDes8*) a2);
+        break;
+
+    case RDevUsbcClient::EControlGetCSEndpointDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSEndpointDescriptor"));
+        r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
+        if (r != KErrNone)
+            PanicClientThread(r);
+        ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
+        r = iController->GetCSEndpointDescriptorBlock(iClient, this, epInfo.iSetting,
+                                                      ep, *(TDes8*) epInfo.iArg);
+        break;
+
+    case RDevUsbcClient::EControlGetCSEndpointDescriptorSize:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSEndpointDescriptorSize"));
+        r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
+        if (r != KErrNone)
+            PanicClientThread(r);
+        ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
+        r = iController->GetCSEndpointDescriptorBlockSize(iClient, this, epInfo.iSetting,
+                                                          ep, *(TDes8*) epInfo.iArg);
+        break;
+
+    case RDevUsbcClient::EControlSignalRemoteWakeup:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSignalRemoteWakeup"));
+        r = iController->SignalRemoteWakeup();
+        break;
+
+    case RDevUsbcClient::EControlDeviceDisconnectFromHost:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceDisconnectFromHost"));
+        r = iController->UsbDisconnect();
+        break;
+
+    case RDevUsbcClient::EControlDeviceConnectToHost:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceConnectToHost"));
+        r = iController->UsbConnect();
+        break;
+
+    case RDevUsbcClient::EControlDevicePowerUpUdc:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlDevicePowerUpUdc"));
+        r = iController->PowerUpUdc();
+        break;
+
+    case RDevUsbcClient::EControlSetDeviceControl:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceControl"));
+        r = iController->SetDeviceControl(this);
+        if (r == KErrNone)
+            {
+            iOwnsDeviceControl = ETrue;
+            if (iEndpoint[0] == NULL)
+                {
+                __KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceControl 11"));
+                r = SetupEp0();
+                if (r != KErrNone)
+                    {
+                    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: SetupEp0() failed"));
+                    iController->ReleaseDeviceControl(this);
+                    DestroyEp0();
+                    iOwnsDeviceControl = EFalse;
+                    }
+                iEndpoint[0]->TryToStartRead(EFalse);
+                }
+            }
+        else
+            r = KErrInUse;
+        break;
+
+    case RDevUsbcClient::EControlCurrentlyUsingHighSpeed:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlCurrentlyUsingHighSpeed"));
+        r = iController->CurrentlyUsingHighSpeed();
+        break;
+
+    case RDevUsbcClient::EControlSetInterface:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetInterface"));
+        r = Kern::ThreadRawRead(iClient, a2, &ifcInfo, sizeof(ifcInfo));
+        if (r != KErrNone)
+            PanicClientThread(r);
+        if (iValidInterface && (iDeviceState == UsbShai::EUsbPeripheralStateConfigured))
+            {
+            r = KErrGeneral;
+            }
+        else
+            {
+            bandwidthPriority = ifcInfo.iBandwidthPriority;
+            if ((bandwidthPriority & 0xffffff00) ||
+                ((bandwidthPriority & 0x0f) >= KUsbcDmaBufMaxPriorities) ||
+                (((bandwidthPriority >> 4) & 0x0f) >= KUsbcDmaBufMaxPriorities))
+                {
+                r = KErrArgument;
+                }
+            else
+                {
+                r = SetInterface((TInt) a1, &ifcInfo);
+                }
+            }
+            
+        break;
+
+    case RDevUsbcClient::EControlReleaseInterface:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlReleaseInterface"));
+        r = iController->ReleaseInterface(this, (TInt) a1);
+        if (r == KErrNone)
+            {
+            DestroyInterface((TUint) a1);
+            }
+        else
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error in PIL: LDD interface won't be released."));
+            }
+        break;
+
+    case RDevUsbcClient::EControlSetCSInterfaceDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetCSInterfaceDescriptor"));
+        r = Kern::ThreadRawRead(iClient, a1, &desInfo, sizeof(desInfo));
+        if (r != KErrNone)
+            PanicClientThread(r);
+        r = iController->SetCSInterfaceDescriptorBlock(iClient, this, desInfo.iSetting,
+                                                       *reinterpret_cast<const TDes8*>(desInfo.iArg),
+                                                       desInfo.iSize);
+        break;
+
+    case RDevUsbcClient::EControlSetCSEndpointDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetCSEndpointDescriptor"));
+        r = Kern::ThreadRawRead(iClient, a1, &desInfo, sizeof(desInfo));
+        if (r != KErrNone)
+            PanicClientThread(r);
+        ep = EpFromAlternateSetting(desInfo.iSetting, desInfo.iEndpoint);
+        r = iController->SetCSEndpointDescriptorBlock(iClient, this, desInfo.iSetting, ep,
+                                                      *reinterpret_cast<const TDes8*>(desInfo.iArg),
+                                                      desInfo.iSize);
+        break;
+
+    case RDevUsbcClient::EControlGetStringDescriptorLangId:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetStringDescriptorLangId"));
+        r = iController->GetStringDescriptorLangId(iClient, *((TDes8*) a1));
+        break;
+
+    case RDevUsbcClient::EControlSetStringDescriptorLangId:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetStringDescriptorLangId"));
+        r = iController->SetStringDescriptorLangId(reinterpret_cast<TUint>(a1));
+        break;
+
+    case RDevUsbcClient::EControlGetManufacturerStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetManufacturerStringDescriptor"));
+        r = iController->GetManufacturerStringDescriptor(iClient, *((TPtr8*) a1));
+        break;
+
+    case RDevUsbcClient::EControlSetManufacturerStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetManufacturerStringDescriptor"));
+        r = iController->SetManufacturerStringDescriptor(iClient, *((TPtr8*) a1));
+        break;
+
+    case RDevUsbcClient::EControlRemoveManufacturerStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveManufacturerStringDescriptor"));
+        r = iController->RemoveManufacturerStringDescriptor();
+        break;
+
+    case RDevUsbcClient::EControlGetProductStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetProductStringDescriptor"));
+        r = iController->GetProductStringDescriptor(iClient, *((TPtr8*) a1));
+        break;
+
+    case RDevUsbcClient::EControlSetProductStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetProductStringDescriptor"));
+        r = iController->SetProductStringDescriptor(iClient, *((TPtr8*) a1));
+        break;
+
+    case RDevUsbcClient::EControlRemoveProductStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveProductStringDescriptor"));
+        r = iController->RemoveProductStringDescriptor();
+        break;
+
+    case RDevUsbcClient::EControlGetSerialNumberStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetSerialNumberStringDescriptor"));
+        r = iController->GetSerialNumberStringDescriptor(iClient, *((TPtr8*) a1));
+        break;
+
+    case RDevUsbcClient::EControlSetSerialNumberStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetSerialNumberStringDescriptor"));
+        r = iController->SetSerialNumberStringDescriptor(iClient, *((TPtr8*) a1));
+        break;
+
+    case RDevUsbcClient::EControlRemoveSerialNumberStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveSerialNumberStringDescriptor"));
+        r = iController->RemoveSerialNumberStringDescriptor();
+        break;
+
+    case RDevUsbcClient::EControlGetConfigurationStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetConfigurationStringDescriptor"));
+        r = iController->GetConfigurationStringDescriptor(iClient, *((TPtr8*) a1));
+        break;
+
+    case RDevUsbcClient::EControlSetConfigurationStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetConfigurationStringDescriptor"));
+        r = iController->SetConfigurationStringDescriptor(iClient, *((TPtr8*) a1));
+        break;
+
+    case RDevUsbcClient::EControlRemoveConfigurationStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveConfigurationStringDescriptor"));
+        r = iController->RemoveConfigurationStringDescriptor();
+        break;
+
+    case RDevUsbcClient::EControlGetStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetStringDescriptor"));
+        r = iController->GetStringDescriptor(iClient, (TUint8) (TInt) a1, *((TPtr8*) a2));
+        break;
+
+    case RDevUsbcClient::EControlSetStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetStringDescriptor"));
+        r = iController->SetStringDescriptor(iClient, (TUint8) (TInt) a1, *((TPtr8*) a2));
+        break;
+
+    case RDevUsbcClient::EControlRemoveStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveStringDescriptor"));
+        r = iController->RemoveStringDescriptor((TUint8) (TInt) a1);
+        break;
+
+    case RDevUsbcClient::EControlQueryEndpointResourceUse:
+        epRes = (TUsbcEndpointResource)((TInt) a2);
+        if (!ValidEndpoint((TInt)a1))
+            {
+            r = KErrUsbEpNotInInterface;
+            }
+        else
+            {
+            r = iController->QueryEndpointResource(this, iEndpoint[(TInt)a1]->RealEpNumber(), epRes);
+            }
+        break;
+
+    case RDevUsbcClient::EControlSetOtgDescriptor:
+        {
+        r = iController->SetOtgDescriptor(iClient, *((const TDesC8*)a1));
+        }
+        break;
+
+    case RDevUsbcClient::EControlGetOtgDescriptor:
+        {
+        r = iController->GetOtgDescriptor(iClient, *((TDes8*)a1));
+        }
+        break;
+
+    case RDevUsbcClient::EControlGetOtgFeatures:
+        {
+        r = iController->GetOtgFeatures(iClient, *((TDes8*)a1));
+        }
+        break;
+
+    default:
+        __KTRACE_OPT(KUSB, Kern::Printf("Function code not supported"));
+        r = KErrNotSupported;
+        }
+
+    return r;
+    }
+
+
+TInt DLddUsbcChannel::SetInterface(TInt aInterfaceNumber, TUsbcIfcInfo* aInfoBuf)
+    {
+    TUsbcInterfaceInfoBuf ifc_info_buf;
+    TUsbcInterfaceInfoBuf* const ifc_info_buf_ptr = aInfoBuf->iInterfaceData;
+    const TInt srcLen = Kern::ThreadGetDesLength(iClient, ifc_info_buf_ptr);
+    if (srcLen < ifc_info_buf.Length())
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("SetInterface can't copy"));
+        PanicClientThread(EDesOverflow);
+        }
+
+    TInt r = Kern::ThreadDesRead(iClient, ifc_info_buf_ptr, ifc_info_buf, 0, KChunkShiftBy0);
+    if (r != KErrNone)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("SetInterface Copy failed reason=%d", r));
+        PanicClientThread(r);
+        }
+
+    TUsbcEndpointInfo* pEndpointData = ifc_info_buf().iEndpointData;
+
+    // If an alternate interface is being asked for then do nothing,
+    // just pass it down to the Controller.
+    const TInt num_endpoints = ifc_info_buf().iTotalEndpointsUsed;
+    __KTRACE_OPT(KUSB, Kern::Printf("SetInterface num_endpoints=%d", num_endpoints));
+
+    // [The next 4 variables have to be initialized here because of the goto's that follow.]
+    // Both IN and OUT buffers will be fully cached:
+    const TUint32 cacheAttribs = EMapAttrSupRw | EMapAttrCachedMax;
+    const TUint32 bandwidthPriority = aInfoBuf->iBandwidthPriority;
+
+    // Supports ep0+5 endpoints
+    TInt real_ep_numbers[6] = {-1, -1, -1, -1, -1, -1};
+
+    // See if PIL will accept this interface
+    __KTRACE_OPT(KUSB, Kern::Printf("SetInterface Calling controller"));
+    r = iController->SetInterface(this,
+                                  iClient,
+                                  aInterfaceNumber,
+                                  ifc_info_buf().iClass,
+                                  aInfoBuf->iString,
+                                  ifc_info_buf().iTotalEndpointsUsed,
+                                  ifc_info_buf().iEndpointData,
+                                  &real_ep_numbers,
+                                  ifc_info_buf().iFeatureWord);
+
+    __KTRACE_OPT(KUSB, Kern::Printf("SetInterface controller returned %d", r));
+    if (r != KErrNone)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("SetInterface failed reason=%d", r));
+        return r;
+        }
+
+    // [The next variable has to be initialized here because of the goto's that follow.]
+    TUsbcAlternateSettingList* alternateSettingListRec;
+
+    // ep0
+    if (iEndpoint[0] == NULL)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("SetInterface 11"));
+        r = SetupEp0();
+        if (r != KErrNone)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: SetupEp0() failed"));
+            DestroyEp0();
+            goto F1;
+            }
+        }
+
+    alternateSettingListRec = new TUsbcAlternateSettingList;
+    if (!alternateSettingListRec)
+        {
+        r = KErrNoMemory;
+        goto F1;
+        }
+
+    __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcChannel::SetInterface num_endpoints=%d", num_endpoints));
+
+    // other endpoints
+    // calculate the total buffer size
+    for (TInt i = 1; i <= num_endpoints; i++, pEndpointData++)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("SetInterface for ep=%d", i));
+        if (!ValidateEndpoint(pEndpointData))
+            {
+            r = KErrUsbBadEndpoint;
+            goto F2;
+            }
+
+        TUsbcEndpoint* ep = new TUsbcEndpoint(this, iController, pEndpointData, i, bandwidthPriority);
+        alternateSettingListRec->iEndpoint[i] = ep;
+        if (!ep)
+            {
+            r = KErrNoMemory;
+            goto F2;
+            }
+        if (ep->Construct() != KErrNone)
+            {
+            r = KErrNoMemory;
+            goto F2;
+            }
+
+        __KTRACE_OPT(KUSB, Kern::Printf("SetInterface for ep=%d rec=0x%08x ep==0x%08x",
+                                        i, alternateSettingListRec, ep));
+        }
+
+    // buf size of each endpoint
+    TInt bufSizes[KMaxEndpointsPerClient + 1];
+    TInt epNum[KMaxEndpointsPerClient + 1];
+
+    // init
+    for( TInt i=0;i<KMaxEndpointsPerClient+1;i++ )
+        {
+        bufSizes[i] = -1;
+        epNum[i] = i;
+        }
+
+    // Record the actual buf size of each endpoint
+    for( TInt i=1;i<=num_endpoints;i++ )
+        {
+        bufSizes[i] = alternateSettingListRec->iEndpoint[i]->BufferSize();
+        }
+
+    __KTRACE_OPT(KUSB, Kern::Printf("Sort the endpoints:"));
+
+    // sort the endpoint number by the bufsize decreasely
+    for( TInt i=1;i<num_endpoints;i++ )
+        {
+        TInt epMaxBuf = i;
+        for(TInt k=i+1;k<=num_endpoints;k++ )
+            {
+            if( bufSizes[epMaxBuf]<bufSizes[k])
+                {
+                epMaxBuf = k;
+                }
+            }
+        TInt temp = bufSizes[i];
+        bufSizes[i] = bufSizes[epMaxBuf];
+        bufSizes[epMaxBuf] = temp;
+
+        temp = epNum[i];
+        epNum[i] = epNum[epMaxBuf];
+        epNum[epMaxBuf] = temp;
+
+        alternateSettingListRec->iEpNumDeOrderedByBufSize[i] = epNum[i];
+
+        __KTRACE_OPT(KUSB, Kern::Printf(" %d:%d", epNum[i], bufSizes[i]));
+        }
+    alternateSettingListRec->iEpNumDeOrderedByBufSize[num_endpoints] = epNum[num_endpoints];
+    __KTRACE_OPT(KUSB, Kern::Printf(" %d:%d", epNum[num_endpoints], bufSizes[num_endpoints]));
+    __KTRACE_OPT(KUSB, Kern::Printf("\n"));
+
+    // chain in this alternate setting
+    alternateSettingListRec->iNext = iAlternateSettingList;
+    iAlternateSettingList = alternateSettingListRec;
+    alternateSettingListRec->iSetting = aInterfaceNumber;
+    alternateSettingListRec->iNumberOfEndpoints = num_endpoints;
+
+    // Record the 'real' endpoint number used by the PDD in both the Ep and
+    // the Req callback:
+    for (TInt i = 1; i <= num_endpoints; i++)
+        {
+        alternateSettingListRec->iEndpoint[i]->SetRealEpNumber(real_ep_numbers[i]);
+        }
+
+    r = SetupInterfaceMemory(iHwChunks, cacheAttribs );
+    if( r==KErrNone )
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("SetInterface ready to exit"));
+    
+        if (aInterfaceNumber == 0)
+            {
+            // make sure we're ready to go with the main interface
+            iValidInterface = ETrue;
+            __KTRACE_OPT(KUSB, Kern::Printf("SetInterface SelectAlternateSetting"));
+            SelectAlternateSetting(0);
+            }
+        return KErrNone;
+        }
+    else
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("Destroying all interfaces"));
+        DestroyAllInterfaces();
+        DestroyEp0();
+        return r;
+        }
+
+ F2:
+    delete alternateSettingListRec;
+    //Fall through
+ 
+ F1:
+#if _DEBUG
+    TInt r1 = iController->ReleaseInterface(this, aInterfaceNumber);
+    __KTRACE_OPT(KUSB, Kern::Printf("Release Interface controller returned %d", r1));
+#else
+    (void)    iController->ReleaseInterface(this, aInterfaceNumber);
+#endif
+    return r;
+    }
+
+// realloc the memory, and set the previous interfaces 
+TInt DLddUsbcChannel::SetupInterfaceMemory(RArray<DPlatChunkHw*> &aHwChunks, 
+        TUint32 aCacheAttribs )
+    {
+    TUsbcAlternateSettingList* asRec = iAlternateSettingList;
+
+    // if buffers has been changed
+    TBool chunkChanged = EFalse;
+    TInt numOfEp = asRec->iNumberOfEndpoints;
+ 
+    // 1, collect all bufs' sizes for the current interface
+    //    to realloc all the chunks
+    __KTRACE_OPT(KUSB, Kern::Printf("Collect all buffer sizes:"));
+    RArray<TInt> bufSizes;
+    for(TInt i=1;i<=numOfEp;i++)
+        {
+        TInt nextEp = asRec->iEpNumDeOrderedByBufSize[i];
+        TInt epBufCount = asRec->iEndpoint[nextEp]->BufferNumber();
+        __KTRACE_OPT(KUSB, Kern::Printf(" ep %d, buf count %d", nextEp, epBufCount ));
+        for(TInt k=0;k<epBufCount;k++)
+            {
+            TInt epBufSize = asRec->iEndpoint[nextEp]->BufferSize();
+            TInt r = bufSizes.Append(epBufSize);
+            if(r!=KErrNone)
+                {
+                iController->DeRegisterClient(this);
+                bufSizes.Close();
+                return r;
+                }
+            __KTRACE_OPT(KUSB,Kern::Printf(" %d", epBufSize ));
+            }
+        __KTRACE_OPT(KUSB, Kern::Printf("\n"));
+
+        }
+   
+    // 2, alloc the buffer decreasely, biggest-->smallest
+    //   2.1 check the existing chunks
+    TInt bufCount = bufSizes.Count();
+    __KTRACE_OPT(KUSB, Kern::Printf(" ep buf number needed %d", bufCount ));
+    __KTRACE_OPT(KUSB, Kern::Printf(" chunks available %d", aHwChunks.Count() ));
+
+    TInt chunkInd = 0;
+    while( (chunkInd<aHwChunks.Count())&& (chunkInd<bufCount))
+        {
+        TUint8* oldAddr = NULL;
+        oldAddr = reinterpret_cast<TUint8*>(aHwChunks[chunkInd]->LinearAddress());
+
+        DPlatChunkHw* chunk = ReAllocate(bufSizes[chunkInd], aHwChunks[chunkInd], aCacheAttribs);
+        if (chunk == NULL)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("Failed to alloc chunks size %d!", bufSizes[chunkInd]));
+            // lost all interfaces:
+            // Tell Controller to release Interface and h/w resources associated with this
+            iController->DeRegisterClient(this);
+            bufSizes.Close();
+            return KErrNoMemory;
+            }
+        else
+            {
+            // Parcel out the memory between endpoints
+            TUint8* newAddr = reinterpret_cast<TUint8*>(chunk->LinearAddress());
+            __KTRACE_OPT(KUSB, Kern::Printf("SetupInterfaceMemory alloc new chunk=0x%x, size=%d", newAddr,bufSizes[chunkInd]));
+            // The check is important to avoid chunkChanged to be corrupted.
+            // This code change is to fix the problem that one chunk is used by multiple interfaces.
+            if(!chunkChanged)
+                {
+                chunkChanged = (newAddr != oldAddr);
+                }            
+            aHwChunks[chunkInd] = chunk;
+            }
+        chunkInd++;
+        }
+    
+    //   2.2 in case available chunks are not enough
+    while( chunkInd<bufCount)
+        {
+        DPlatChunkHw* chunk = NULL;
+        chunk = Allocate( bufSizes[chunkInd], aCacheAttribs);
+        if (chunk == NULL)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("Failed to alloc chunk, size %d!", bufSizes[chunkInd]));
+            // lost all interfaces:
+            // Tell Controller to release Interface and h/w resources associated with this
+            iController->DeRegisterClient(this);
+            bufSizes.Close();
+            return KErrNoMemory;
+            }
+        else
+            {
+            // Parcel out the memory between endpoints
+            __KTRACE_OPT(KUSB, Kern::Printf("SetupInterfaceMemory alloc new chunk=0x%x, size=%d",
+                                    reinterpret_cast<TUint8*>(chunk->LinearAddress()), bufSizes[chunkInd]));
+            TInt r = aHwChunks.Append(chunk);
+            if(r!=KErrNone)
+                {
+                ClosePhysicalChunk(chunk);
+                iController->DeRegisterClient(this);
+                bufSizes.Close();
+                return r;
+                }
+            }
+        chunkInd++;
+        }
+
+    // 3, Set the the bufs of the interfaces
+    
+    ReSetInterfaceMemory(asRec, aHwChunks);
+
+    if(chunkChanged)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("SetupInterfaceMemory readdressing."));
+        asRec = asRec->iNext;
+        while (asRec)
+            {
+            // Interfaces are not concurrent so they can all start at the same logical address
+            __KTRACE_OPT(KUSB, Kern::Printf("SetupInterfaceMemory readdressing setting=%d", asRec->iSetting));
+            ReSetInterfaceMemory(asRec, aHwChunks);
+            asRec = asRec->iNext;
+            }
+        }
+    return KErrNone;
+    }
+
+TInt DLddUsbcChannel::SetupEp0()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("SetupEp0 entry %x", this));
+    TInt ep0Size = iController->Ep0PacketSize();
+    TUsbcEndpointInfo ep0Info = TUsbcEndpointInfo(UsbShai::KUsbEpTypeControl, UsbShai::KUsbEpDirBidirect, ep0Size);
+    TUsbcEndpoint* ep0 = new TUsbcEndpoint(this, iController, &ep0Info, 0, 0);
+    if (ep0 == NULL)
+        {
+        return KErrNoMemory;
+        }
+    // In case we have to return early:
+    iEndpoint[0] = ep0;
+    TInt r = ep0->Construct();
+    if (r != KErrNone)
+        {
+        return KErrNoMemory;
+        }
+
+    TInt bufferNum = ep0->BufferNumber();
+    TInt bufferSize = ep0->BufferSize();
+    TUint32 cacheAttribs = EMapAttrSupRw | EMapAttrCachedMax;
+
+    for(TInt i=0;i<bufferNum;i++)
+        {
+        DPlatChunkHw* chunk = Allocate(bufferSize, cacheAttribs );
+        if(chunk==NULL)
+            {
+            return KErrNoMemory;
+            }
+        TInt r = iHwChunksEp0.Append(chunk);
+        if(r!=KErrNone)
+            {
+            ClosePhysicalChunk(chunk);
+            return r;
+            }
+        TUint8 * buf;
+        buf = (TUint8*) chunk->LinearAddress();
+        ep0->SetBufferAddr( i, buf);
+        __KTRACE_OPT(KUSB, Kern::Printf("SetupEp0 60 buffer number %d", i));
+        __KTRACE_OPT(KUSB, Kern::Printf("SetupEp0 60 buffer size %d", bufferSize));
+        }
+
+    ep0->SetRealEpNumber(0);
+    return KErrNone;
+    }
+
+// Set buffer address of the interface
+// Precondition: Enough chunks available.
+void DLddUsbcChannel::ReSetInterfaceMemory(TUsbcAlternateSettingList* aAlternateSettingListRec,
+        RArray<DPlatChunkHw*> &aHwChunks)
+    {
+    TUsbcAlternateSettingList* asRec = aAlternateSettingListRec;
+
+    // set all the interfaces
+    TInt chunkInd = 0;
+    TInt numOfEp = asRec->iNumberOfEndpoints;
+
+    for (TInt i = 1; i <= numOfEp; i++)
+        {
+        TInt nextEp = asRec->iEpNumDeOrderedByBufSize[i];
+        TInt epBufCount = asRec->iEndpoint[nextEp]->BufferNumber();
+        for(TInt k=0;k<epBufCount;k++)
+            {
+            TUsbcEndpoint* ep = asRec->iEndpoint[nextEp];
+            if (ep != NULL )
+                {
+                TUint8* pBuf = NULL;
+                pBuf = reinterpret_cast<TUint8*>(aHwChunks[chunkInd]->LinearAddress());
+                ep->SetBufferAddr( k, pBuf);
+                __KTRACE_OPT(KUSB, Kern::Printf("  ep %d, buf %d, addr 0x%x", nextEp, k, pBuf ));
+                chunkInd++;
+                __ASSERT_DEBUG(chunkInd<=aHwChunks.Count(),
+                               Kern::Printf("  Error: available chunks %d, run out at epInd%d, bufInd%d",
+                                       aHwChunks.Count(), i, k));
+                __ASSERT_DEBUG(chunkInd<=aHwChunks.Count(),
+                                   Kern::Fault("usbc.ldd", __LINE__));
+                }
+            }
+        }
+
+    }
+
+void DLddUsbcChannel::DestroyAllInterfaces()
+    {
+    // Removes all interfaces
+    TUsbcAlternateSettingList* alternateSettingListRec = iAlternateSettingList;
+    while (alternateSettingListRec)
+        {
+        iController->ReleaseInterface(this, alternateSettingListRec->iSetting);
+        TUsbcAlternateSettingList* alternateSettingListRecNext = alternateSettingListRec->iNext;
+        delete alternateSettingListRec;
+        alternateSettingListRec = alternateSettingListRecNext;
+        }
+    iNumberOfEndpoints = 0;
+    iAlternateSettingList = NULL;
+
+    for(TInt i=0;i<iHwChunks.Count();i++)
+        {
+        ClosePhysicalChunk( iHwChunks[i]);
+        }
+    iHwChunks.Close();
+
+    iValidInterface = EFalse;
+    }
+
+
+void DLddUsbcChannel::DestroyInterface(TUint aInterfaceNumber)
+    {
+    if (iAlternateSetting == aInterfaceNumber)
+        {
+        ResetInterface(KErrUsbInterfaceNotReady);
+        iValidInterface = EFalse;
+        iNumberOfEndpoints = 0;
+        for (TInt i = 1; i <= KMaxEndpointsPerClient; i++)
+            {
+            iEndpoint[i] = NULL;
+            }
+        }
+    TUsbcAlternateSettingList* alternateSettingListRec = iAlternateSettingList;
+    TUsbcAlternateSettingList* alternateSettingListRecOld = NULL;
+    while (alternateSettingListRec)
+        {
+        TUsbcAlternateSettingList* alternateSettingListRecNext = alternateSettingListRec->iNext;
+        if (alternateSettingListRec->iSetting == aInterfaceNumber)
+            {
+            // This record is to be deleted
+            if (alternateSettingListRecOld == NULL)
+                {
+                // The record to be deleted is at the list head
+                iAlternateSettingList = alternateSettingListRecNext;
+                }
+            else
+                {
+                // The record to be deleted is NOT at the list head
+                alternateSettingListRecOld->iNext = alternateSettingListRecNext;
+                }
+            delete alternateSettingListRec;
+            break;
+            }
+        alternateSettingListRecOld = alternateSettingListRec;
+        alternateSettingListRec = alternateSettingListRecNext;
+        }
+
+    if (iAlternateSettingList == NULL)
+        {
+        // if no interfaces left destroy non-ep0 buffering
+        for(TInt i=0;i<iHwChunks.Count();i++)
+            {
+            ClosePhysicalChunk( iHwChunks[i]);
+            }
+        iHwChunks.Close();
+        }
+    }
+
+
+void DLddUsbcChannel::DestroyEp0()
+    {
+    delete iEndpoint[0];
+    iEndpoint[0] = NULL;
+    for(TInt i=0;i<iHwChunksEp0.Count();i++)
+        {
+        ClosePhysicalChunk( iHwChunksEp0[i] );
+        }
+    iHwChunksEp0.Close();
+    }
+
+
+void DLddUsbcChannel::EndpointStatusChangeCallback(TAny* aDLddUsbcChannel)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("EndpointStatusChangeCallback"));
+    DLddUsbcChannel* dUsbc = (DLddUsbcChannel*) aDLddUsbcChannel;
+    if (dUsbc->iChannelClosing)
+        return;
+    TUint endpointState = dUsbc->iEndpointStatusCallbackInfo.State();
+    const TInt reqNo = (TInt) RDevUsbcClient::ERequestEndpointStatusNotify;
+    if (dUsbc->iRequestStatus[reqNo])
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("EndpointStatusChangeCallback Notify status"));
+        DThread* client = dUsbc->iClient;
+        
+        dUsbc->iEndpointStatusChangeReq->Data() = endpointState;
+        dUsbc->iRequestStatus[reqNo] = NULL;
+        Kern::QueueRequestComplete(client,dUsbc->iEndpointStatusChangeReq,KErrNone);
+        dUsbc->iEndpointStatusChangePtr = NULL;
+        }
+    }
+
+
+void DLddUsbcChannel::StatusChangeCallback(TAny* aDLddUsbcChannel)
+    {
+    DLddUsbcChannel* dUsbc = (DLddUsbcChannel*) aDLddUsbcChannel;
+    if (dUsbc->iChannelClosing)
+        return;
+
+    TUsbcDeviceState deviceState;
+    TInt i;
+     for (i = 0;
+          (i < KUsbcDeviceStateRequests) && ((deviceState = dUsbc->iStatusCallbackInfo.State(i)) != UsbShai::EUsbPeripheralNoState);
+          ++i)
+        {
+         __KTRACE_OPT(KUSB, Kern::Printf("StatusChangeCallBack status=%d", deviceState));
+        if (deviceState & KUsbAlternateSetting)
+            {
+            dUsbc->ProcessAlternateSetting(deviceState);
+            }
+        else
+            {
+            dUsbc->ProcessDeviceState(deviceState);
+            }
+        // Only queue if userside is interested
+        if (dUsbc->iDeviceStatusNeeded)
+            {
+            dUsbc->iStatusFifo->AddStatusToQueue(deviceState);
+            const TInt reqNo = (TInt) RDevUsbcClient::ERequestAlternateDeviceStatusNotify;
+            if (dUsbc->AlternateDeviceStateTestComplete())
+                {
+                    dUsbc->iRequestStatus[reqNo]=NULL;
+                    Kern::QueueRequestComplete(dUsbc->iClient,dUsbc->iStatusChangeReq,KErrNone);
+                }
+            }
+        }
+     // We don't want to be interrupted in the middle of this:
+    const TInt irqs = NKern::DisableInterrupts(2);
+     dUsbc->iStatusCallbackInfo.ResetState();
+    NKern::RestoreInterrupts(irqs);
+    }
+
+
+void DLddUsbcChannel::OtgFeatureChangeCallback(TAny* aDLddUsbcChannel)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("OtgFeatureChangeCallback"));
+    DLddUsbcChannel* dUsbc = (DLddUsbcChannel*) aDLddUsbcChannel;
+    if (dUsbc->iChannelClosing)
+        return;
+
+    TUint8 features;
+    // No return value check. Assume OTG always supported here
+    dUsbc->iController->GetCurrentOtgFeatures(features);
+
+    const TInt reqNo = (TInt) RDevUsbcClient::ERequestOtgFeaturesNotify;
+    if (dUsbc->iRequestStatus[reqNo])
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("OtgFeatureChangeCallback Notify status"));
+        dUsbc->iOtgFeatureChangeReq->Data()=features;
+        dUsbc->iRequestStatus[reqNo] = NULL;
+        Kern::QueueRequestComplete(dUsbc->iClient,dUsbc->iOtgFeatureChangeReq,KErrNone);
+        dUsbc->iOtgFeatureChangePtr = NULL;
+        }
+    }
+
+
+TInt DLddUsbcChannel::SelectAlternateSetting(TUint aAlternateSetting)
+    {
+    TInt r = KErrGeneral;                                    // error code doesn't go userside
+    TUsbcAlternateSettingList* alternateSettingListRec = iAlternateSettingList;
+    while (alternateSettingListRec)
+        {
+        if (alternateSettingListRec->iSetting == aAlternateSetting)
+            {
+            // found the correct interface, now latch in new endpoint set
+            for (TInt i = 1; i <= KMaxEndpointsPerClient; i++)
+                {
+                iEndpoint[i] = NULL;
+                }
+            iNumberOfEndpoints = alternateSettingListRec->iNumberOfEndpoints;
+            r = KErrNone;
+            for (TInt i = 1; i <= KMaxEndpointsPerClient; i++)
+                {
+                iEndpoint[i] = alternateSettingListRec->iEndpoint[i];
+                }
+            // Only after correct alternate setting has been chosen.
+            UpdateEndpointSizes();
+            }
+        alternateSettingListRec = alternateSettingListRec->iNext;
+        }
+    return r;
+    }
+
+
+TInt DLddUsbcChannel::EpFromAlternateSetting(TUint aAlternateSetting, TInt aEndpoint)
+    {
+    TUsbcAlternateSettingList* alternateSettingListRec = iAlternateSettingList;
+    while (alternateSettingListRec)
+        {
+        if (alternateSettingListRec->iSetting == aAlternateSetting)
+            {
+            if ((aEndpoint <= alternateSettingListRec->iNumberOfEndpoints) &&
+                (aEndpoint >= 0))
+                {
+                return alternateSettingListRec->iEndpoint[aEndpoint]->RealEpNumber();
+                }
+            else
+                {
+                __KTRACE_OPT(KPANIC, Kern::Printf("  Error: aEndpoint %d wrong for aAlternateSetting %d",
+                                                  aEndpoint, aAlternateSetting));
+                return -1;
+                }
+            }
+        alternateSettingListRec = alternateSettingListRec->iNext;
+        }
+    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: no aAlternateSetting %d found", aAlternateSetting));
+    return -1;
+    }
+
+
+TInt DLddUsbcChannel::ProcessAlternateSetting(TUint aAlternateSetting)
+    {
+    ResetInterface(KErrUsbInterfaceChange);                    // kill any outstanding transfers
+    __KTRACE_OPT(KUSB, Kern::Printf("ProcessAlternateSetting 0x%08x", aAlternateSetting));
+    TUint newSetting = aAlternateSetting&(~KUsbAlternateSetting);
+    __KTRACE_OPT(KUSB, Kern::Printf("ProcessAlternateSetting selecting alternate setting 0x%08x", newSetting));
+    TInt r = SelectAlternateSetting(newSetting);
+    if (r != KErrNone)
+        return r;
+    StartEpReads();
+    iAlternateSetting = newSetting;
+    return KErrNone;
+    }
+
+
+TInt DLddUsbcChannel::ProcessDeviceState(TUsbcDeviceState aDeviceState)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("ProcessDeviceState(%d -> %d)", iDeviceState, aDeviceState));
+    if (iDeviceState == aDeviceState)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  No state change => nothing to be done."));
+        return KErrNone;
+        }
+    if (iDeviceState == UsbShai::EUsbPeripheralStateSuspended)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Coming out of Suspend: old state = %d", iOldDeviceState));
+        iDeviceState = iOldDeviceState;
+        if (iDeviceState == aDeviceState)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  New state same as before Suspend => nothing to be done."));
+            return KErrNone;
+            }
+        }
+    TBool renumerateState = (aDeviceState == UsbShai::EUsbPeripheralStateConfigured);
+    TBool deconfigured = EFalse;
+    TInt cancellationCode = KErrNone;
+    if (aDeviceState == UsbShai::EUsbPeripheralStateSuspended)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Suspending..."));
+        iOldDeviceState = iDeviceState;
+        // Put PSL into low power mode here
+        }
+    else
+        {
+        deconfigured = (iDeviceState == UsbShai::EUsbPeripheralStateConfigured &&
+                        aDeviceState != UsbShai::EUsbPeripheralStateConfigured);
+        if (iDeviceState == UsbShai::EUsbPeripheralStateConfigured)
+            {
+            if (aDeviceState == UsbShai::EUsbPeripheralStateUndefined)
+                cancellationCode = KErrUsbCableDetached;
+            else if (aDeviceState == UsbShai::EUsbPeripheralStateAddress)
+                cancellationCode = KErrUsbDeviceNotConfigured;
+            else if (aDeviceState == UsbShai::EUsbPeripheralStateDefault)
+                cancellationCode = KErrUsbDeviceBusReset;
+            else
+                cancellationCode = KErrUsbDeviceNotConfigured;
+            }
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("  %d --> %d", iDeviceState, aDeviceState));
+    iDeviceState = aDeviceState;
+    if (iValidInterface || iOwnsDeviceControl)
+        {
+        // This LDD may not own an interface. It could be some manager reenumerating
+        // after its subordinate LDDs have setup their interfaces.
+        if (deconfigured)
+            {
+            DeConfigure(cancellationCode);
+            }
+        else if (renumerateState)
+            {
+            // Update size of Ep0.
+            iEndpoint[0]->SetMaxPacketSize(iController->Ep0PacketSize());
+            // First cancel transfers on all endpoints
+            ResetInterface(KErrUsbInterfaceChange);
+            // Select main interface & latch in new endpoint set
+            SelectAlternateSetting(0);
+            // Here we go
+            StartEpReads();
+            }
+        }
+
+    const TInt reqNo = (TInt) RDevUsbcClient::ERequestReEnumerate;
+    if (renumerateState && iRequestStatus[reqNo])
+        {
+        // This lot must be done if we are reenumerated
+        CompleteBufferRequest(iClient, reqNo, KErrNone);
+        }
+
+    return KErrNone;
+    }
+
+
+void DLddUsbcChannel::UpdateEndpointSizes()
+    {
+    // The regular ones.
+    TInt i = 0;
+    while ((++i <= KMaxEndpointsPerClient) && iEndpoint[i])
+        {
+        const TInt size = iController->EndpointPacketSize(this, iEndpoint[i]->RealEpNumber());
+        if (size < 0)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Packet size < 0 for ep %d", i));
+            continue;
+            }
+        iEndpoint[i]->SetMaxPacketSize(size);
+        }
+    __ASSERT_DEBUG(i == iNumberOfEndpoints + 1,
+                   Kern::Printf("  Error: iNumberOfEndpoints wrong (%d)", iNumberOfEndpoints));
+    }
+
+
+DPlatChunkHw* DLddUsbcChannel::ReAllocate(TInt aBuffersize, DPlatChunkHw* aHwChunk, TUint32 aCacheAttribs)
+    {
+    DPlatChunkHw* chunk = aHwChunk;
+    if ((!chunk) || (chunk->iSize < aBuffersize))
+        {
+        if (chunk)
+            {
+            ClosePhysicalChunk(chunk);
+            }
+        __KTRACE_OPT(KUSB, Kern::Printf("ReAllocate need to get new chunk"));
+        chunk = Allocate(aBuffersize, aCacheAttribs);
+        }
+    return chunk;
+    }
+
+
+DPlatChunkHw* DLddUsbcChannel::Allocate(TInt aBuffersize, TUint32 aCacheAttribs)
+    {
+    TUint32 physAddr = 0;
+    TUint32 size = Kern::RoundToPageSize(aBuffersize);
+
+    if (Epoc::AllocPhysicalRam(size, physAddr) != KErrNone)
+        return NULL;
+
+    DPlatChunkHw* HwChunk;
+    if (DPlatChunkHw::New(HwChunk, physAddr, aBuffersize, aCacheAttribs) != KErrNone)
+        {
+        Epoc::FreePhysicalRam(physAddr, size);
+        return NULL;
+        }
+
+    return HwChunk;
+    }
+
+
+TInt DLddUsbcChannel::DoRxComplete(TUsbcEndpoint* aTUsbcEndpoint, TInt aEndpoint, TBool aReEntrant)
+    {
+    TBool completeNow;
+    TInt err = aTUsbcEndpoint->CopyToClient(iClient, completeNow,iClientAsynchNotify[aEndpoint]->iClientBuffer);
+    if (completeNow)
+        {
+        aTUsbcEndpoint->SetClientReadPending(EFalse);
+        CompleteBufferRequest(iClient, aEndpoint, err);
+        }
+    aTUsbcEndpoint->TryToStartRead(aReEntrant);
+    return err;
+    }
+
+
+void DLddUsbcChannel::DoRxCompleteNow(TUsbcEndpoint* aTUsbcEndpoint, TInt aEndpoint)
+    {
+    aTUsbcEndpoint->SetClientReadPending(EFalse);
+    CompleteBufferRequest(iClient, aEndpoint, KErrCancel);
+    }
+
+
+void DLddUsbcChannel::DoTxComplete(TUsbcEndpoint* aTUsbcEndpoint, TInt aEndpoint, TInt aError)
+    {
+    aTUsbcEndpoint->SetClientWritePending(EFalse);
+    CompleteBufferRequest(iClient, aEndpoint, aError);
+    }
+
+
+TBool DLddUsbcChannel::AlternateDeviceStateTestComplete()
+    {
+    TBool completeNow = EFalse;
+    const TInt reqNo = (TInt) RDevUsbcClient::ERequestAlternateDeviceStatusNotify;
+    if (iRequestStatus[reqNo])
+        {
+        // User req is outstanding
+        TUint32 deviceState;
+        if (iStatusFifo->GetDeviceQueuedStatus(deviceState) == KErrNone)
+            {
+            // Device state waiting to be sent userside
+            completeNow = ETrue;
+            __KTRACE_OPT(KUSB, Kern::Printf("StatusChangeCallback Notify status"));
+            iStatusChangeReq->Data()=deviceState;
+            iStatusChangePtr = NULL;
+            }
+        }
+    return completeNow;
+    }
+
+
+void DLddUsbcChannel::EmergencyCompleteDfc(TAny* aDLddUsbcChannel)
+    {
+    ((DLddUsbcChannel*) aDLddUsbcChannel)->DoEmergencyComplete();
+    }
+
+
+void DLddUsbcChannel::DeConfigure(TInt aErrorCode)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcChannel::DeConfigure()"));
+    // Called after deconfiguration. Cancels transfers on all endpoints.
+    ResetInterface(aErrorCode);
+    // Cancel the endpoint status notify request if it is outstanding.
+    const TInt KEpNotReq = RDevUsbcClient::ERequestEndpointStatusNotify;
+    if (iRequestStatus[KEpNotReq])
+        {
+        CancelNotifyEndpointStatus();
+        iRequestStatus[KEpNotReq]=NULL;
+        Kern::QueueRequestComplete(iClient,iEndpointStatusChangeReq,aErrorCode);
+        }
+    // We have to reset the alternate setting number when the config goes away.
+     SelectAlternateSetting(0);
+    iAlternateSetting = 0;
+    }
+
+
+void DLddUsbcChannel::StartEpReads()
+    {
+    // Queued after enumeration. Starts reads on all endpoints.
+    // The endpoint itself decides if it can do a read
+    TInt i;
+    for (i = 0; i <= iNumberOfEndpoints; i++)
+        {
+        // The endpoint itself will decide if it can read
+        iEndpoint[i]->TryToStartRead(EFalse);
+        }
+    }
+
+
+void DLddUsbcChannel::ResetInterface(TInt aErrorCode)
+    {
+    // Called after change in alternate setting.  Cancels transfers on all endpoints
+    if (iValidInterface || iOwnsDeviceControl)
+        {
+        // Reset each endpoint except ep0
+        for (TInt i = 1; i <= iNumberOfEndpoints; i++)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("Cancelling transfer ep=%d", i));
+            iEndpoint[i]->CancelTransfer(iClient,iClientAsynchNotify[i]->iClientBuffer);            // Copies data userside
+            iEndpoint[i]->AbortTransfer();                    // kills any ldd->pil outstanding transfers
+            iEndpoint[i]->iDmaBuffers->Flush();
+            if (iRequestStatus[i] != NULL)
+                CompleteBufferRequest(iClient, i, aErrorCode);
+            iEndpoint[i]->SetClientWritePending(EFalse);
+            iEndpoint[i]->SetClientReadPending(EFalse);
+            }
+        }
+    }
+
+
+void DLddUsbcChannel::AbortInterface()
+    {
+    // Called after when channel is closing
+    if (iValidInterface || iOwnsDeviceControl)
+        {
+        for (TInt i = 0; i <= iNumberOfEndpoints; i++)
+            {
+            if (iEndpoint[i])
+                {
+                // kills any LDD->PDD outstanding transfers
+                iEndpoint[i]->AbortTransfer();
+                }
+            }
+        }
+    }
+
+
+void DLddUsbcChannel::ClosePhysicalChunk(DPlatChunkHw*& aHwChunk)
+    {
+    if (aHwChunk)
+        {
+         const TPhysAddr addr = aHwChunk->PhysicalAddress();
+         const TInt size = aHwChunk->iSize;
+        aHwChunk->Close(NULL);
+         Epoc::FreePhysicalRam(addr, size);
+        }
+    aHwChunk = NULL;
+    }
+
+
+TInt DLddUsbcChannel::DoEmergencyComplete()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpoint::DoEmergencyComplete"));
+    // cancel any pending DFCs
+    // complete all client requests
+    for (TInt i = 0; i < KUsbcMaxRequests; i++)
+        {
+        if (iRequestStatus[i])
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("Complete request 0x%x", iRequestStatus[i]));
+
+            if (i == RDevUsbcClient::ERequestAlternateDeviceStatusNotify)
+                {
+
+                iDeviceStatusNeeded = EFalse;
+                iStatusFifo->FlushQueue();
+
+                if (iStatusChangePtr)
+                    {
+                    iStatusChangeReq->Data() = iController->GetDeviceStatus();
+                    iStatusChangePtr = NULL;
+
+                    if (iStatusChangeReq->IsReady())
+                        {
+                        iRequestStatus[i] = NULL;
+                        Kern::QueueRequestComplete(iClient, iStatusChangeReq,
+                                KErrDisconnected);
+                        }
+                    }
+
+                }
+            else if (i == RDevUsbcClient::ERequestEndpointStatusNotify)
+                {
+                    
+                   if (iEndpointStatusChangePtr)
+                    {
+                    TUint epBitmap = 0;
+                    for (TInt i = 0; i <= iNumberOfEndpoints; i++)
+                        {
+                        TInt v = iController->GetEndpointStatus(this, iEndpoint[i]->RealEpNumber());
+                        TUint b;
+                        (v == EEndpointStateStalled) ? b = 1 : b = 0;
+                        epBitmap |= b << i;
+                        }    
+
+                    iEndpointStatusChangeReq->Data() = epBitmap;
+                    iEndpointStatusChangePtr = NULL;
+                    }
+
+                if (iEndpointStatusChangeReq->IsReady())
+                    {
+                    iRequestStatus[i] = NULL;
+                    Kern::QueueRequestComplete(iClient,iEndpointStatusChangeReq,KErrDisconnected);
+                    }
+
+                }
+            else if (i == RDevUsbcClient::ERequestOtgFeaturesNotify)
+                {
+                    
+                if (iOtgFeatureChangePtr)
+                    {
+                    TUint8 features;
+                    iController->GetCurrentOtgFeatures(features);
+                    iOtgFeatureChangeReq->Data()=features;
+                    iOtgFeatureChangePtr = NULL;
+                    }
+                    
+                if (iOtgFeatureChangeReq->IsReady())
+                    {
+                    iRequestStatus[i] = NULL;
+                    Kern::QueueRequestComplete(iClient, iOtgFeatureChangeReq,
+                            KErrDisconnected);
+                    }
+
+                }
+            else
+                {
+                CompleteBufferRequest(iClient, i, KErrDisconnected);
+                }
+
+            }
+        }
+
+    iStatusCallbackInfo.Cancel();
+    iEndpointStatusCallbackInfo.Cancel();
+    iOtgFeatureCallbackInfo.Cancel();
+    return KErrNone;
+    }
+
+
+void DLddUsbcChannel::PanicClientThread(TInt aReason)
+    {
+    Kern::ThreadKill(iClient, EExitPanic, aReason, KUsbLDDKillCat);
+    }
+
+
+// ===============Endpoint====================
+
+// Constructor
+TUsbcEndpoint::TUsbcEndpoint(DLddUsbcChannel* aLDD, DUsbClientController* aController,
+                             const TUsbcEndpointInfo* aEndpointInfo, TInt aEndpointNum,
+                             TInt aBandwidthPriority)
+    : iController(aController),
+      iEndpointInfo(aEndpointInfo->iType, aEndpointInfo->iDir, aEndpointInfo->iSize),
+      iClientReadPending(EFalse),
+      iClientWritePending(EFalse),
+      iEndpointNumber(aEndpointNum),
+      iRealEpNumber(-1),
+      iLdd(aLDD),
+      iError(KErrNone),
+      iRequestCallbackInfo(NULL),
+      iBytesTransferred(0),
+      iBandwidthPriority(aBandwidthPriority)
+    {
+     ResetTransferInfo();
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpoint::TUsbcEndpoint 2"));
+    }
+
+
+TInt TUsbcEndpoint::Construct()
+    {
+    iDmaBuffers = new TDmaBuf(&iEndpointInfo, iBandwidthPriority);
+    if (iDmaBuffers == NULL)
+        {
+        return KErrNoMemory;
+        }
+    const TInt r = iDmaBuffers->Construct(&iEndpointInfo);
+    if (r != KErrNone)
+        {
+        return r;
+        }
+    iRequestCallbackInfo = new TUsbcRequestCallback(iLdd,
+                                                    iEndpointNumber,
+                                                    TUsbcEndpoint::RequestCallback,
+                                                    this,
+                                                    iLdd->iDfcQ,
+                                                    KUsbRequestCallbackPriority);
+    if (iRequestCallbackInfo == NULL)
+        {
+        return KErrNoMemory;
+        }
+    return KErrNone;
+    }
+
+
+TUsbcEndpoint::~TUsbcEndpoint()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpoint::~TUsbcEndpoint(%d)", iEndpointNumber));
+    AbortTransfer();
+    delete iRequestCallbackInfo;
+    delete iDmaBuffers;
+    }
+
+
+void TUsbcEndpoint::RequestCallback(TAny* aTUsbcEndpoint)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpoint::RequestCallback"));
+    ((TUsbcEndpoint*) aTUsbcEndpoint)->EndpointComplete();
+    }
+
+
+void TUsbcEndpoint::SetMaxPacketSize(TInt aSize)
+    {
+    iEndpointInfo.iSize = aSize;
+    iDmaBuffers->SetMaxPacketSize(aSize);
+    }
+
+
+TInt TUsbcEndpoint::EndpointComplete()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpoint::EndpointComplete ep=%d %d",
+                                    iEndpointNumber, iRequestCallbackInfo->iEndpointNum));
+
+    if (iLdd->ChannelClosing())
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("We're going home -> completions no longer accepted"));
+        return KErrNone;
+        }
+
+    UsbShai::TTransferDirection transferDir = iRequestCallbackInfo->iTransferDir;
+    TInt error = iRequestCallbackInfo->iError;
+
+    switch (transferDir)
+        {
+
+    case UsbShai::EControllerWrite:
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpoint::EndpointComplete Write 2"));
+        if (!iDmaBuffers->TxIsActive())
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  TX completion but !iDmaBuffers->TxIsActive()"));
+            break;
+            }
+
+        iDmaBuffers->TxSetInActive();
+        TBool completeNow = EFalse;
+        iBytesTransferred += iRequestCallbackInfo->iTxBytes;
+        if (iClientWritePending)
+            {
+            //Complete Outstanding Write if necessary
+            iError = error;
+            if (iError != KErrNone)
+                {
+                completeNow = ETrue;
+                if (iError == KErrPrematureEnd)                // Previous write could not be completed
+                    iError = KErrNone;
+                }
+            else
+                {
+                if (iBytesTransferred == (TUint32) iTransferInfo.iTransferSize)
+                    {
+                    completeNow = ETrue;
+                    }
+                else
+                    {
+                    iError = ContinueWrite();
+                    if (iError != KErrNone)
+                        completeNow = ETrue;
+                    }
+                }
+            if (completeNow)
+                {
+                TxComplete();
+                ResetTransferInfo();
+                if (iEndpointNumber == 0)
+                    {
+                    iDmaBuffers->Flush();
+                    TryToStartRead(EFalse);
+                    }
+                }
+            }
+        break;
+        }
+
+    case UsbShai::EControllerRead:
+        {
+        // The first packet always contains the total #of bytes
+        const TInt byteCount = iRequestCallbackInfo->iPacketSize[0];
+        const TInt packetCount = iRequestCallbackInfo->iRxPackets;
+        iDmaBuffers->ReadXferComplete(byteCount, packetCount, error);
+
+        // We queue the dfc if we can complete the read, i.e. if we are reading a packet,
+        // or if we have enough data to satisfy a read data request.
+        if (iClientReadPending)
+            {
+            //Complete outstanding read
+            __KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpoint::EndpointComplete Read 3 (bytes "
+                                            "available=%d)", iDmaBuffers->RxBytesAvailable()));
+            TInt bytesReqd = iTransferInfo.iTransferSize - iBytesTransferred;
+            TBool completeNow = EFalse;
+
+            if (iTransferInfo.iTransferType == ETransferTypeReadPacket ||
+                iTransferInfo.iTransferType == ETransferTypeReadOneOrMore)
+                {
+                // Always complete on a packet read
+                completeNow = ETrue;
+                }
+            else if (iTransferInfo.iTransferType == ETransferTypeReadData)
+                {
+                // Complete only if enough data is present
+                if (iDmaBuffers->RxBytesAvailable() >= bytesReqd)
+                    completeNow = ETrue;
+                }
+            else if (iTransferInfo.iTransferType == ETransferTypeReadUntilShort)
+                {
+                // Complete if enough data is present or if a short packet has been delivered
+                const TInt maxPacketSize = iEndpointInfo.iSize;
+                const TInt lastPacketSize = iRequestCallbackInfo->iPacketSize[packetCount - 1];
+                if (lastPacketSize < maxPacketSize)
+                    completeNow = ETrue;
+                else if (iDmaBuffers->RxBytesAvailable() >= bytesReqd)
+                    completeNow = ETrue;
+                else
+                    {
+                    const TUint type = iEndpointInfo.iType;
+                    if ((type == UsbShai::KUsbEpTypeBulk) && (lastPacketSize & (maxPacketSize - 1)))
+                        {
+                        completeNow = ETrue;
+                        }
+                    else if ((type != UsbShai::KUsbEpTypeBulk) &&
+                             (lastPacketSize > maxPacketSize) &&
+                             (lastPacketSize % maxPacketSize))
+                        {
+                        completeNow = ETrue;
+                        }
+                    }
+                }
+            if (completeNow)
+                {
+                iError = error;
+                RxComplete(EFalse);
+                iClientReadPending = EFalse;
+                }
+            }
+        iDmaBuffers->RxSetInActive();
+        if (error != KErrNone)
+            {
+            return error;
+            }
+        if (TryToStartRead(EFalse) != KErrNone)
+            {
+//            if (iEndpointNumber != 0)
+//                Kern::Printf("EndpointComplete couldn't start read on ep=%d", iEndpointNumber);
+            }
+        break;
+        }
+
+    default:
+        // shouldn't get here
+        break;
+        }
+
+    return KErrNone;
+    }
+
+
+void TUsbcEndpoint::TxComplete()
+    {
+    iLdd->DoTxComplete(this, iEndpointNumber, iError);
+    }
+
+
+TInt TUsbcEndpoint::RxComplete(TBool aReEntrant)
+    {
+    return iLdd->DoRxComplete(this, iEndpointNumber, aReEntrant);
+    }
+
+
+void TUsbcEndpoint::RxCompleteNow()
+    {
+    iLdd->DoRxCompleteNow(this, iEndpointNumber);
+    }
+
+
+TInt TUsbcEndpoint::CopyToClient(DThread* aClient, TClientBuffer *aTcb)
+    {
+    TBool completeNow;
+    return CopyToClient(aClient, completeNow,aTcb);
+    }
+
+
+TInt TUsbcEndpoint::CopyToClient(DThread* aClient, TBool& aCompleteNow, TClientBuffer *aTcb)
+    {
+    TInt err;
+    const TInt length = iTransferInfo.iTransferSize;
+    const TBool KReadData = EFalse;
+    const TBool KReadUntilShort = ETrue;
+
+    __KTRACE_OPT(KUSB, Kern::Printf("CopyToClient: length = %d", length));
+
+    if (iTransferInfo.iTransferType == ETransferTypeReadPacket)
+        {
+        err = iDmaBuffers->RxCopyPacketToClient(aClient, aTcb, length);
+        aCompleteNow = ETrue;
+        }
+    else if (iTransferInfo.iTransferType == ETransferTypeReadOneOrMore)
+        {
+        err = iDmaBuffers->RxCopyDataToClient(aClient, aTcb, length, iBytesTransferred,
+                                              KReadData, aCompleteNow);
+        aCompleteNow = ETrue;
+        }
+    else if (iTransferInfo.iTransferType == ETransferTypeReadUntilShort)
+        {
+        err = iDmaBuffers->RxCopyDataToClient(aClient, aTcb, length, iBytesTransferred,
+                                              KReadUntilShort, aCompleteNow);
+        }
+    else
+        {
+        err = iDmaBuffers->RxCopyDataToClient(aClient, aTcb, length, iBytesTransferred,
+                                              KReadData, aCompleteNow);
+        }
+
+    if (aCompleteNow)
+        {
+        ResetTransferInfo();
+        SetClientReadPending(EFalse);
+        }
+
+    return err;
+    }
+
+
+TInt TUsbcEndpoint::TryToStartRead(TBool aReEntrant)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TryToStartRead 1 ep=%d", iEndpointNumber));
+    TInt r = KErrNone;
+    if (iEndpointInfo.iDir != UsbShai::KUsbEpDirOut &&
+        iEndpointInfo.iDir != UsbShai::KUsbEpDirBidirect)
+        {
+        // Verify ep direction
+        __KTRACE_OPT(KUSB, Kern::Printf("TryToStartRead wrong direction ep=%d", iEndpointNumber));
+        return KErrUsbEpBadDirection;
+        }
+
+    if (iEndpointNumber == 0)
+        {
+        // Can't issue an Ep0 read if reader or writer is active
+        if (iDmaBuffers->TxIsActive())
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("TryToStartRead ep0 Tx already active FATAL"));
+            return KErrUsbEpNotReady;
+            }
+        if (iDmaBuffers->RxIsActive())
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("TryToStartRead ep0 Rx already active non-FATAL"));
+            }
+        }
+
+    if (!(iDmaBuffers->RxIsActive()))
+        {
+        TUint8* bufferAddr;
+        TPhysAddr physAddr;
+        TUsbcPacketArray* indexArray;
+        TUsbcPacketArray* sizeArray;
+        TInt length;
+        r = iDmaBuffers->RxGetNextXfer(bufferAddr, indexArray, sizeArray, length, physAddr);
+        if (r == KErrNone)
+            {
+            iDmaBuffers->RxSetActive();
+            iRequestCallbackInfo->SetRxBufferInfo(bufferAddr, physAddr, indexArray, sizeArray, length);
+
+            __KTRACE_OPT(KUSB, Kern::Printf("TryToStartRead 2 bufferAddr=0x%08x", bufferAddr));
+
+            r = iController->SetupReadBuffer(*iRequestCallbackInfo);
+            if (r != KErrNone)
+                {
+                iDmaBuffers->RxSetInActive();
+                __KTRACE_OPT(KPANIC, Kern::Printf("  Error: TryToStartRead controller rejects read"));
+                }
+            }
+        else
+            {
+            if (iClientReadPending)
+                {
+                // Deadlock, try to resolve it by draining buffer into descriptor
+                if (!aReEntrant)
+                    {
+                    RxComplete(ETrue);
+                    }
+                else
+                    {
+                    // we are stuck, better complete userside otherwise the userside request will hang
+                    RxCompleteNow();
+                    }
+                }
+            }
+        }
+    return r;
+    }
+
+
+TInt TUsbcEndpoint::TryToStartWrite(TEndpointTransferInfo* pTfr)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TryToStartWrite 1 ep=%d", iEndpointNumber));
+    if (iEndpointInfo.iDir != UsbShai::KUsbEpDirIn &&
+        iEndpointInfo.iDir != UsbShai::KUsbEpDirBidirect)
+        {
+        // Verify ep direction
+        return KErrUsbEpBadDirection;
+        }
+    if (iEndpointNumber == 0)
+        {
+        // Can't issue an Ep0 write if unread data is available or writer is active
+        if (iDmaBuffers->TxIsActive() || !iDmaBuffers->IsReaderEmpty())
+            {
+            return KErrUsbEpNotReady;
+            }
+        if (iDmaBuffers->RxIsActive())
+            {
+            // if a reader is active then cancel the read
+            iDmaBuffers->RxSetInActive();
+            iController->CancelReadBuffer(iLdd, iRealEpNumber);
+            }
+        }
+    SetTransferInfo(pTfr);
+    ContinueWrite();
+    return KErrNone;
+    }
+
+
+TInt TUsbcEndpoint::ContinueWrite()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("ContinueWrite 2"));
+    TUint8* bufferAddr;
+    TPhysAddr physAddr;
+    TInt bufferLength;
+    TInt r = iDmaBuffers->TxGetNextXfer(bufferAddr, bufferLength, physAddr);
+    if (r != KErrNone)                                            // probably already active
+        return r;
+    __KTRACE_OPT(KUSB, Kern::Printf("ContinueWrite 3"));
+    iDmaBuffers->TxSetActive();
+    TBool zlpReqd = EFalse;
+    TUint32 transferSize = iTransferInfo.iTransferSize;
+    TInt length = Min(transferSize - iBytesTransferred, (TUint32) bufferLength);
+    if (iBytesTransferred+length>=transferSize)
+        {
+        // only send a zlp if this is the last buffer of the transfer
+        zlpReqd = iTransferInfo.iZlpReqd;
+        }
+    r = iDmaBuffers->TxStoreData(iLdd->Client(), iLdd->GetClientBuffer(iEndpointNumber), length, iBytesTransferred);
+    if (r != KErrNone)
+        return r;
+    iDmaBuffers->TxSetActive();
+    iRequestCallbackInfo->SetTxBufferInfo(bufferAddr, physAddr, length);
+    iRequestCallbackInfo->iZlpReqd = zlpReqd;
+#if 0
+    for (TInt i = 0; i < iRequestCallbackInfo->iLength; i++)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("Buffer[%d] = 0x%02x", i, iRequestCallbackInfo->iBufferStart[i]));
+        }
+#endif
+    r = iController->SetupWriteBuffer(*iRequestCallbackInfo);
+    return r;
+    }
+
+
+void TUsbcEndpoint::CancelTransfer(DThread* aThread, TClientBuffer *aTcb)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("CancelTransfer"));
+    if (iDmaBuffers != NULL)
+        {
+        if (iClientWritePending)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  (iClientWritePending)"));
+            iClientWritePending = EFalse;
+            iController->CancelWriteBuffer(iLdd, iRealEpNumber);
+            iDmaBuffers->TxSetInActive();
+            }
+        if (iClientReadPending)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  (iClientReadPending)"));
+            iClientReadPending = EFalse;
+            CopyToClient(aThread,aTcb);
+            }
+        }
+    }
+
+
+void TUsbcEndpoint::AbortTransfer()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("Abort Transfer"));
+    if (iDmaBuffers != NULL)
+        {
+        if (iDmaBuffers->TxIsActive())
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  (iClientWritePending)"));
+            iController->CancelWriteBuffer(iLdd, iRealEpNumber);
+            iDmaBuffers->TxSetInActive();
+            }
+        if (iDmaBuffers->RxIsActive())
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  (iClientReadPending)"));
+            iController->CancelReadBuffer(iLdd, iRealEpNumber);
+            iDmaBuffers->RxSetInActive();
+            }
+        iRequestCallbackInfo->iDfc.Cancel();
+        }
+    }
+
+
+TUsbcAlternateSettingList::TUsbcAlternateSettingList()
+    : iNext(NULL),
+      iNumberOfEndpoints(0),
+      iSetting(0)
+    {
+    for (TInt i = 0; i <= KMaxEndpointsPerClient; i++)
+        {
+        iEpNumDeOrderedByBufSize[i] = -1;
+        iEndpoint[i] = NULL;
+        }
+    }
+
+
+TUsbcAlternateSettingList::~TUsbcAlternateSettingList()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcAlternateSettingList::~TUsbcAlternateSettingList()"));
+    for (TInt i = 0; i <= KMaxEndpointsPerClient; i++)
+        {
+        delete iEndpoint[i];
+        }
+    }
+
+
+TUsbcDeviceStatusQueue::TUsbcDeviceStatusQueue()
+    {
+    FlushQueue();
+    }
+
+
+void TUsbcDeviceStatusQueue::FlushQueue()
+    {
+    for (TInt i = 0; i < KUsbDeviceStatusQueueDepth; i++)
+        {
+        iDeviceStatusQueue[i] = KUsbDeviceStatusNull;
+        }
+    iStatusQueueHead = 0;
+    }
+
+
+void TUsbcDeviceStatusQueue::AddStatusToQueue(TUint32 aDeviceStatus)
+    {
+    // Only add a new status if it is not a duplicate of the one at the head of the queue
+    if (!(iStatusQueueHead != 0 &&
+          iDeviceStatusQueue[iStatusQueueHead - 1] == aDeviceStatus))
+        {
+        if (iStatusQueueHead == KUsbDeviceStatusQueueDepth)
+            {
+            // Discard item at tail of queue
+            TUint32 status;
+            GetDeviceQueuedStatus(status);
+            }
+        iDeviceStatusQueue[iStatusQueueHead] = aDeviceStatus;
+        iStatusQueueHead++;
+        }
+    }
+
+
+TInt TUsbcDeviceStatusQueue::GetDeviceQueuedStatus(TUint32& aDeviceStatus)
+    {
+    TInt r = KErrNone;
+    if (iStatusQueueHead <= 0)
+        {
+        r = KErrGeneral;
+        aDeviceStatus = KUsbDeviceStatusNull;
+        }
+    else
+        {
+        aDeviceStatus = iDeviceStatusQueue[0];
+        for(TInt i = 1; i < KUsbDeviceStatusQueueDepth; i++)
+            {
+            TUint32 s = iDeviceStatusQueue[i];
+            iDeviceStatusQueue[i - 1] = s;
+            }
+        iStatusQueueHead--;
+        iDeviceStatusQueue[KUsbDeviceStatusQueueDepth - 1] = KUsbDeviceStatusNull;
+        }
+    return r;
+    }
+
+void TClientAsynchNotify::Reset()
+{
+    iBufferRequest->Reset();
+    iClientBuffer=NULL;
+}
+
+//---
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/ldd/perildd/src/usbdma.cpp	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,983 @@
+// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\drivers\usbc\usbdma.cpp
+// LDD for USB Device driver stack:
+// Management of DMA-capable data buffers.
+// 
+//
+
+/**
+ @file usbdma.cpp
+ @internalTechnology
+*/
+
+#include <usb/usbc.h>
+
+
+#if defined(_DEBUG)
+static const char KUsbPanicLdd[] = "USB LDD";
+#endif
+
+
+TDmaBuf::TDmaBuf(TUsbcEndpointInfo* aEndpointInfo, TInt aBandwidthPriority)
+    : iBufBasePtr(NULL),
+      iCurrentDrainingBuffer(NULL),
+      iCurrentPacket(0),
+      iCurrentPacketIndexArray(NULL),
+      iCurrentPacketSizeArray(NULL)
+    {
+    iMaxPacketSize = aEndpointInfo->iSize;
+    iEndpointType = aEndpointInfo->iType;
+
+    switch (aEndpointInfo->iType)
+        {
+    case UsbShai::KUsbEpTypeControl:
+        iBufSz = KUsbcDmaBufSzControl;
+        iNumberofBuffers = KUsbcDmaBufNumControl;
+        break;
+    case UsbShai::KUsbEpTypeIsochronous:
+        iBufSz = KUsbcDmaBufSzIsochronous;
+        iNumberofBuffers = KUsbcDmaBufNumIsochronous;
+        break;
+    case UsbShai::KUsbEpTypeBulk:
+        {
+        if (aEndpointInfo->iDir == UsbShai::KUsbEpDirOut)
+            {
+            const TInt priorityOUT = aBandwidthPriority & 0x0f;
+            iBufSz = KUsbcDmaBufSizesBulkOUT[priorityOUT];
+            }
+        else
+            {
+            const TInt priorityIN = (aBandwidthPriority >> 4) & 0x0f;
+            iBufSz = KUsbcDmaBufSizesBulkIN[priorityIN];
+            }
+        iNumberofBuffers = KUsbcDmaBufNumBulk;
+        }
+        break;
+    case UsbShai::KUsbEpTypeInterrupt:
+        iBufSz = KUsbcDmaBufSzInterrupt;
+        iNumberofBuffers = KUsbcDmaBufNumInterrupt;
+        break;
+    default:
+        iBufSz = 0;
+        iNumberofBuffers = 0;
+        }
+
+    if (aEndpointInfo->iDir == UsbShai::KUsbEpDirIn)
+        {
+        iNumberofBuffers = 1;                                // IN endpoints only have 1 buffer
+        }
+
+    for (TInt i = 0; i < KUsbcDmaBufNumMax; i++)
+        {
+        // Buffer logical addresses (pointers)
+        iBuffers[i] = NULL;
+        // Buffer physical addresses
+        iBufferPhys[i] = 0;
+        // Packet indexes base array
+        iPacketIndex[i] = NULL;
+        // Packet sizes base array
+        iPacketSize[i] = NULL;
+        }
+    }
+
+
+TInt TDmaBuf::Construct(TUsbcEndpointInfo* aEndpointInfo)
+    {
+    if (aEndpointInfo->iDir != UsbShai::KUsbEpDirIn)
+        {
+        // IN endpoints don't need a packet array
+
+        // At most 2 packets (clump of max packet size packets) + possible zlp
+        TUsbcPacketArray* bufPtr = iPacketInfoStorage;
+        // this divides up the packet indexing & packet size array over the number of buffers
+        __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::Construct() array base=0x%08x", bufPtr));
+        for (TInt i = 0; i < iNumberofBuffers; i++)
+            {
+            iPacketIndex[i] = bufPtr;
+            bufPtr += KUsbcDmaBufMaxPkts;
+            iPacketSize[i] = bufPtr;
+            bufPtr += KUsbcDmaBufMaxPkts;
+            __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::Construct() packetIndex[%d]=0x%08x packetSize[%d]=0x%08x",
+                                            i, iPacketIndex[i], i, iPacketSize[i]));
+            }
+        }
+    else
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::Construct() IN endpoint"));
+        }
+    Flush();
+    return KErrNone;
+    }
+
+
+TDmaBuf::~TDmaBuf()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::~TDmaBuf()"));
+    }
+
+TInt TDmaBuf::BufferTotalSize() const
+    {
+    return iBufSz * iNumberofBuffers;
+    }
+
+TInt TDmaBuf::BufferSize() const
+    {
+    return iBufSz;
+    }
+
+TInt TDmaBuf::SetBufferAddr(TInt aBufInd, TUint8* aBufAddr)
+    {
+    __ASSERT_DEBUG((aBufInd < iNumberofBuffers),
+                       Kern::Fault(KUsbPanicLdd, __LINE__));
+    iDrainable[aBufInd] = iCanBeFreed[aBufInd] = EFalse;
+    iBuffers[aBufInd] = aBufAddr;
+    iBufferPhys[aBufInd] = Epoc::LinearToPhysical((TLinAddr)aBufAddr);
+    __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::SetBufferAddr() iBuffers[%d]=0x%08x", aBufInd, iBuffers[aBufInd]));
+    return KErrNone;
+    }
+
+TInt TDmaBuf::BufferNumber() const
+    {
+    return iNumberofBuffers;
+    }
+
+void TDmaBuf::SetMaxPacketSize(TInt aSize)
+    {
+    iMaxPacketSize = aSize;
+    }
+
+
+void TDmaBuf::Flush()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::Flush %x", this));
+    iRxActive = EFalse;
+    iTxActive = EFalse;
+    iExtractOffset = 0;
+    iTotalRxBytesAvail = 0;
+    iTotalRxPacketsAvail = 0;
+    iCurrentDrainingBufferIndex = KUsbcInvalidBufferIndex;
+    iCurrentFillingBufferIndex = 0;
+    iDrainQueueIndex = KUsbcInvalidDrainQueueIndex;
+    for (TInt i = 0; i < KUsbcDmaBufNumMax; i++)
+        {
+        iDrainable[i] = EFalse;
+        iCanBeFreed[i] = EFalse;
+        iNumberofBytesRx[i] = 0;
+        iNumberofPacketsRx[i] = 0;
+        iError[i] = KErrGeneral;
+        iDrainQueue[i] = KUsbcInvalidBufferIndex;
+#if defined(USBC_LDD_BUFFER_TRACE)
+        iFillingOrderArray[i] = 0;
+        iNumberofBytesRxRemain[i] = 0;
+        iNumberofPacketsRxRemain[i] = 0;
+#endif
+        }
+    // Drain queue is 1 oversized
+    iDrainQueue[KUsbcDmaBufNumMax] = KUsbcInvalidBufferIndex;
+
+#if defined(USBC_LDD_BUFFER_TRACE)
+    iFillingOrder = 0;
+    iDrainingOrder = 0;
+#endif
+    }
+
+
+void TDmaBuf::RxSetActive()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxSetActive %x", this));
+    iRxActive = ETrue;
+    }
+
+
+void TDmaBuf::RxSetInActive()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxSetInActive %x", this));
+    iRxActive = EFalse;
+    }
+
+
+TBool TDmaBuf::RxIsActive()
+    {
+    return iRxActive;
+    }
+
+
+void TDmaBuf::TxSetActive()
+    {
+    iTxActive = ETrue;
+    }
+
+
+void TDmaBuf::TxSetInActive()
+    {
+    iTxActive = EFalse;
+    }
+
+
+TBool TDmaBuf::TxIsActive()
+    {
+    return iTxActive;
+    }
+
+
+/**************************** Rx DMA Buffer Access *************************/
+
+void TDmaBuf::ModifyTotalRxBytesAvail(TInt aVal)
+    {
+    iTotalRxBytesAvail += aVal;
+    }
+
+
+void TDmaBuf::ModifyTotalRxPacketsAvail(TInt aVal)
+    {
+    iTotalRxPacketsAvail += aVal;
+    }
+
+
+TBool TDmaBuf::AdvancePacket()
+    {
+    ModifyTotalRxPacketsAvail(-1);
+    TBool r = ETrue;
+    __ASSERT_DEBUG((iCurrentDrainingBufferIndex >= 0),
+                       Kern::Fault(KUsbPanicLdd, __LINE__));
+    if (++iCurrentPacket >= iNumberofPacketsRx[iCurrentDrainingBufferIndex])
+        {
+        r = NextDrainableBuffer();
+        }
+    iExtractOffset = 0;
+    __ASSERT_DEBUG((iCurrentDrainingBufferIndex == KUsbcInvalidBufferIndex) ||
+                   (iCurrentPacket < KUsbcDmaBufMaxPkts),
+                   Kern::Fault(KUsbPanicLdd, __LINE__));
+    return r;
+    }
+
+
+TInt TDmaBuf::PeekNextPacketSize()
+    {
+    TUint pkt = iCurrentPacket;
+    TInt index = iCurrentDrainingBufferIndex;
+    TInt size = -1;
+    if (pkt >= iNumberofPacketsRx[index])
+        {
+        index = PeekNextDrainableBuffer();
+        pkt = 0;
+        }
+
+    if ((index != KUsbcInvalidBufferIndex) && iNumberofPacketsRx[index])
+        {
+        const TUsbcPacketArray* sizeArray = iPacketSize[index];
+        size = (TInt)sizeArray[pkt];
+        }
+
+    __ASSERT_DEBUG((iCurrentDrainingBufferIndex == KUsbcInvalidBufferIndex) ||
+                   (iCurrentPacket < KUsbcDmaBufMaxPkts),
+                   Kern::Fault(KUsbPanicLdd, __LINE__));
+    return size;
+    }
+
+
+inline TInt TDmaBuf::GetCurrentError()
+    {
+    // USB bus errors are v.rare. To avoid having an error code attached to every packet since
+    // almost every errorcode will be KErrNone, we have a single error code per buffer
+    // If the error code is != KErrNone then it refers to the LAST packet in the buffer
+    TInt errorCode = KErrNone;
+    //Check the index, it's not equal to negative (-1) value defined in 
+    //KUsbcInvalidBufferIndex.
+    __ASSERT_DEBUG((iCurrentDrainingBufferIndex >= 0),
+                       Kern::Fault(KUsbPanicLdd, __LINE__));
+    
+    if (iError[iCurrentDrainingBufferIndex] != KErrNone)
+        {
+        // See if we are at the last packet
+        if ((iCurrentPacket + 1) == iNumberofPacketsRx[iCurrentDrainingBufferIndex])
+            {
+            errorCode = iError[iCurrentDrainingBufferIndex];
+            }
+        }
+    return errorCode;
+    }
+
+
+// used to decide whether a client read can complete straight away
+TBool TDmaBuf::IsReaderEmpty()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::IsReaderEmpty iTotalRxPacketsAvail=%d",
+                                    iTotalRxPacketsAvail));
+    return (iTotalRxPacketsAvail == 0);
+    }
+
+
+void TDmaBuf::ReadXferComplete(TInt aNoBytesRecv, TInt aNoPacketsRecv, TInt aErrorCode)
+    {
+    // Adjust pending packet
+    if ((aNoBytesRecv == 0) && (aErrorCode != KErrNone))
+        {
+        // Make the buffer available for reuse
+        iDrainable[iCurrentFillingBufferIndex] = EFalse;
+        return;
+        }
+
+    ModifyTotalRxBytesAvail(aNoBytesRecv);
+    ModifyTotalRxPacketsAvail(aNoPacketsRecv);
+    iNumberofBytesRx[iCurrentFillingBufferIndex] = aNoBytesRecv;
+    iNumberofPacketsRx[iCurrentFillingBufferIndex] = aNoPacketsRecv;
+
+#if defined(USBC_LDD_BUFFER_TRACE)
+    iNumberofBytesRxRemain[iCurrentFillingBufferIndex] = aNoBytesRecv;
+    iNumberofPacketsRxRemain[iCurrentFillingBufferIndex] = aNoPacketsRecv;
+#endif
+
+    __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::ReadXferComplete 2 # of bytes=%d # of packets=%d",
+                                    iTotalRxBytesAvail, iTotalRxPacketsAvail));
+    iDrainable[iCurrentFillingBufferIndex] = ETrue;
+    iError[iCurrentFillingBufferIndex] = aErrorCode;
+    AddToDrainQueue(iCurrentFillingBufferIndex);
+    if (iCurrentDrainingBufferIndex == KUsbcInvalidBufferIndex)
+        {
+        NextDrainableBuffer();
+        }
+    }
+
+
+TInt TDmaBuf::RxGetNextXfer(TUint8*& aBufferAddr, TUsbcPacketArray*& aIndexArray,
+                            TUsbcPacketArray*& aSizeArray, TInt& aLength, TPhysAddr& aBufferPhys)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxGetNextXfer 1"));
+    if (RxIsActive())
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf(" ---> RxIsActive, returning"));
+        return KErrInUse;
+        }
+
+    __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxGetNextXfer Current buffer=%d",
+                                    iCurrentFillingBufferIndex));
+    if (iDrainable[iCurrentFillingBufferIndex])
+        {
+        // If the controller refused the last read request, then the current buffer will still be marked
+        // as !Drainable, because the controller never completed the read to the ldd. and therefore the buffer
+        // can be reused.
+        if (!NextFillableBuffer())
+            {
+            return KErrNoMemory;
+            }
+        }
+
+    __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxGetNextXfer New buffer=%d",
+                                    iCurrentFillingBufferIndex));
+    aBufferAddr = iBuffers[iCurrentFillingBufferIndex];
+    aBufferPhys = iBufferPhys[iCurrentFillingBufferIndex];
+    aIndexArray = iPacketIndex[iCurrentFillingBufferIndex];
+    aSizeArray = iPacketSize[iCurrentFillingBufferIndex];
+    aLength = iBufSz;
+
+#if defined(USBC_LDD_BUFFER_TRACE)
+    iFillingOrderArray[iCurrentFillingBufferIndex] = ++iFillingOrder;
+#endif
+
+    return KErrNone;
+    }
+
+
+TInt TDmaBuf::RxCopyPacketToClient(DThread* aThread, TClientBuffer *aTcb, TInt aLength)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxCopyPacketToClient 1"));
+
+#if defined(USBC_LDD_BUFFER_TRACE)
+    const TInt numPkts = NoRxPackets();
+    const TInt numPktsAlt = NoRxPacketsAlt();
+    const TInt numBytes = RxBytesAvailable();
+    const TInt numBytesAlt = NoRxBytesAlt();
+
+    if (numPkts != numPktsAlt)
+        {
+        Kern::Printf(
+            "TDmaBuf::RxCopyPacketToClient: Error: #pkts mismatch global=%d actual=%d",
+            numPkts, numPktsAlt);
+        }
+    if (numBytes != numBytesAlt)
+        {
+        Kern::Printf(
+            "TDmaBuf::RxCopyPacketToClient: Error: #bytes mismatch global=%d actual=%d",
+            numBytes, numBytesAlt);
+        }
+    if ((numPkts == 0) && (numBytes !=0))
+        {
+        Kern::Printf(
+            "TDmaBuf::RxCopyPacketToClient: Error: global bytes & pkts mismatch pkts=%d bytes=%d",
+            numPkts, numBytes);
+        }
+    if ((numPktsAlt == 0) && (numBytesAlt !=0))
+        {
+        Kern::Printf(
+            "TDmaBuf::RxCopyPacketToClient: Error: actual bytes & pkts mismatch pkts=%d bytes=%d",
+            numPktsAlt, numBytesAlt);
+        }
+#endif
+
+    if (!NoRxPackets())
+        return KErrNotFound;
+
+    __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxCopyPacketToClient 2"));
+    // the next condition should be true because we have some packets available
+    // coverity[var_tested_neg]
+    if (iCurrentDrainingBufferIndex == KUsbcInvalidBufferIndex)
+        {
+        // Marked as Coverity "Intentional" as the member variable
+        // iCurrentDrainingBufferIndex is attentionaly negative, from previous 
+        // initialization to KUsbcInvalidBufferIndex (which equals -1).
+        if (!NextDrainableBuffer())
+            return KErrNotFound;
+        }
+
+    __ASSERT_DEBUG((iCurrentDrainingBufferIndex >= 0 ),
+                           Kern::Fault(KUsbPanicLdd, __LINE__));
+    
+    if (!iDrainable[iCurrentDrainingBufferIndex])
+        return KErrNotFound;
+
+    // Calculate copy-from address & adjust for the fact that
+    // some data may have already been read from the packet
+    TUint8* logicalSrc = iCurrentDrainingBuffer + iCurrentPacketIndexArray[iCurrentPacket] + iExtractOffset;
+    TInt packetSz = iCurrentPacketSizeArray[iCurrentPacket];
+    TInt thisPacketSz = packetSz - iExtractOffset;
+    TInt errorCode;
+    // try and sort out what a "packet" might mean.
+    // in a multi-packet dma environment, we might see super-packets
+    // i.e. we might just see one packet, maybe 4K or so long, made of lots of small packets
+    // Since we don't know where the packet boundaries will be, we have to assume that
+    // any 'packet' larger than the max packet size of the ep is, in fact, a conglomeration
+    // of smaller packets. However, for the purposes of the packet count, this is still regarded
+    // as a single packet and the packet count only decremented when it is consumed.
+    // As before, if the user fails to read an entire packet out then the next packet is moved onto anyway
+    // To be safe the user must always supply a buffer of at least max packet size bytes.
+    if (thisPacketSz > iMaxPacketSize)
+        {
+        // Multiple packets left in buffer
+        // calculate number of bytes to end of packet
+        if (iEndpointType == UsbShai::KUsbEpTypeBulk)
+            {
+            thisPacketSz = iMaxPacketSize - (iExtractOffset & (iMaxPacketSize - 1));
+            }
+        else
+            {
+            thisPacketSz = iMaxPacketSize - (iExtractOffset % iMaxPacketSize);
+            }
+        errorCode = KErrNone;
+        }
+    else
+        {
+        errorCode = GetCurrentError();                        // single packet left
+        }
+
+    iExtractOffset += thisPacketSz;            // iExtractOffset is now at the end of the real or notional packet
+
+    ModifyTotalRxBytesAvail(-thisPacketSz);
+#if defined(USBC_LDD_BUFFER_TRACE)
+    iNumberofBytesRxRemain[iCurrentDrainingBufferIndex] -= thisPacketSz;
+#endif
+    // this can only be untrue if the "packet" is a conglomeration of smaller packets:
+    if (iExtractOffset == packetSz)
+        {
+        // packet consumed, advance to next packet in buffer
+#if defined(USBC_LDD_BUFFER_TRACE)
+        iNumberofPacketsRxRemain[iCurrentDrainingBufferIndex] -= 1;
+#endif
+        AdvancePacket();
+        }
+
+    TPtrC8 des(logicalSrc, thisPacketSz);
+    TInt r=Kern::ThreadBufWrite(aThread, aTcb, des, 0, 0, aThread);
+    if (r == KErrNone)
+        {
+        r = errorCode;
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxCopyPacketToClient 3"));
+
+    FreeDrainedBuffers();
+
+    // Use this error code to complete client read request:
+    return r;
+    }
+
+
+TInt TDmaBuf::RxCopyDataToClient(DThread* aThread, TClientBuffer *aTcb, TInt aLength, TUint32& aDestOffset,
+                                 TBool aRUS, TBool& aCompleteNow)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxCopyDataToClient 1"));
+    aCompleteNow = ETrue;
+
+#if defined(USBC_LDD_BUFFER_TRACE)
+    const TInt numPkts = NoRxPackets();
+    const TInt numPktsAlt = NoRxPacketsAlt();
+    const TInt numBytes = RxBytesAvailable();
+    const TInt numBytesAlt = NoRxBytesAlt();
+
+    if (numPkts != numPktsAlt)
+        {
+        Kern::Printf(
+            "TDmaBuf::RxCopyDataToClient: Error: #pkts mismatch global=%d actual=%d",
+            numPkts, numPktsAlt);
+        }
+    if (numBytes != numBytesAlt)
+        {
+        Kern::Printf(
+            "TDmaBuf::RxCopyDataToClient: Error: #bytes mismatch global=%d actual=%d",
+            numBytes, numBytesAlt);
+        }
+    if ((numPkts == 0) && (numBytes != 0))
+        {
+        Kern::Printf(
+            "TDmaBuf::RxCopyDataToClient: Error: global bytes & pkts mismatch pkts=%d bytes=%d",
+            numPkts, numBytes);
+        }
+    if ((numPktsAlt == 0) && (numBytesAlt != 0))
+        {
+        Kern::Printf(
+            "TDmaBuf::RxCopyDataToClient: Error: actual bytes & pkts mismatch pkts=%d bytes=%d",
+            numPktsAlt, numBytesAlt);
+        }
+#endif
+
+    if (!NoRxPackets())
+        {
+        return KErrNotFound;
+        }
+
+    // coverity[var_tested_neg]
+    if (iCurrentDrainingBufferIndex == KUsbcInvalidBufferIndex)
+        {
+        // Marked as Coverity "Inentional" as the member variable
+        // iCurrentDrainingBufferIndex is attentionaly negative, from previous 
+        // initialization to KUsbcInvalidBufferIndex (which equals -1).
+
+        if (!NextDrainableBuffer())
+            {
+#if defined(USBC_LDD_BUFFER_TRACE)
+            Kern::Printf("TDmaBuf::RxCopyDataToClient: Error:  No buffer draining=%d, packets=%d",
+                         iCurrentDrainingBufferIndex, iTotalRxPacketsAvail);
+#endif
+            return KErrNotFound;
+            }
+        }
+#if defined(USBC_LDD_BUFFER_TRACE)
+
+    __ASSERT_DEBUG((iCurrentDrainingBufferIndex >= 0 ),
+                               Kern::Fault(KUsbPanicLdd, __LINE__));
+        
+    if (iDrainingOrder != iFillingOrderArray[iCurrentDrainingBufferIndex])
+        {
+        Kern::Printf("!!! Out of Order Draining TDmaBuf::RxCopyDataToClient 10 draining=%d",
+                     iCurrentDrainingBufferIndex);
+        }
+#endif
+    __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxCopyDataToClient 2"));
+
+    TUint8* blockStartAddr = iCurrentDrainingBuffer + iCurrentPacketIndexArray[iCurrentPacket] + iExtractOffset;
+    TUint8* lastEndAddr = blockStartAddr;                    // going to track the contiguity of the memory
+    TUint8* thisStartAddr = blockStartAddr;
+    TInt toDo = Min(aLength - (TInt)aDestOffset, iTotalRxBytesAvail);
+#if defined(USBC_LDD_BUFFER_TRACE)
+    TInt bufnum = iCurrentDrainingBufferIndex;
+#endif
+    TInt errorCode = KErrNone;
+    TBool isShortPacket = EFalse;
+    const TInt maxPacketSizeMask = iMaxPacketSize - 1;
+    do
+        {
+#if defined(USBC_LDD_BUFFER_TRACE)
+        if (bufnum != iCurrentDrainingBufferIndex)
+            {
+            bufnum = iCurrentDrainingBufferIndex;
+            if (iDrainingOrder != iFillingOrderArray[iCurrentDrainingBufferIndex])
+                {
+                Kern::Printf("!!! Out of Order Draining TDmaBuf::RxCopyDataToClient 20 draining=%d",
+                             iCurrentDrainingBufferIndex);
+                }
+            }
+#endif
+        if (errorCode == KErrNone)
+            {
+            errorCode = GetCurrentError();
+            }
+        thisStartAddr = iCurrentDrainingBuffer + iCurrentPacketIndexArray[iCurrentPacket] + iExtractOffset;
+        const TInt thisPacketSize = iCurrentPacketSizeArray[iCurrentPacket];
+        const TInt size = thisPacketSize - iExtractOffset;
+        if (aRUS)
+            {
+            if (iEndpointType == UsbShai::KUsbEpTypeBulk)
+                {
+                isShortPacket = (size < iMaxPacketSize) || (size & maxPacketSizeMask);
+                }
+            else
+                {
+                // this 'if' block is arranged to avoid a division on packet sizes <= iMaxPacketSize
+                isShortPacket = (size < iMaxPacketSize) ||
+                    ((size > iMaxPacketSize) && (size % iMaxPacketSize));
+                }
+            }
+        TInt copySize = Min(size, toDo);
+        iExtractOffset += copySize;
+        toDo -= copySize;
+        if (thisStartAddr != lastEndAddr)
+            {
+            TInt bytesToCopy = lastEndAddr - blockStartAddr;
+            TInt r=CopyToUser(aThread, blockStartAddr, bytesToCopy, aTcb, aDestOffset);
+            if(r != KErrNone)
+                Kern::ThreadKill(aThread, EExitPanic, r, KUsbLDDKillCat);
+            blockStartAddr = thisStartAddr;
+            }
+
+        ModifyTotalRxBytesAvail(-copySize);
+#if defined(USBC_LDD_BUFFER_TRACE)
+        iNumberofBytesRxRemain[iCurrentDrainingBufferIndex] -= copySize;
+#endif
+        lastEndAddr = thisStartAddr + copySize;
+        if (iExtractOffset == thisPacketSize)
+            {
+            // More data to copy, so need to access new packet
+#if defined(USBC_LDD_BUFFER_TRACE)
+            iNumberofPacketsRxRemain[iCurrentDrainingBufferIndex] -= 1;
+#endif
+            if (!AdvancePacket())
+                {
+                break;                                        // no more packets left
+                }
+            }
+        } while (toDo > 0 && !isShortPacket);
+
+    if (thisStartAddr != lastEndAddr)
+        {
+        TInt bytesToCopy = lastEndAddr - blockStartAddr;
+        TInt r=CopyToUser(aThread, blockStartAddr, bytesToCopy, aTcb, aDestOffset);
+        if(r != KErrNone)
+            Kern::ThreadKill(aThread, EExitPanic, r, KUsbLDDKillCat);
+        }
+
+    // If we have transferred the requested amount of data it is still possible that
+    // the next packet is a zlp which needs to be bumped over
+
+    if (aRUS && (toDo == 0) && (iExtractOffset == 0) && (!isShortPacket) && (!IsReaderEmpty()) &&
+        (PeekNextPacketSize() == 0))
+        {
+        // swallow a zlp
+        isShortPacket = ETrue;
+#if defined(USBC_LDD_BUFFER_TRACE)
+        iNumberofPacketsRxRemain[iCurrentDrainingBufferIndex] -= 1;
+#endif
+        AdvancePacket();
+        }
+    aCompleteNow = isShortPacket || (((TInt)aDestOffset) == aLength) || (errorCode != KErrNone);
+
+    FreeDrainedBuffers();
+
+    // Use this error code to complete client read request
+    return errorCode;
+    }
+
+
+inline TInt TDmaBuf::CopyToUser(DThread* aThread, const TUint8* aSourceAddr,
+                                TInt aLength, TClientBuffer *aTcb, TUint32& aDestOffset)
+    {
+    TPtrC8 des(aSourceAddr, aLength);
+    TInt errorCode = Kern::ThreadBufWrite(aThread, aTcb, des, aDestOffset, KChunkShiftBy0, aThread);
+    if (errorCode == KErrNone)
+        {
+        aDestOffset += aLength;
+        }
+    return errorCode;
+    }
+
+
+inline TInt TDmaBuf::NoRxPackets() const
+    {
+    return iTotalRxPacketsAvail;
+    }
+
+
+inline void TDmaBuf::IncrementBufferIndex(TInt& aIndex)
+    {
+    if (++aIndex == iNumberofBuffers)
+        aIndex = 0;
+    }
+
+
+TBool TDmaBuf::NextDrainableBuffer()
+    {
+    TBool r = EFalse;
+    if (iCurrentDrainingBufferIndex != KUsbcInvalidBufferIndex)
+        {
+        iCanBeFreed[iCurrentDrainingBufferIndex] = ETrue;
+        iNumberofPacketsRx[iCurrentDrainingBufferIndex] = 0; // Current buffer is empty
+        iNumberofBytesRx[iCurrentDrainingBufferIndex] = 0;    // Current buffer is empty
+
+#if defined(USBC_LDD_BUFFER_TRACE)
+        TUint& bytesRemain = iNumberofBytesRxRemain[iCurrentDrainingBufferIndex];
+        TUint& pktsRemain = iNumberofPacketsRxRemain[iCurrentDrainingBufferIndex];
+        if ((bytesRemain != 0) || (pktsRemain != 0))
+            {
+            Kern::Printf(
+                "TDmaBuf::NextDrainableBuffer: Error: data discarded buffer=%d pkts=%d bytes=%d",
+                iCurrentDrainingBufferIndex, pktsRemain, bytesRemain);
+            bytesRemain = 0;
+            pktsRemain = 0;
+            }
+#endif
+
+        iCurrentDrainingBufferIndex = KUsbcInvalidBufferIndex;
+        iCurrentPacket = KUsbcInvalidPacketIndex;
+        }
+
+    if (iDrainQueueIndex != KUsbcInvalidDrainQueueIndex)
+        {
+        r = ETrue;
+        const TInt index = iDrainQueue[0];
+        iDrainQueueIndex--;
+        for (TInt i = 0; i < iNumberofBuffers; i++)
+            {
+            iDrainQueue[i] = iDrainQueue[i+1];
+            }
+
+#if defined(USBC_LDD_BUFFER_TRACE)
+        if (index != KUsbcInvalidBufferIndex)
+            iDrainingOrder++;
+#endif
+
+        iCurrentDrainingBufferIndex = index;
+        iCurrentDrainingBuffer = iBuffers[index];
+        iCurrentPacketIndexArray = iPacketIndex[index];
+        iCurrentPacketSizeArray = iPacketSize[index];
+        iCurrentPacket = 0;
+        }
+    return r;
+    }
+
+
+TInt TDmaBuf::PeekNextDrainableBuffer()
+    {
+    TInt r = KUsbcInvalidBufferIndex;
+    if (iDrainQueueIndex != KUsbcInvalidDrainQueueIndex)
+        {
+        r = iDrainQueue[0];
+        }
+    return r;
+    }
+
+
+TBool TDmaBuf::NextFillableBuffer()
+    {
+    TBool r = EFalse;
+    TInt index = iCurrentFillingBufferIndex;
+    IncrementBufferIndex(index);
+    // the sequence will restart at 0 if a buffer can't be found this time
+    iCurrentFillingBufferIndex = 0;
+    for (TInt i = 0; i < iNumberofBuffers; i++)
+        {
+        if (!iDrainable[index])
+            {
+            iCurrentFillingBufferIndex = index;
+            r = ETrue;
+            break;
+            }
+        IncrementBufferIndex(index);
+        }
+    return r;
+    }
+
+
+void TDmaBuf::FreeDrainedBuffers()
+    {
+    for (TInt i = 0; i < iNumberofBuffers; i++)
+        {
+        if (iDrainable[i] && iCanBeFreed[i])
+            {
+            iDrainable[i] = iCanBeFreed[i] = EFalse;
+            }
+        }
+    }
+
+
+TBool TDmaBuf::ShortPacketExists()
+    {
+    // Actually, a short packet or residue data
+    __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::ShortPacketExists 1"));
+    TInt index = iCurrentDrainingBufferIndex;
+    TUsbcPacketArray* pktSizeArray = iCurrentPacketSizeArray;
+
+    if (iMaxPacketSize > 0)
+        {
+        // No buffers available for draining
+        if ((iCurrentDrainingBufferIndex == KUsbcInvalidBufferIndex) ||
+            (iCurrentPacket == KUsbcInvalidPacketIndex))
+            return EFalse;
+
+        // Zlp waiting at tail
+        if ((iTotalRxBytesAvail == 0) && (NoRxPackets() == 1))
+            return ETrue;
+
+        if (iEndpointType == UsbShai::KUsbEpTypeBulk)
+            {
+            const TInt mask = iMaxPacketSize - 1;
+            if (iTotalRxBytesAvail & mask)
+                return ETrue;
+
+            // residue==0; this can be because
+            // zlps exist, or short packets combine to n * max_packet_size
+            // This means spadework
+            const TInt s = iCurrentPacketSizeArray[iCurrentPacket] - iExtractOffset;
+            if ((s == 0) || (s & mask))
+                {
+                return ETrue;
+                }
+
+            for (TInt i = 0; i < iNumberofBuffers; i++)
+                {
+                if (index == KUsbcInvalidBufferIndex)
+                    break;
+                if (iDrainable[index])
+                    {
+                    const TInt packetCount = iNumberofPacketsRx[index];
+                    const TInt lastPacketSize=pktSizeArray[packetCount - 1];
+                    if ((lastPacketSize < iMaxPacketSize) || (lastPacketSize & mask))
+                        {
+                        return ETrue;
+                        }
+                    }
+                index = iDrainQueue[i];
+                pktSizeArray = iPacketSize[index];
+                }
+            }
+        else
+            {
+            if (iTotalRxBytesAvail % iMaxPacketSize)
+                return ETrue;
+
+            // residue==0; this can be because
+            // zlps exist, or short packets combine to n * max_packet_size
+            // This means spadework
+            const TInt s = iCurrentPacketSizeArray[iCurrentPacket] - iExtractOffset;
+            if ((s == 0) || (s % iMaxPacketSize))
+                {
+                return ETrue;
+                }
+
+            for (TInt i = 0; i < iNumberofBuffers; i++)
+                {
+                if (index == KUsbcInvalidBufferIndex)
+                    break;
+                if (iDrainable[index])
+                    {
+                    const TInt packetCount = iNumberofPacketsRx[index];
+                    const TInt lastPacketSize = pktSizeArray[packetCount - 1];
+                    if ((lastPacketSize < iMaxPacketSize) || (lastPacketSize % iMaxPacketSize))
+                        {
+                        return ETrue;
+                        }
+                    }
+                index = iDrainQueue[i];
+                pktSizeArray = iPacketSize[index];
+                }
+            }
+        }
+
+    return EFalse;
+    }
+
+
+void TDmaBuf::AddToDrainQueue(TInt aBufferIndex)
+    {
+    if (iDrainQueue[iDrainQueueIndex + 1] != KUsbcInvalidBufferIndex)
+        {
+#if defined(USBC_LDD_BUFFER_TRACE)
+        Kern::Printf("TDmaBuf::AddToDrainQueue: Error: invalid iDrainQueue[x]");
+#endif
+        }
+    iDrainQueue[++iDrainQueueIndex] = aBufferIndex;
+    }
+
+
+#if defined(USBC_LDD_BUFFER_TRACE)
+TInt TDmaBuf::NoRxPacketsAlt() const
+    {
+    TInt pktCount = 0;
+    for(TInt i = 0; i < iNumberofBuffers; i++)
+        {
+        if (iDrainable[i])
+            {
+            pktCount += iNumberofPacketsRxRemain[i];
+            }
+        }
+    return pktCount;
+    }
+
+
+TInt TDmaBuf::NoRxBytesAlt() const
+    {
+    TInt byteCount = 0;
+    for(TInt i = 0; i < iNumberofBuffers; i++)
+        {
+        if (iDrainable[i])
+            {
+            byteCount += iNumberofBytesRxRemain[i];
+            }
+        }
+    return byteCount;
+    }
+#endif
+
+
+// We only store 1 transaction, no other buffering is done
+TInt TDmaBuf::TxStoreData(DThread* aThread, TClientBuffer *aTcb, TInt aTxLength, TUint32 aBufferOffset)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::TxStoreData 1"));
+    if (!IsReaderEmpty())
+        return KErrInUse;
+
+    __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::TxStoreData 2"));
+    
+    TInt remainTxLength = aTxLength;
+    TUint32 bufferOffset = aBufferOffset;
+    // Store each buffer separately
+    for( TInt i=0;(i<iNumberofBuffers)&&(remainTxLength>0);i++)
+        {
+        TUint8* logicalDest = iBuffers[i];
+        TInt xferSz = Min(remainTxLength, iBufSz);
+        TPtr8 des(logicalDest, xferSz, xferSz);
+        TInt r = Kern::ThreadBufRead(aThread, aTcb, des, bufferOffset, KChunkShiftBy0);
+        if(r != KErrNone)
+            {
+            Kern::ThreadKill(aThread, EExitPanic, r, KUsbLDDKillCat);
+            return r;
+            }
+        remainTxLength -= iBufSz;
+        bufferOffset += iBufSz;
+        }
+
+    return KErrNone;
+    }
+
+
+TInt TDmaBuf::TxGetNextXfer(TUint8*& aBufferAddr, TInt& aTxLength, TPhysAddr& aBufferPhys)
+    {
+    if (iTxActive)
+        return KErrInUse;
+
+    aBufferAddr = iBuffers[0];                                // only 1 tx buffer
+    aBufferPhys = iBufferPhys[0];
+    aTxLength = BufferTotalSize();
+
+    return KErrNone;
+    }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/ldd/perilddsc/appifwrapper/eabi/usbcscu.def	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,23 @@
+EXPORTS
+	_ZN15TEndpointBuffer11WriteBufferEPvjiR14TRequestStatus @ 1 NONAME
+	_ZN15TEndpointBuffer11WriteBufferEjjiR14TRequestStatus @ 2 NONAME
+	_ZN15TEndpointBuffer16GetInBufferRangeERPvRj @ 3 NONAME
+	_ZN15TEndpointBuffer16GetInBufferRangeERjS0_ @ 4 NONAME
+	_ZN15TEndpointBuffer5CloseEv @ 5 NONAME
+	_ZN15TEndpointBuffer9GetBufferERPvRjRiR14TRequestStatusj @ 6 NONAME
+	_ZN15TEndpointBufferC1Ev @ 7 NONAME
+	_ZN15TEndpointBufferC2Ev @ 8 NONAME
+	_ZN16RDevUsbcScClient12OpenEndpointER15TEndpointBufferi @ 9 NONAME
+	_ZN16RDevUsbcScClient17FinalizeInterfaceERP6RChunk @ 10 NONAME
+	_ZN16RDevUsbcScClient17FinalizeInterfaceEv @ 11 NONAME
+	_ZN16RDevUsbcScClient20GetDataTransferChunkERP6RChunk @ 12 NONAME
+	_ZN16RDevUsbcScClient28StartNextOutAlternateSettingEi @ 13 NONAME
+	_ZN18TUsbcScChunkHeader20GetNumberOfEndpointsEi @ 14 NONAME
+	_ZN18TUsbcScChunkHeader9GetBufferEiiRP24TUsbcScHdrEndpointRecord @ 15 NONAME
+	_ZN18TUsbcScChunkHeaderC1E6RChunk @ 16 NONAME
+	_ZN18TUsbcScChunkHeaderC2E6RChunk @ 17 NONAME
+	_ZN15TEndpointBuffer4DumpEv @ 18 NONAME
+	_ZN15TEndpointBuffer10TakeBufferERPvRjRiR14TRequestStatusj @ 19 NONAME
+	_ZN15TEndpointBuffer6ExpireEv @ 20 NONAME
+	_ZN15TEndpointBuffer6ExpireEPv @ 21 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/ldd/perilddsc/appifwrapper/group/bld.inf	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,39 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// bld.inf
+// USB Client Driver
+// 
+//
+
+/**
+ @file
+*/
+PRJ_PLATFORMS
+
+BASEDEFAULT
+
+PRJ_MMPFILES
+
+#if defined(GENERIC_MARM) || defined(WINS) || defined(GENERIC_X86)
+#if !defined(MARM_THUMB) && !defined(MARM_ARMI)
+
+#if !defined(WINS) 
+#if !defined(X86)
+usbcsc_bil
+#endif
+#endif
+
+
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/ldd/perilddsc/appifwrapper/group/usbcsc_bil.mmp	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,31 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32/drivers/usbcsc/usbcsc_bil.mmp
+// 
+//
+USERINCLUDE    ../../include
+
+OS_LAYER_SYSTEMINCLUDE
+
+target            usbcsc_bilshai.dll
+targettype        dll
+sourcepath        ../src
+source            usbcsc_bil.cpp
+
+library           euser.lib
+
+deffile           ../~/usbcsc.def 
+
+VENDORID        0x70000001
+capability        all
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/ldd/perilddsc/appifwrapper/src/usbcsc_bil.cpp	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,633 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\drivers\usbcsc\usbcsc_bil.cpp
+// 
+//
+
+#include <e32std.h>
+#include <e32std_private.h>
+#include <usb/d32usbcsc.h>
+#include <e32debug.h>
+
+/** @file usbcsc_bil.cpp
+
+	Buffer Interface Layer for USB Client Device driver stack, using shared chunks.
+
+	@internalTechnology
+*/
+
+EXPORT_C TInt RDevUsbcScClient::FinalizeInterface()
+	{
+	TInt errorOrhandle = DoControl(EControlRealizeInterface); //returns a error value or chunk handle
+	TInt r = iSharedChunk.SetReturnedHandle(errorOrhandle);
+	iEndpointStatus = 0x00; //all endpoints are closed at the moment
+	iAlternateSetting = 0;
+	iNewAltSetting = 0;
+	iAltSettingSeq = 0;
+	return r;
+	}
+
+
+EXPORT_C TInt RDevUsbcScClient::FinalizeInterface(RChunk*& aChunk)
+	{
+	TInt errorOrhandle = DoControl(EControlRealizeInterface);
+	iSharedChunk.SetReturnedHandle(errorOrhandle);
+	iEndpointStatus = 0x00; //all endpoints are closed at the moment
+	iAlternateSetting = 0;
+	return aChunk->SetReturnedHandle(errorOrhandle);
+	}
+
+
+EXPORT_C TInt RDevUsbcScClient::OpenEndpoint(TEndpointBuffer& aEpB, TInt aEpI)
+	{
+	TUsbcScHdrEndpointRecord* endpointInf = NULL;
+	TBuf8<KUsbDescSize_Endpoint> descriptor;
+	TUsbcScChunkHeader chunkHeader(iSharedChunk);
+	//Do some validity checks
+	if((aEpB.iInState != TEndpointBuffer::ENotValid) && (aEpB.iOutState != TEndpointBuffer::ENotValid))
+		return KErrArgument;
+
+	TInt nEndpoints = chunkHeader.GetNumberOfEndpoints(iAlternateSetting);	
+	if ((aEpI < KEp0Number) && (aEpI > nEndpoints)) // Check endpoint number range 
+		return KErrNotFound;
+
+	if(iEndpointStatus & (1 << aEpI)) // Check that endpoint isn't already opene
+		return KErrInUse;
+
+	if(aEpI == KEp0Number) //endpoint 0
+		{
+		TUsbcScHdrEndpointRecord ep0=  TUsbcScHdrEndpointRecord(KUsbcScEndpointZero, KUsbScHdrEpDirectionBiDir | KUsbScHdrEpTypeControl);
+		aEpB.Construct(this,iSharedChunk.Base(), &ep0 ,aEpI, 
+		(SUsbcScBufferHeader*) ((TUint)iSharedChunk.Base() + (chunkHeader.iBuffers)->Ep0Out()->Offset()));
+
+		aEpB.iBufferStartAddr = (TUint8*) ((TUint)iSharedChunk.Base() + (chunkHeader.iBuffers)->Ep0In()->Offset());
+		aEpB.iSize = chunkHeader.iBuffers->Ep0In()->Size();
+		}
+	else  // If normal endpoint (!ep0)
+		{
+		TUsbcScBufferRecord* buf = 	chunkHeader.GetBuffer(iAlternateSetting,aEpI,endpointInf);
+		if (!buf)
+			return KErrGeneral;
+		// Set up endpoint members
+		aEpB.iBufferStartAddr = (TUint8*)  (buf->Offset() + (TUint)iSharedChunk.Base());
+		aEpB.iSize = buf->Size();
+		TInt r = GetEndpointDescriptor(iAlternateSetting, aEpI, descriptor);
+		if(r != KErrNone) // We need this to be able to calculate alignment
+			{
+			return r;
+			}
+
+		if (endpointInf->Direction()&KUsbScHdrEpDirectionIn)
+			{  							//in case of IN endpoints, first endpoint buffer location points to end offset
+			aEpB.Construct(this,iSharedChunk.Base(),endpointInf,aEpI);
+			if (iInAltSetting==KErrEof)
+			aEpB.iInState=TEndpointBuffer::EEOF;
+
+			}
+		else
+			{
+			SUsbcScBufferHeader *endpointHdr = (SUsbcScBufferHeader *) aEpB.iBufferStartAddr;
+			//In this case,SUsbcScBufferHeader points to full OUT endpoint header 
+			aEpB.Construct(this,iSharedChunk.Base(),endpointInf,aEpI, endpointHdr);
+			}
+		}
+	iEndpointStatus |= (1 << aEpI);	
+
+#ifdef _DEBUG
+	aEpB.Dump();
+	RDebug::Printf("iEndpointStatus: %x \n",iEndpointStatus);
+#endif
+	return KErrNone;
+	}
+
+
+//Internal, used by RDevUsbcScClient::StartNextOutAlternateSetting(...)
+//This drains any old data from an OUT buffer, and gets it ready for reading an ep.
+//aBufferOffset - The offset, into the chunk, that the buffer in question, may be found.
+ 
+TInt RDevUsbcScClient::Drain(TUint aBufferOffset)
+{
+	TUint8* base = iSharedChunk.Base();
+	SUsbcScBufferHeader* endpointHdr = (SUsbcScBufferHeader*) (aBufferOffset+base);
+	TUint localTail = endpointHdr->iBilTail;
+	TUsbcScTransferHeader* currentTransfer;
+	TUint16 next = (iAltSettingSeq+1)&0xFFFF;
+	TInt err=KErrNone;
+
+	while (ETrue)
+		{
+		if (localTail == (TUint) endpointHdr->iHead)
+			{
+			err = KErrNotReady;
+			break;
+			}
+		currentTransfer = (TUsbcScTransferHeader*) (base + localTail);
+
+		if (currentTransfer->iAltSettingSeq == next)
+			{
+			iNewAltSetting=currentTransfer->iAltSetting; // record new alt setting
+			break;
+			}
+		else
+			{
+			localTail = currentTransfer->iNext;
+			}
+		} // end while
+	endpointHdr->iBilTail = localTail;
+	endpointHdr->iTail = localTail;
+	return err;
+}
+
+//Internal, used by RDevUsbcScClient::StartNextOutAlternateSetting(...)
+//This method checks that the OUT buffer is ready for reading an ep.
+//aBufferOffset - The offset, into the chunk, that the buffer in question, may be found.
+
+TInt RDevUsbcScClient::Peek(TUint aBufferOffset)
+{
+	TUint8* base = iSharedChunk.Base();
+	SUsbcScBufferHeader* endpointHdr = (SUsbcScBufferHeader*) (aBufferOffset+base);
+	TUint localTail = endpointHdr->iBilTail;
+	TUsbcScTransferHeader* currentTransfer = (TUsbcScTransferHeader*) (base + localTail);
+
+	if ((localTail == (TUint)endpointHdr->iHead) || (currentTransfer->iAltSettingSeq != (iAltSettingSeq+1)&0xFFFF))
+		// if alternate setting has not changed
+		return KErrNotReady;
+	else
+		{
+		iNewAltSetting=currentTransfer->iAltSetting;
+		return KErrNone;
+		}
+}
+
+//Internal, used by RDevUsbcScClient::StartNextOutAlternateSetting(...)
+//This method is called if an alternate setting change happens from a set of ONLY IN endpoints.
+//Used to find the least possible alternate setting it can return to the user, stored in iNewAltSetting
+//Returns the sequence number of the 'latest' alternate setting it can switch to
+
+TInt RDevUsbcScClient::FindNextAlternateSetting()
+	{
+	TUsbcScChunkHeader chunkHeader(iSharedChunk);
+	TUsbcScHdrEndpointRecord* endpointInf = NULL;
+	TUint bufOff;
+	TInt altSet;
+	TInt ep;
+	TInt bufNum;
+
+	RArray <TInt> bufferOffset;	// Array to contain all OUT enpoint buffer offsets
+	// Populate array
+	for (altSet = 0; altSet < chunkHeader.iAltSettings->iNumOfAltSettings ; altSet++)
+		{
+		TInt numEndpoints = chunkHeader.GetNumberOfEndpoints(altSet);
+		for (ep =  1; ep  <= numEndpoints ; ep ++)
+			{
+			bufOff = chunkHeader.GetBuffer(altSet, ep, endpointInf)->Offset();	
+			if ((endpointInf->Direction() & KUsbScHdrEpDirectionOut) && (bufferOffset.Find(bufOff) == KErrNotFound))
+				{
+				bufferOffset.Append(bufOff);
+				}
+			}
+		}
+
+	TInt err = KErrNotFound;
+	TUint16 altSetSeqDelta = 0;
+	TUint16 currentaltSetSeqDelta = 0;
+	TBool noNewSettingFound = ETrue;
+	TInt altSetSeq = iAltSettingSeq;
+	TUint8* base = iSharedChunk.Base();
+
+	for (bufNum = 0; bufNum < bufferOffset.Count(); bufNum++) // Scan all OUT buffers
+		{	
+		SUsbcScBufferHeader* endpointHdr = (SUsbcScBufferHeader*) (bufferOffset[bufNum] + base);
+		TUint localTail = endpointHdr->iBilTail;
+		TUsbcScTransferHeader* currentTransfer;
+		TUint16 next = (iAltSettingSeq+1)&0xFFFF;
+		
+		while (ETrue)
+			{
+			if (localTail == (TUint) endpointHdr->iHead)
+				{
+				break;	// This OUT endpoint buffer has no data, proceed checking with other OUT endpoint buffers
+				}
+			currentTransfer = (TUsbcScTransferHeader*) (base + localTail);
+
+			if (currentTransfer->iAltSettingSeq != iAltSettingSeq) 
+				{
+				if (currentTransfer->iAltSettingSeq == next)
+					{
+					altSetSeq = currentTransfer->iAltSettingSeq;
+					iNewAltSetting = currentTransfer->iAltSetting; // record new alt setting
+					err = KErrNone;
+					break;
+					}
+
+				if (noNewSettingFound)
+					{
+					altSetSeqDelta = Abs(iAltSettingSeq - currentTransfer->iAltSettingSeq);
+					altSetSeq = currentTransfer->iAltSettingSeq;
+					iNewAltSetting = currentTransfer->iAltSetting; // record new alt setting
+					noNewSettingFound = EFalse;
+					}
+				else
+					{
+					currentaltSetSeqDelta = Abs(iAltSettingSeq - currentTransfer->iAltSettingSeq);
+					if (currentaltSetSeqDelta < altSetSeqDelta)
+						{
+						altSetSeqDelta = currentaltSetSeqDelta;
+						altSetSeq = currentTransfer->iAltSettingSeq;
+						iNewAltSetting = currentTransfer->iAltSetting;
+						}
+					}
+				break;
+				}
+			
+			localTail = currentTransfer->iNext;
+			} // end while
+
+		if (!err) // Found an alt set sequence one after iAltSettingSeq
+			{
+			break; // found 'the next' alternate setting, exit for loop
+			}
+		
+		}// for loop
+
+	return altSetSeq;
+	}
+
+EXPORT_C TInt RDevUsbcScClient::StartNextOutAlternateSetting(TBool aFlush)
+	{
+	TUsbcScChunkHeader chunkHeader(iSharedChunk);
+	
+	//if endpoints are still open, return KErrInUse 
+	if((iEndpointStatus&~1) != 0)
+		{
+		return KErrInUse;
+		}
+
+	TInt r;
+	TInt ep;
+	TInt noEp;
+	TUint bufOff;
+	TBool inEndpointSet = ETrue;
+	TUsbcScHdrEndpointRecord* endpointInf = NULL;
+
+	// check if alternate setting contains all IN endpoints
+	noEp = chunkHeader.GetNumberOfEndpoints(iAlternateSetting);
+
+	// for each used buffer. 
+	for (ep=1;ep<=noEp;ep++)
+		{
+		bufOff = chunkHeader.GetBuffer(iAlternateSetting,ep,endpointInf)->Offset();	
+	
+		if (endpointInf->Direction() & KUsbScHdrEpDirectionOut) 
+			{
+			inEndpointSet = EFalse;
+			if (aFlush)
+				r = Drain(bufOff); // we need to remove anythng in the way, and get it ready for reading.
+			else
+				r = Peek(bufOff); // we need to check it is ready for reading!
+			if (r) 
+				return r;
+			}
+		}
+
+
+	TInt altSeq = 0;
+	if (inEndpointSet)	// If all endpoints in the current alternate setting are IN endpoints
+		{	// go through all OUT buffers for alternate setting change
+		altSeq = FindNextAlternateSetting();
+		}
+
+	if((iNewAltSetting == iAlternateSetting) && (!inEndpointSet))
+			{
+			return KErrNotReady;
+			}
+
+	// Find/Set IN alternate setting
+	TInt ret = StartNextInAlternateSetting();
+	SUsbcScAlternateSetting* altrec = ((SUsbcScAlternateSetting*) (&ret));
+
+	if (altrec->iSequence==iAltSettingSeq+1)
+		{
+		if (altrec->iSetting!=iNewAltSetting)
+			return KErrGeneral;
+		iInAltSetting=iNewAltSetting;
+		}
+	else
+		{
+		if (inEndpointSet)
+			{
+			if ((altSeq == iAltSettingSeq) || (iAltSettingSeq == altrec->iSequence))
+				{
+				return KErrNotReady;
+				}
+			else if (altSeq != altrec->iSequence)
+				{
+				iInAltSetting=KErrEof;
+				}
+			}
+		iInAltSetting=KErrEof;
+		}
+
+	iAlternateSetting = iNewAltSetting;
+	iAltSettingSeq += 1;
+
+	return iAlternateSetting;
+	}
+
+
+EXPORT_C TInt RDevUsbcScClient::GetDataTransferChunk(RChunk* & aChunk)
+	{
+	aChunk = &iSharedChunk;
+	return KErrNone;
+	}
+
+// Constructor
+
+EXPORT_C TEndpointBuffer::TEndpointBuffer()
+		:iInState(ENotValid),
+		iOutState(ENotValid),
+		iEndpointNumber(-1),
+		iBufferNum(-1),
+		iBufferStartAddr(0),
+		iSize(0)
+	{
+	}
+
+// Internal, called by RDevUsbcScClient::OpenEndpoint.
+void TEndpointBuffer::Construct(RDevUsbcScClient* aClient, TUint8* aBaseAddr, const TUsbcScHdrEndpointRecord* aEpType , TInt aEndpointNumber,SUsbcScBufferHeader* aEndpointHdr)
+	{
+	iClient		= aClient;
+	iBaseAddr	= (TUint) aBaseAddr;
+	iInState 	= (((aEpType->Direction())&KUsbScHdrEpDirectionIn) ? EValid :  ENotValid);
+	iOutState	= (((aEpType->Direction())&KUsbScHdrEpDirectionOut) ? EValid :  ENotValid);
+	iBufferNum	= (aEpType->iBufferNo==(KUsbcScEndpointZero&0xFF))?KUsbcScEndpointZero:aEpType->iBufferNo;
+	iEndpointNumber = aEndpointNumber;
+
+	iEndpointHdr = aEndpointHdr;
+	};
+
+EXPORT_C TInt TEndpointBuffer::GetInBufferRange(TAny*& aStart, TUint& aSize)
+	{
+	if ((iInState))
+		{
+		return iInState;
+		}
+	aStart= iBufferStartAddr;
+	aSize= iSize;
+	return KErrNone;
+	};
+
+EXPORT_C TInt TEndpointBuffer::GetInBufferRange(TUint& aStart, TUint& aSize)
+	{
+	if ((iInState))
+		return iInState;
+	aStart=	(TUint) iBufferStartAddr - iBaseAddr;
+	aSize= iSize;
+	return KErrNone;
+	}
+
+
+EXPORT_C TInt TEndpointBuffer::GetBuffer(TAny*& aBuffer,TUint& aSize,TBool& aZLP,TRequestStatus& aStatus,TUint aLength)
+	{
+	if (iOutState)
+		return iOutState;
+
+	TUsbcScTransferHeader* currentTransfer;
+	TInt r;
+	do // until we have a transfer with data.
+		{
+		iEndpointHdr->iTail = iEndpointHdr->iBilTail; 
+		if(iEndpointHdr->iBilTail == iEndpointHdr->iHead)  //If no new data, create request
+			{
+			r = iClient->ReadDataNotify(iBufferNum,aStatus);
+			if (r!=KErrCompletion)  // Data could arrive since we checked.
+				return r;
+			}
+		currentTransfer = (TUsbcScTransferHeader*) (iBaseAddr + iEndpointHdr->iBilTail);
+
+		iEndpointHdr->iBilTail = currentTransfer->iNext;
+		aZLP = (currentTransfer->iFlags & KUsbcScShortPacket)!=EFalse;
+
+		if(currentTransfer->iAltSettingSeq != (iClient->iAltSettingSeq))  // if alternate setting has changed
+			{
+			if (currentTransfer->iAltSettingSeq == (iClient->iAltSettingSeq+1))	   //Note- KIS ATM, if multiple alternate setting changes happen
+				iClient->iNewAltSetting = currentTransfer->iAltSetting; //before StartNextOutAlternateSetting is called, 		   
+																	   //this variable will reflect the latest requested AlternateSetting
+
+
+			if (iEndpointNumber != KEp0Number)
+				{
+//				iOutState =  EEOF;	
+				return KErrEof;
+				}
+			else if ((currentTransfer->iBytes==0) && (!aZLP)) 
+				{
+				return KErrAlternateSettingChanged;
+				}
+			}						
+
+		}
+	while ((currentTransfer->iBytes==0) && (!aZLP)); // ignore empty transfers
+
+	aBuffer = currentTransfer->iData.i;
+	aSize = currentTransfer->iBytes;	
+	return (currentTransfer->iFlags & KUsbcScStateChange)?KStateChange:KErrCompletion;	
+	}
+
+EXPORT_C TInt TEndpointBuffer::TakeBuffer(TAny*& aBuffer,TUint& aSize,TBool& aZLP,TRequestStatus& aStatus,TUint aLength)
+	{
+	if (iOutState)
+		return iOutState;
+
+	TUsbcScTransferHeader* currentTransfer;
+	TInt r;
+	do // until we have a transfer with data.
+		{
+		if(iEndpointHdr->iBilTail == iEndpointHdr->iHead)  //If no new data, create request
+			{
+			r = iClient->ReadDataNotify(iBufferNum,aStatus);
+			if (r!=KErrCompletion)  // Data could arrive since we checked.
+				{
+				return r;
+				}
+			}
+
+		currentTransfer = (TUsbcScTransferHeader*) (iBaseAddr + iEndpointHdr->iBilTail);
+		iEndpointHdr->iBilTail = currentTransfer->iNext;
+		aZLP = (currentTransfer->iFlags & KUsbcScShortPacket)!=EFalse; // True if short packet else false 
+
+		if(currentTransfer->iAltSettingSeq != (iClient->iAltSettingSeq))  // if alternate setting has changed
+			{
+			if (currentTransfer->iAltSettingSeq == (iClient->iAltSettingSeq+1))	   //Note- KIS ATM, if multiple alternate setting changes happen
+				iClient->iNewAltSetting = currentTransfer->iAltSetting; //before StartNextOutAlternateSetting is called, 		   
+																	   //this variable will reflect the latest requested AlternateSetting
+			Expire(currentTransfer->iData.i);
+			if (iEndpointNumber != KEp0Number)
+				{
+//				iOutState = EEOF;
+				return KErrEof;
+				}
+			else if ((currentTransfer->iBytes==0) && (!aZLP)) 
+				{
+				return KErrAlternateSettingChanged;
+				}
+
+			}	
+
+		if ((currentTransfer->iBytes==0) && (!aZLP)) // here , if empty transfer with alt setting information, Call expire 
+			{
+			Expire(currentTransfer->iData.i);
+			}
+		}
+	while ((currentTransfer->iBytes==0) && (!aZLP)); // ignore empty transfers
+
+	aBuffer = currentTransfer->iData.i;
+	aSize = currentTransfer->iBytes;
+	return (currentTransfer->iFlags & KUsbcScStateChange)?KStateChange:KErrCompletion;	
+	}
+
+EXPORT_C TInt TEndpointBuffer::Expire()
+	{
+	if (!(iOutState != ENotValid))
+		return iOutState;
+
+	if (iEndpointHdr->iTail != iEndpointHdr->iBilTail)
+		{
+		TUsbcScTransferHeader* currentTransfer = (TUsbcScTransferHeader*) (iBaseAddr + iEndpointHdr->iTail);
+		iEndpointHdr->iTail = currentTransfer->iNext;
+		}
+	return KErrNone;
+	}
+
+EXPORT_C TInt TEndpointBuffer::Expire(TAny* aAddress)
+	{
+	if (!(iOutState != ENotValid))
+		return iOutState;
+
+	TUint headerSize = sizeof(TUsbcScTransferHeader)-4; // TransferHeader includes 4 bytes of data.
+	TInt transferToExpire = ((TUint) aAddress - headerSize);
+	TInt offsetToExpire = transferToExpire - iBaseAddr; 
+
+	TInt currentTail = iEndpointHdr->iTail;
+
+	TInt prevTail = NULL;
+	TBool found = EFalse;
+	while (currentTail != iEndpointHdr->iBilTail)
+		{
+		TUsbcScTransferHeader* currentTransfer = (TUsbcScTransferHeader*) (iBaseAddr + currentTail);
+		if (currentTail == offsetToExpire)		// found which to expire
+			{
+			found = ETrue;
+			// This offset is to be expired
+			if (prevTail == NULL)
+				{
+				// The offset is at the list head
+				iEndpointHdr->iTail = currentTransfer->iNext;	
+				}
+			else
+				{
+				// The offset is NOT at the list head
+				// This leaves a GAP in the buffer which will not be filled unless the 'transfers' before 'currentTail' are expired
+				currentTail = currentTransfer->iNext;
+				TUsbcScTransferHeader* prevTransfer = (TUsbcScTransferHeader*) (iBaseAddr + prevTail);
+				prevTransfer->iNext = currentTail;
+				}
+			break;
+			}
+		prevTail = currentTail;
+		currentTail = currentTransfer->iNext;
+		}
+	return found ? KErrNone : KErrNotFound;
+	}
+
+	
+EXPORT_C TInt TEndpointBuffer::WriteBuffer(TAny* aBuffer,TUint aSize,TBool aZLP,TRequestStatus& aStatus)
+	{
+	if (iInState)
+		return iInState;
+
+	iClient->WriteData(iBufferNum, ((TUint)aBuffer - (TUint)iBaseAddr),aSize,aZLP,aStatus);
+	return KErrNone;
+	}
+
+
+EXPORT_C TInt TEndpointBuffer::WriteBuffer(TUint aOffset,TUint aSize,TBool aZLP,TRequestStatus& aStatus)
+	{
+	if (iInState)
+		return iInState;
+
+	iClient->WriteData(iBufferNum,aOffset,aSize,aZLP,aStatus);
+	return KErrNone;
+	}
+
+
+/**
+Closes the endpoint buffer
+@return			KErrNone if close is successfull
+*/	
+EXPORT_C TInt TEndpointBuffer::Close()
+	{
+	if ((iInState == ENotValid) && (iOutState == ENotValid))
+		return KErrNotFound;
+	if (iOutState != ENotValid)
+		{
+		TUsbcScTransferHeader* currentTransfer = (TUsbcScTransferHeader*) (iBaseAddr + iEndpointHdr->iTail);
+		//Incase of AlternateSetting changes and using TEndpointBuffer::GetBuffer, iTail is always one 'transfer' behind iBilTail
+		//Incase of AlternateSetting changes and using TEndpointBuffer::TakeBuffer, this shuold force the user to update iTail & only then closes the endpoint buffer
+		if (((TInt) currentTransfer->iNext != iEndpointHdr->iBilTail) && (iEndpointHdr->iTail != iEndpointHdr->iBilTail))
+			return KErrNotReady;
+		}
+	iClient->iEndpointStatus &= ~(1 << iEndpointNumber); //reset the bit corresponding to endpoint
+	iInState = ENotValid;
+	iOutState = ENotValid;
+	return KErrNone;
+	}
+
+
+  
+EXPORT_C TUsbcScChunkHeader::TUsbcScChunkHeader(RChunk aChunk)
+	{
+	iChunk = aChunk;
+	iBuffers     = (TUsbcScChunkBuffersHeader*)    (aChunk.Base()+((TUsbcScChunkHdrOffs*)iChunk.Base())->iBuffers);
+	iAltSettings = (TUsbcScChunkAltSettingHeader*) (aChunk.Base()+((TUsbcScChunkHdrOffs*)iChunk.Base())->iAltSettings);
+	}
+
+EXPORT_C TInt TUsbcScChunkHeader::GetNumberOfEndpoints(TInt aAltSetting)
+	{
+	if ((aAltSetting<0) || (aAltSetting>=iAltSettings->iNumOfAltSettings))
+		return KErrArgument;
+	return  *((TInt*) (iAltSettings->iAltTableOffset[aAltSetting] + (TInt) iChunk.Base()));
+	}
+
+
+EXPORT_C TUsbcScBufferRecord* TUsbcScChunkHeader::GetBuffer(TInt aAltSetting, TInt aEndpoint, TUsbcScHdrEndpointRecord*& aEndpointInf)
+	{
+	if ((aAltSetting<0) || (aAltSetting>=iAltSettings->iNumOfAltSettings))
+		return NULL;
+	TInt8* iEndpoint = (TInt8*) (iAltSettings->iAltTableOffset[aAltSetting] + (TInt) iChunk.Base());
+	if ((aEndpoint<=0) || (aEndpoint>*iEndpoint))
+		return NULL;
+	aEndpointInf = (TUsbcScHdrEndpointRecord*) &(iEndpoint[aEndpoint*iAltSettings->iEpRecordSize]);
+	return iBuffers->Buffers(aEndpointInf->iBufferNo);
+	}
+
+
+/* Debug functions */
+
+EXPORT_C void TEndpointBuffer::Dump()
+	{
+	RDebug::Printf("TEndpointBuffer::Dump iBufferStart: 0x%x, iSize: 0x%x, iEndpointNumber: 0x%x, iBufferNum: %d, iInState: 0x%x iOutState: 0x%x\n",
+							iBufferStartAddr,iSize,iEndpointNumber,iBufferNum,iInState,iOutState);
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/ldd/perilddsc/group/bld.inf	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,43 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// bld.inf
+// USB Client Driver
+// 
+//
+
+/**
+ @file
+*/
+#include "../appifwrapper/group/bld.inf"
+
+PRJ_PLATFORMS
+
+BASEDEFAULT
+
+PRJ_EXPORTS
+
+PRJ_MMPFILES
+
+#if defined(GENERIC_MARM) || defined(WINS) || defined(GENERIC_X86)
+#if !defined(MARM_THUMB) && !defined(MARM_ARMI)
+
+#if !defined(WINS) 
+#if !defined(X86)
+usbcsc
+#endif
+#endif
+
+
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/ldd/perilddsc/group/usbcsc.mmp	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,32 @@
+// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32/drivers/usbcsc/usbcsc.mmp
+// 
+//
+#include <kernel/kern_ext.mmh>
+
+
+OS_LAYER_SYSTEMINCLUDE
+
+target            usbcscshai.ldd
+targettype        ldd
+
+sourcepath        ../src
+source            d_usbcsc.cpp
+
+library            usbperipheralpil.lib
+
+uid             0 0x101F8928
+VENDORID        0x70000001
+capability        all
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/ldd/perilddsc/src/d_usbcsc.cpp	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,3663 @@
+// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\drivers\usbcsc\d_usbcsc.cpp
+// LDD for USB Device driver stack, using shared chunks:
+// The channel object.
+// 
+//
+
+/**
+ @file d_usbcsc.cpp
+ @internalTechnology
+*/
+
+// #include <drivers/usbcsc.h>
+#include <usb/usbcsc.h>
+#include "platform.h"
+
+/*****************************************************************************\
+*   DUsbcScLogDevice                                                          *
+*                                                                             *
+*   Inherits from DLogicalDevice, the USB Shared Chunk LDD factory class      *
+*                                                                             *
+\*****************************************************************************/
+
+_LIT(KUsbScLddName, "Usbcsc");
+
+static const TInt KUsbRequestCallbackPriority = 2;
+
+/** Real entry point from the Kernel: return a new driver.
+ */
+DECLARE_STANDARD_LDD()
+    {
+    return new DUsbcScLogDevice;
+    }
+
+/** Create a channel on the device.
+
+    @internalComponent
+*/
+TInt DUsbcScLogDevice::Create(DLogicalChannelBase*& aChannel)
+    {
+    aChannel = new DLddUsbcScChannel;
+    return aChannel ? KErrNone : KErrNoMemory;
+    }
+
+
+DUsbcScLogDevice::DUsbcScLogDevice()
+      {
+      iParseMask = KDeviceAllowUnit;
+      iUnitsMask = 0xffffffff;                                // Leave units decision to the Controller
+      iVersion = TVersion(KUsbcScMajorVersion, KUsbcScMinorVersion, KUsbcScBuildVersion);
+      }
+
+
+TInt DUsbcScLogDevice::Install()
+    {
+    // Only proceed if we have the Controller underneath us
+    if (!DUsbClientController::UsbcControllerPointer())
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("LDD Install: USB Controller Not Present"));
+        return KErrGeneral;
+        }
+    return SetName(&KUsbScLddName);
+    }
+
+
+//
+// Return the USB controller capabilities.
+//
+void DUsbcScLogDevice::GetCaps(TDes8& aDes) const
+    {
+    TPckgBuf<TCapsDevUsbc> b;
+    b().version = iVersion;
+    Kern::InfoCopy(aDes, b);
+    }
+
+// End DUsbcScLogDevice
+
+/*****************************************************************************\
+*   TUsbcScChunkInfo                                                          *
+*                                                                             *
+*   Where Chunk information is stored for the channel, and preseved for the   *
+*   life of the chunk.                                                        *
+*                                                                             *
+\*****************************************************************************/
+
+void DfcChunkCleanup(TAny*);
+
+TUsbcScChunkInfo::TUsbcScChunkInfo(DLogicalDevice* aLdd)
+    :     iChunk(NULL),
+        iCleanup((TDfcFn)&DfcChunkCleanup,this,Kern::SvMsgQue(),0),
+        iChunkMem(NULL),
+        iLdd(aLdd)
+    {
+    iPageNtz = (TInt8)__e32_find_ls1_32(Kern::RoundToPageSize(1));
+    }
+
+TInt TUsbcScChunkInfo::CreateChunk(TInt aTotalSize)
+    {
+    // First, reserve an TUint of memory for each of pages needed to hold aTotalSize of memory.
+    // This will form the chunk map, so that we can look up the memory geometry.
+    iAllocatedSize = (aTotalSize>>iPageNtz)*sizeof(TUint);
+    iPhysicalMap = (TUint*) Kern::AllocZ(iAllocatedSize);
+    TInt r;
+    if (iPhysicalMap==NULL)
+        r = KErrNoMemory;
+    else
+        {
+        TChunkCreateInfo chunkInfo;
+        chunkInfo.iType = TChunkCreateInfo::ESharedKernelMultiple;
+        chunkInfo.iMaxSize = aTotalSize;
+        chunkInfo.iMapAttr = EMapAttrCachedMax;
+        chunkInfo.iOwnsMemory = EFalse;
+        chunkInfo.iDestroyedDfc = &iCleanup;
+
+        TLinAddr chunkMem;
+        r = Kern::ChunkCreate(chunkInfo, iChunk, chunkMem, iChunkMapAttr);
+        iChunkMem = (TInt8*) chunkMem;
+        if (r==KErrNone)
+            iLdd->Open();
+        }
+
+    return r;
+}
+
+
+// This method requests closing the chunk.
+// Note that nothing may happen immediately, as something else may have the chunk open.
+void TUsbcScChunkInfo::Close()
+{
+    Kern::ChunkClose(iChunk);    
+}
+
+
+TInt TUsbcScChunkInfo::ChunkAlloc(TInt aOffset, TInt aSize)
+    {
+    TUint pageMask = (~0)<<iPageNtz;
+    TUint rleMask = ~pageMask;
+    TUint pageSize = rleMask+1;
+    TInt r;
+    TLinAddr physAddr;
+
+    __KTRACE_OPT(KUSB, Kern::Printf("::chunkalloc  AllocPhysicalRam aSize %d", aSize));
+
+    r = Epoc::AllocPhysicalRam(aSize, physAddr);
+    __KTRACE_OPT(KUSB, if (r!=KErrNone) Kern::Printf("::chunkalloc AllocPhysicalRam r=%d  (Error!)", r));
+    if (r==KErrNone)
+        {    
+        __KTRACE_OPT(KUSB, Kern::Printf("::chunkalloc ChunkCommitPhysical iChunk 0x%x size(%d), aOffset 0x%x, aSize 0x%x phsAddr 0x%x",
+                                                                                     iChunk, sizeof(DChunk), aOffset, aSize,physAddr ));
+
+        r = Kern::ChunkCommitPhysical(iChunk, aOffset, aSize, physAddr);
+        __KTRACE_OPT(KUSB, if (r!=KErrNone) Kern::Printf("::chunkalloc ChunkCommitPhysical r=%d  (Error!)", r));
+
+        if (r!=KErrNone)
+                Epoc::FreePhysicalRam(physAddr, aSize);
+        else 
+            { // record physical address and length in physical map
+            TInt rle;
+            TInt i=0;
+            for (rle=(aSize>>iPageNtz); rle>0; rle--, i++,physAddr+=pageSize) 
+                {
+                __KTRACE_OPT(KUSB, Kern::Printf("::phys offset 0x%x = 0x%x",
+                                                (aOffset>>iPageNtz)+i,  (physAddr & pageMask) | ((rle>(TInt)rleMask)?(TInt)rleMask:rle)));
+                iPhysicalMap[(aOffset>>iPageNtz)+i] = (physAddr & pageMask) | ((rle>(TInt)rleMask)?(TInt)rleMask:rle);
+                }
+            }
+        }
+    else if (r==KErrNoMemory)
+        r = -KErrNoMemory;  // Semi-expected error.
+    return r;
+    }
+
+/**
+This method retrieves the physical address of a given offset into the Chunk, and returns
+the length of contiguous physical memory from this point.
+
+@param aOffset        the offset from the start of the chunk, to be queried.
+@param aPhysical    a pointer to a TPhysAddr, to be filled with the physical
+                    address of the memory at the given offset.
+
+@returns the length of contiguous physical memory from the given offset.
+*/
+
+TInt TUsbcScChunkInfo::GetPhysical(TInt aOffset, TPhysAddr* aPhysical)
+    {
+    // Use masks, to retrieve the two components from the physical map, we created of the memory.
+    TUint pageMask = (~0)<<iPageNtz;
+    TUint val =  iPhysicalMap[aOffset>>iPageNtz];
+    *aPhysical=(val & pageMask)+(aOffset & ~pageMask);
+    return ((val & ~pageMask)<<iPageNtz) -  (aOffset & ~pageMask);
+    }
+
+
+// DFC calls this fuction, which invokes the cleanup method.
+
+void DfcChunkCleanup(TAny* aChunkInfo)
+    {
+    ((TUsbcScChunkInfo*) aChunkInfo)->ChunkCleanup();
+    }
+
+
+void TUsbcScChunkInfo::ChunkCleanup()
+{
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChunkInfo::ChunkCleanup()"));
+    TUint physAddr;
+    TInt length;
+    TInt offset = 0;
+    
+    // The part of the field used for the physical page address.
+    TUint pageMask = (~0)<<iPageNtz;
+
+    // The part of the field used for the run length encoding, of the contiguous pages.
+    TUint rleMask = ~pageMask;
+    TInt records=(iAllocatedSize>>2);
+
+    while (offset < records) 
+        {
+        physAddr =     iPhysicalMap[offset] & pageMask;
+        length = iPhysicalMap[offset] & rleMask;
+
+        if (physAddr>0)    
+            Epoc::FreePhysicalRam(physAddr, length);
+
+        offset += (length>0)?length:1;
+        }
+    Kern::Free(iPhysicalMap);
+
+    DLogicalDevice* ldd = iLdd;
+    delete this;
+    ldd->Close(NULL);
+}
+
+TInt TUsbcScChunkInfo::New(TUsbcScChunkInfo*& aChunk, TInt aSize, DLogicalDevice* aLdd)
+{
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChunkInfo::New totalSize %d", aSize));
+
+    aChunk = new TUsbcScChunkInfo(aLdd);
+    if (aChunk==NULL)
+        {
+        return KErrNoMemory;
+        }
+                    
+    TInt r = aChunk->CreateChunk(aSize);
+    if (r!=KErrNone)
+        {
+        delete aChunk;
+        aChunk=NULL;
+        return r;
+        }
+
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChunkInfo::New Created at 0x%x",  aChunk->iChunkMem  ));
+    return KErrNone;
+}
+
+// End TUsbcScChunkInfo
+
+/*****************************************************************************\
+*    TUsbcScBuffer                                                            *
+*                                                                             *
+*    Represents a buffer, within a chunk.  Each buffers can be used by        *
+*    differt endpoint on differnt alt settings                                *
+*                                                                             *
+\*****************************************************************************/
+
+
+TInt TUsbcScBuffer::Construct(TInt aDirection, DLddUsbcScChannel* aLdd, TInt aBufferOffset, TInt aBufferEndOffset, TInt aMinReadSize, TInt aMaxPacketSize, TInt aMaxReadSize)
+    {
+    TInt r;
+#ifdef _DEBUG
+    iSequence = aBufferOffset; // Initialized at this, so that each buffer starts with a diffrent sequence number
+#endif
+    iMinReadSize = aMinReadSize;
+    TInt size = (aBufferEndOffset - aBufferOffset);
+    TInt pageSize = Kern::RoundToPageSize(1);
+    if (aMaxReadSize > 0)
+        iMaxReadSize = aMaxReadSize;
+    else
+        iMaxReadSize = pageSize + ((size/3) & ~(pageSize -1));
+    iLdd = aLdd;
+    iDirection = aDirection;
+    iMode=0;
+    iChunkInfo = aLdd->iChunkInfo;
+    iChunkAddr = (TLinAddr) (aLdd->iChunkInfo->iChunkMem);  //aChunkAddr;
+
+    TInt headerSize =  sizeof(TUsbcScTransferHeader)-4; // TransferHeader includes 4 bytes of data.
+
+
+    TUint maxAlignment; // Note:  This is a mask for max Alignment, 
+
+    if (aMaxPacketSize)
+        { // EP0 packets are not DMAed, and so dont need ialignment.
+        iAlignMask = ~3;
+        maxAlignment = 3;
+        }
+    else
+         maxAlignment = 1023; // We don't know what the alignment requirement will be until enumeration, so assume worse case.
+
+    iFirstPacket = aBufferOffset + sizeof(SUsbcScBufferHeader) + headerSize;
+    iFirstPacket = (iFirstPacket + maxAlignment) & ~maxAlignment;
+    
+    iBufferStart = (SUsbcScBufferHeader *) (iChunkAddr+aBufferOffset);
+    iBufferEnd = aBufferEndOffset;
+
+    if ((iDirection&1)==KUsbcScOut)
+        iHead = iFirstPacket-headerSize;//aBufferOffset + sizeof(SUsbcScBufferHeader);
+    else
+        iSent = 0;
+
+    iStalled=0;
+    iMaxPacketSize=0;
+    
+    r =  iStatusList.Construct((aDirection==KUsbcScIn)?KUsbcScInRequests:KUsbcScOutRequests, iLdd->iClient);
+    if (!r)
+        {
+        iMaxPacketSize = aMaxPacketSize; // Indicates configured if ep0, otherwise not.
+        }
+    return r;
+    }
+
+
+void TUsbcScBuffer::CreateChunkBufferHeader()
+{
+    if ((iDirection&1)==KUsbcScOut)
+        {
+        iBufferStart->iHead= iHead;
+        iBufferStart->iTail= iHead; // Initially no data!
+        iBufferStart->iBilTail=iHead;
+        __KTRACE_OPT(KUSB, Kern::Printf("Realize:  iHead 0x%x  bufferHeader 0x%x", iHead,iBufferStart ));
+
+        // Dont need to round here, as we will round it up on endpoint change. (configuration)
+        }
+}
+
+/*
+TUsbcScBuffer::StartEndpoint
+
+This method sets the nessesary paramenters to the buffer, for use for a particular endpoint.
+
+*/
+void TUsbcScBuffer::StartEndpoint(TUsbcRequestCallback* aRequestInfo, TUint aFlags)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartEndpoint (0x%x) : ep %d(%d)",this,aRequestInfo->iEndpointNum, aRequestInfo->iRealEpNum));
+    
+    iCallback=aRequestInfo;
+    iMaxPacketSize =  iLdd->iController->EndpointPacketSize(iLdd, aRequestInfo->iRealEpNum);
+    iAlignMask = ~(((iMaxPacketSize+1) & 0xFFFFFFF8)-1);
+    iMode = aFlags;
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartEndpoint : max Packets %d, mask 0x%x flags 0x%x", iMaxPacketSize, iAlignMask, iMode));
+    if ((iDirection&1)==KUsbcScOut)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UsbcScOut\n"));
+        // Add dummy packet (doesnt have to be aligned, which avoids what if it changes issue)
+        // And Start next read.
+        iNeedsPacket=KEpIsStarting;
+        }
+    }
+
+
+
+void TUsbcScBuffer::Destroy()
+{
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::Destroy()"));
+    Cancel(KErrCancel);
+    if (iLdd->iController && ((iDirection&1)==KUsbcScOut))  
+        {  // Me must cancel reads to LDD to, an there will be no list for the callbacks to look into.
+        iLdd->iController->CancelReadBuffer(iLdd, iCallback->iRealEpNum);
+        }
+    iStatusList.Destroy();
+}
+
+
+
+TInt TUsbcScBuffer::StartDataRead()
+{
+    if (!iMaxPacketSize)
+    {
+        __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataRead() - Not Configured"));
+        return KErrNone;
+    }
+    if (iStatusList.iState!=ENotRunning) 
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataRead() - Already Stated! (%d)",iStatusList.iState));
+        return KErrNone;
+        }
+
+    TInt maxLength;
+    TInt freeSpace;
+    TPhysAddr physAddr;
+
+    // get next request
+    TUsbcScStatusElement* nextJob = iStatusList.Next();
+    if (nextJob == NULL)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("No more jobs"));
+        if (iMode && KUsbScCoupledRead)
+            return KErrEof;
+        iStatusList.iState=EReadingAhead;
+        }
+    else
+        iStatusList.iState=EInProgress;
+
+    TInt tail = iBufferStart->iTail;
+    TInt headerSize =  sizeof(TUsbcScTransferHeader)-4; // TransferHeader includes 4 bytes of data.
+    maxLength = iChunkInfo->GetPhysical(iHead + headerSize, &physAddr); //returns all the bytes available after iHead + headerSize)
+
+    __ASSERT_DEBUG(maxLength>0,Kern::Fault("TUsbcScBuffer::StartDataRead(", __LINE__)); 
+
+
+    if (tail>iHead)  //  # # # H _ _ _ T # # # #
+        {
+        __KTRACE_OPT(KUSB,Kern::Printf("TUsbcScBuffer::StartDataRead() - tail 0x%x>head 0x%x, maxlength 0x%x", tail, iHead, maxLength));
+
+        freeSpace = (tail & iAlignMask) - (iHead +headerSize + (~iAlignMask+1) );  // Cant read right up to last buffer, or head/tail will cross.
+
+        if (freeSpace<iMinReadSize)
+            {
+            iStatusList.iState=ENotRunning;
+            __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataRead() - Stall!!"));
+            return KErrOverflow;                 // Read STALL !! !! !!
+            }
+
+        if (freeSpace<maxLength)
+            maxLength = freeSpace;
+        }
+    if (maxLength> iMaxReadSize) 
+        maxLength =  iMaxReadSize;
+    // else  tail<iHead (or empty)      _ _ _ T # # # H _ _ _ _
+    // We would not have set iHead here if too small. So must be ok.
+        
+    __ASSERT_DEBUG(maxLength>=iMinReadSize,Kern::Fault("TUsbcScBuffer::StartDataRead(", __LINE__)); 
+
+    TUint8* data = ((TUsbcScTransferHeader *) (iHead + iChunkAddr))->iData.b;
+    // set up callback stucture
+
+    iCallback->SetRxBufferInfo(data, physAddr, iIndexArray, iSizeArray,maxLength);
+    TInt r;
+    // Go!!
+    r = iLdd->iController->SetupReadBuffer(*iCallback);
+    if (r!=KErrNone)
+        {
+        __KTRACE_OPT(KUSB,Kern::Printf("SetupReadBuffer Error: %d, RT %d",r, iStatusList.iState));
+        iStatusList.Complete(r);
+        }
+    // After this, TUsbcScEndpoint::RequestCallback is called in a DFC.
+    // This in turn calls either TUsbcScBuffer::CompleteRead.
+    return KErrNone;
+}
+
+
+void TUsbcScBuffer::CompleteRead(TBool aStartNextRead)
+{
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::CompleteRead buff=%x",this));
+
+    // The first packet always contains the total #of bytes
+    const TInt byteCount = iCallback->iPacketSize[0];
+    const TInt packetCount = iCallback->iRxPackets;
+     iCallback->iRxPackets=0;
+    TUint flags = 0;
+
+    if (iCallback->iPacketSize[packetCount - 1] < (TUint) iMaxPacketSize)
+        flags = KUsbcScShortPacket;
+
+    UpdateBufferList(byteCount, flags, aStartNextRead);
+}
+
+
+// This method "submits" the current transfer, and starts off the next read.
+
+void TUsbcScBuffer::UpdateBufferList(TInt aByteCount,TUint aFlags, TBool aStartNextRead)
+    {
+
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst aByteCount %d, flags 0x%x iHead 0x%x", aByteCount, aFlags, iHead));
+
+    TInt headerSize =  sizeof(TUsbcScTransferHeader)-4; // TransferHeader includes 4 bytes of data.
+    TLinAddr dummy;
+    __KTRACE_OPT(KUSB, Kern::Printf("iHead 0x%x headerSize 0x%x",iHead, headerSize));
+
+    // Find iNext
+
+    TInt next =  iHead +  headerSize + aByteCount; // next unused byte in buffer.
+    TInt maxLength; 
+
+    // This may take a few loops before we settle on a value.
+    do 
+        {
+        // round up.
+        next = (next + headerSize + ~iAlignMask) & iAlignMask;
+        maxLength = iChunkInfo->GetPhysical(next, &dummy);
+
+        __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst  next %x  buffer end %x min-read: %x  maxRun %x", next, iBufferEnd, iMinReadSize, maxLength));
+        // At the end of the buffer - wrap it if needbe.
+        if ((TUint)(next + iMinReadSize) > iBufferEnd)
+            {
+            next = iFirstPacket;
+            continue;
+            }
+        // Not enough space, move onto next block.
+        if (maxLength<iMinReadSize) 
+            {
+            next+=maxLength;
+            __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst Skip exhausted block. next %x max %d", next, maxLength));
+            continue;
+            }
+        }
+    while (EFalse);
+
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst next (pre deduct): %x, Fill in header at head: 0x%x,  BuffStart: 0x%x.", next, iHead, iBufferStart));
+    
+    next -=  headerSize;  // Move next back from the data start position, to the header start.
+
+    TUsbcScTransferHeader* header = (TUsbcScTransferHeader*) (iHead + iChunkAddr);
+    
+// Create Header
+#ifdef _DEBUG
+    header->iHashId=59*(iLdd->iAlternateSetting+1)+iCallback->iRealEpNum; // Alt setting realated....
+    header->iSequence=iSequence;
+    iSequence++;
+#endif
+    header->iBytes=aByteCount;
+    header->iNext=next;
+    header->iAltSettingSeq=iLdd->iAsSeq;
+    header->iAltSetting=iLdd->iAlternateSetting;
+    header->iFlags=aFlags;
+    __KTRACE_OPT(KUSB, Kern::Printf("We set next to 0x%x", next));
+
+    iStatusList.iState=ENotRunning;
+    if (next==iBufferStart->iTail) //or (othwise is as good as full)
+        {
+            iStalled=next;
+        }
+    else
+        {
+
+        __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst StartRead?? "));
+        TInt oldHead=iHead;
+        iHead = next;
+
+        if ((aStartNextRead) && (StartDataRead() == KErrOverflow))
+            { // Oh crumbs, set state as slalled.
+            if (oldHead != iBufferStart->iBilTail) 
+                // If user has not read everything in the buffer
+                // then set up a stall, so that ldd get to be woken early
+                {
+                iStalled=next;
+                iHead=oldHead;
+                }
+            else // otherwise if everything is read
+                // no choice but to return what we have
+                {
+                iBufferStart->iHead = iHead;
+                }
+            }
+        else
+            {
+            iBufferStart->iHead = next;
+            __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst Compleating\n"));
+            }
+        // Complete userside
+        iStatusList.Complete();
+        }  
+    }
+
+void TUsbcScBuffer::PopStall()
+    {
+    if (iStalled==iBufferStart->iTail)
+        return;  // Still stalled.
+
+    if (iStalled!=-1) // If not Alt packet only stall
+    {
+        // pop off packet    
+        iHead = iStalled;
+     }
+    iStalled=0;
+    // If Alt setting of the popped packet is different to now
+    // Add alt setting change packet.
+
+
+    if (StartDataRead() == KErrOverflow)
+    {
+        __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::PopStall Warning: Transfer was freed, but still no space!\n"));
+    }
+
+    iBufferStart->iHead = iHead;
+    }
+
+
+
+void TUsbcScBuffer::StartDataWrite()
+    {
+    
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataWrite()"));
+    TUsbcScStatusElement* nextJob = iStatusList.Next();
+    TBool zlpReqd;
+    TInt length;
+    TUint start;
+    TUint8* startAddr;
+    TInt maxLength;
+    TPhysAddr physAddr;
+    TInt r;
+    if (!iMaxPacketSize)
+    {
+        __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataWrite() - Not Configured"));
+        return;
+    }
+
+    if (nextJob == NULL)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataWrite() - No more jobs d=%d", iDirection));
+        if (iDirection==KUsbcScBiIn) // assume this is EP0, if this is true.
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataWrite() Queue Read on EP0."));    
+            // Start other read again.
+            iLdd->iBuffers[iLdd->iEP0OutBuff].StartDataRead();
+            }
+        }
+    else
+        {
+        if (iStatusList.iState==ENotRunning)
+            iSent=0;
+        iStatusList.iState=EInProgress;
+
+        start = nextJob->iStart;
+        startAddr = (TUint8*) (start + ((TUint) (iChunkInfo->iChunkMem)));
+
+        length = nextJob->iLength;
+        zlpReqd = (nextJob->iFlags & KUsbcScWriteFlagsZlp) !=0;
+        // get max read length
+        maxLength = iChunkInfo->GetPhysical( start, &physAddr); 
+
+        if (maxLength < length)
+            {
+                // modify request.
+                nextJob->iStart += maxLength;
+                nextJob->iLength -= maxLength;
+                // start this request.
+                iStatusList.iState=EFramgementInProgress;
+                zlpReqd=EFalse;
+                length =  maxLength;
+            }
+
+        if (iDirection==KUsbcScBiIn) // this is for EP0
+            {
+            iLdd->iController->CancelReadBuffer(iLdd, iCallback->iRealEpNum);
+            iLdd->iBuffers[iLdd->iEP0OutBuff].iStatusList.iState=ENotRunning;
+            }
+        
+        iCallback->SetTxBufferInfo(startAddr, physAddr, length);
+        iCallback->iZlpReqd = zlpReqd;
+        r = iLdd->iController->SetupWriteBuffer(*iCallback);
+        if (r!=KErrNone)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("SetupWriteBUffer Error: %d",r));
+            iStatusList.Complete(r);
+            }
+        }
+
+    }
+
+void TUsbcScBuffer::CompleteWrite()
+    {
+    TInt error = iCallback->iError;
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::CompleteWrite buff=%x, err=%d",this, error));
+    iSent+= iCallback->iTxBytes;
+
+    // More to send?
+    if (error || iStatusList.iState!=EFramgementInProgress)
+        {
+        // complete request with error (if one).
+        // Some data could have been transmitted, even with an error. 
+        iStatusList.Complete(error);
+        }
+
+    // Start next request, or next part of this one.
+    StartDataWrite();
+    
+    }
+
+// Cancels the current request's callback.
+// This is not to say it will cancel the actual operation,
+// However it will cancel any further sections of the user perceived operation
+// that are not yet started.
+void TUsbcScBuffer::Cancel(TInt aErrorCode)
+    {
+    iStatusList.CancelQueued();
+    if (iLdd->iController && ((iDirection&1)==KUsbcScIn))
+        {
+        iLdd->iController->CancelWriteBuffer(iLdd, iCallback->iRealEpNum);
+        }
+
+    iStatusList.Complete(aErrorCode);
+    }
+
+void TUsbcScBuffer::Ep0CancelLddRead()
+    {
+    // Stopping a read isn't as easy as one might think.
+    // We cancel the callback, but then check if any data was received (but not returned to us).
+    // If so, we must de-queue the request, and call the completion code.
+    
+    iLdd->iController->CancelReadBuffer(iLdd, iCallback->iRealEpNum);
+    if (iCallback->iRxPackets) // received data?
+        {
+        // remove DFC (if infact sent)
+        iCallback->iDfc.Cancel();
+
+        // process the callback now, but dont start another
+        CompleteRead(EFalse);
+        }
+    }
+
+void TUsbcScBuffer::SendEp0StatusPacket(TInt aState)
+{
+    __KTRACE_OPT(KUSB, Kern::Printf(" TUsbcScBuffer::SendEp0StatusPacket(%d)", aState));
+
+    // We need to add a packet to the buffer, so we must stop the pending read, and start
+    // another after we have added out packet.  
+    Ep0CancelLddRead();
+
+    TUint* state = ((TUsbcScTransferHeader *) (iHead + iChunkAddr))->iData.i;
+    *state = aState;
+    UpdateBufferList(4,KUsbcScStateChange);
+}
+
+// End TUsbcScBuffer
+
+/*****************************************************************************\
+*    TUsbcScStatusList                                                        *
+*                                                                             *
+*    This is a list of read or write requests, containing user status         *
+*    requests, that should later be completed.                                *
+*                                                                             *
+\*****************************************************************************/
+
+/**
+Constructor for TUsbcScStatusList.
+
+@param aSize    is the number of requests to allow at any one time.  This value
+                must be a power of two, for correct operation.
+
+@returns KErrNoMemory if memory allocation failure, otherwise KErrNone.
+*/
+
+TInt TUsbcScStatusList::Construct(TInt aSize, DThread* aClient)
+    {
+    iSize=aSize;
+    iHead = 0;
+    iLength = 0;
+    iClient = aClient;
+    iElements=(TUsbcScStatusElement *) Kern::AllocZ(sizeof(TUsbcScStatusElement)*aSize);
+    return (iElements==NULL)?KErrNoMemory:KErrNone;    
+    };
+
+
+// StatusList must be inactive before destroying.
+void TUsbcScStatusList::Destroy()
+    {
+    if (iState!=ENotRunning)
+        Kern::Fault("TUsbcScStatusList::Destroy", __LINE__);
+    if (iElements)
+        {
+        Kern::Free(iElements);    
+        iElements=NULL;
+        }
+    iClient=NULL;
+}
+
+void TUsbcScStatusList::Pop()
+    {
+    if (iLength>0)
+        {
+        iLength--;
+        iHead = ((iHead+1) & (iSize-1));
+        }
+    }
+
+TUsbcScStatusElement* TUsbcScStatusList::Next()
+    {
+    return (iLength==0)?NULL:&(iElements[iHead]);
+    }
+
+TInt TUsbcScStatusList ::Add(TRequestStatus* aStatus, TInt aLength, TUint aStart, TUint aFlags)
+    {
+    __KTRACE_OPT(KUSB,Kern::Printf("Adding request.  iLength %d  iSize %d", iLength, iSize));
+    if (iLength<iSize)
+        {
+        TUsbcScStatusElement& e = iElements[((iHead+iLength) & (iSize-1))];
+        e.iStatus = aStatus;
+        e.iLength = aLength;
+        e.iStart = aStart;
+        e.iFlags = aFlags;
+        iLength++;
+        __KTRACE_OPT(KUSB,Kern::Printf("Adding request.  new iLength %d", iLength));
+
+        return KErrNone;
+        }
+    else
+        return KErrInUse;
+    }
+
+
+
+// This method cancels any requests that have yet to be started.
+
+void TUsbcScStatusList::CancelQueued(TInt aError)
+{
+    if ((iLength==0) || ((iState!=ENotRunning) && (iLength==1)))  // Nothing to do.
+        return;  
+    TInt elements2Complete = iLength - (iState?1:0);
+    TInt head = iHead;
+    iLength = 0;
+    if (iState)    // If (iState != ENotRunning), complete all elements excepting the one at head
+        {
+        head = ((head+1) & (iSize-1)); // To iterate through the queue
+        iLength = 1;
+        }
+    // complete them all.
+    for (; elements2Complete>0; elements2Complete--)
+          {
+        Kern::RequestComplete(iClient, iElements[head].iStatus, aError);
+        head = ((head+1) & (iSize-1)); 
+          }
+    
+}
+
+
+/* This method Completes the head status request, and pops it from its list.
+This version of Complete is to be used in cases where the next request is not
+chained - usually because of an error.
+
+@Param aError - the code to complete with.
+
+returns KErrNotFound if there was no request to complete
+*/
+
+
+TInt TUsbcScStatusList::Complete(TInt aError)
+    {
+    if (iState==ENotRunning)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScStatusList::Complete() - iState == ENotRunning!"));
+        }
+     else
+        {
+        iState=ENotRunning;
+        if (iLength==0)
+            return KErrNotFound;
+
+        Kern::RequestComplete(iClient, iElements[iHead].iStatus, aError);
+
+        iLength--;
+        iHead = ((iHead+1) & (iSize-1));
+        }
+    return KErrNone;
+    }
+
+
+/* This method Completes the head status request, and pops it from its list. (If found.)
+This version of Complete is to be used in cases where the request is successful, and
+ next request after this has (if present) been chained.
+*/
+
+void TUsbcScStatusList::Complete()
+    {
+    if (iLength==0)
+        return;
+    __KTRACE_OPT(KUSB, Kern::Printf("Completing request.  iLength %d", iLength));
+
+    Kern::RequestComplete(iClient, iElements[iHead].iStatus, KErrNone);
+
+    iLength--;
+    iHead = ((iHead+1) & (iSize-1));
+    }
+
+// End TUsbcScStatusList
+
+/*****************************************************************************\
+*   TRealizeInfo                                                              *
+*                                                                             *
+*   Used by DLddUsbcScChannel::RealizeInterface to set up the chunk           *
+*                                                                             *
+\*****************************************************************************/
+
+// Init
+//
+// This method works out the number potential maximum number of endpoints
+// and the number of alt settings.  With this information it allocs
+// the necessary space for the given stucture to store information about
+// the endpoints.  
+// This is intended to be called by RealizeInterface.  This stucture is
+// intended to be only temporary, and the space will be freed with Free()
+// before RealizeInteface has finished.
+
+void TRealizeInfo::Init(TUsbcScAlternateSettingList* aAlternateSettingList)
+{
+    iAlternateSettingList = aAlternateSettingList;
+    iMaxEndpoints=0;
+    iTotalSize   =0;
+    iTotalBuffers=0;
+    iAltSettings =0;
+    __KTRACE_OPT(KUSB, Kern::Printf("Realize: work out max endpoint"));
+    // Work out max endpoints and number of alternate settings.
+
+    if (iAlternateSettingList)
+        {
+        TUsbcScAlternateSetting* alt = iAlternateSettingList->iHead;
+        while (alt != NULL) 
+            {
+            iAltSettings++;
+            if (alt->iNumberOfEndpoints>iMaxEndpoints)
+                iMaxEndpoints = alt->iNumberOfEndpoints;
+            // could work out in/out specifics, but unnecessary.
+            alt = alt->iNext;
+            };
+        }
+    
+    // Alloc some temporary working space for temp endpoint metadata 
+    __KTRACE_OPT(KUSB, Kern::Printf("Realize: Alloc temp.  Maxendpoints %d", iMaxEndpoints));
+    TInt inout;
+    for (inout=KUsbcScIn; inout<KUsbcScDirections; inout++)
+        {
+        iBufs[inout].iEp = (TUsbcScEndpoint **) Kern::AllocZ(iAltSettings*iMaxEndpoints*sizeof(TUsbcScEndpoint *));
+        iBufs[inout].iSizes = (TInt *) Kern::AllocZ(iMaxEndpoints*sizeof(TInt));
+        }
+}
+
+// CopyAndSortEndpoints
+//
+// This method copies pointers to the endpoint records into TRealizeInfo
+// such that they are sorted in order of size per alt setting.
+// In and Out endpoints are separated, and kept separate.
+// The provided data structure is assumed to have been initialised with
+// Realize_InitRealizeInfo. 
+//
+// Return KErrArgument if the direction field is neither In or Out.
+//
+
+TInt TRealizeInfo::CopyAndSortEndpoints()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("Realize: copy And sort"));
+
+    TInt altSetting = 0;
+    TInt endpointOffs;
+    TInt endpoint;
+    TInt altEp;
+    TInt inout;
+    TBool placed;
+    TUsbcScAlternateSetting* alt;
+    TEndpointSortBufs* bufsd;
+
+    if (iAlternateSettingList)
+        {
+        for (alt = iAlternateSettingList->iHead;alt!=NULL;alt = alt->iNext )
+            {        
+            __KTRACE_OPT(KUSB, Kern::Printf("Realize:   AlternateSetting %x", alt));
+
+            iBufs[KUsbcScIn].iEps =0;
+            iBufs[KUsbcScOut].iEps =0;
+
+            // For alt setting, iterate eps
+            for (altEp=1; altEp <= alt->iNumberOfEndpoints; altEp++)
+                {
+                __KTRACE_OPT(KUSB, Kern::Printf("Realize:     Endpoint to add: %d",altEp));
+
+                TUsbcScEndpoint* nextEp = alt->iEndpoint[altEp];
+
+                __KTRACE_OPT(KUSB, Kern::Printf("Realize:      ep Buffer Size: %d",nextEp->EndpointInfo()->iBufferSize));
+                
+                inout = (nextEp->EndpointInfo()->iDir==UsbShai::KUsbEpDirIn)?KUsbcScIn:
+                        (nextEp->EndpointInfo()->iDir==UsbShai::KUsbEpDirOut)?KUsbcScOut:KUsbcScUnknown;
+                if (inout==KUsbcScUnknown)
+                    {
+                    __KTRACE_OPT(KUSB, Kern::Printf("Realize:     KUsbcScUnknown %x",nextEp->EndpointInfo()->iDir));
+                    return KErrArgument;
+                    }
+
+                bufsd = &(iBufs[inout]);
+                __KTRACE_OPT(KUSB, Kern::Printf("Realize:      ep direction: %x # endpoints %d", inout, bufsd->iEps));
+
+
+                // find and position ep, and insert.
+
+                if (bufsd->iEps==0) // First entry.
+                    {
+                    __KTRACE_OPT(KUSB, Kern::Printf("Realize:       Add first endpoint"));
+                    endpointOffs = altSetting*iMaxEndpoints;
+                    bufsd->iEp[endpointOffs] = nextEp;
+                    }
+                else
+                    {
+                    placed = EFalse;
+                    // Move down the list, until we find the right place.
+                    for (endpoint=bufsd->iEps-1; endpoint>-1; endpoint--)
+                        {
+                        endpointOffs = altSetting*iMaxEndpoints + endpoint;
+                        if (bufsd->iEp[endpointOffs]->EndpointInfo()->iBufferSize < nextEp->EndpointInfo()->iBufferSize)
+                            {
+                            __KTRACE_OPT(KUSB, Kern::Printf("Realize:       Shift Endpoint %d", endpoint));
+        
+                            bufsd->iEp[endpointOffs+1] = bufsd->iEp[endpointOffs];
+                            }
+                        else
+                            {
+                            __KTRACE_OPT(KUSB, Kern::Printf("Realize:       Insert After Endpoint %d", endpoint));
+
+                            bufsd->iEp[endpointOffs+1] = nextEp;
+                            placed = ETrue;
+                            break;
+                            }
+                        } // end for endpoint
+                        if (!placed) // if we didn't place it, it must be the biggest so far, so goes at the top.
+                            bufsd->iEp[0] = nextEp;
+                    } // endif
+                bufsd->iEps++;            
+                } // for altEp
+                altSetting++;
+            } // for alt
+        }// if iAltsettingList
+    return KErrNone;
+    }
+
+// CalcBuffSizes
+//
+// This works out the sizes of all the buffers, and stores the result in aBufInfo
+// based on the buffer information provided in the same structure.
+// Realize_CopyAndSortEndpoints is used to fill the structure with the informaition
+// required.
+
+void TRealizeInfo::CalcBuffSizes()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("Realize: Calculate Buffers"));
+
+    TInt endpoint;
+    TInt inout;
+    TInt altSetting;
+    TUsbcScEndpoint* nextEp;
+    TInt bufferSize;
+    TEndpointSortBufs* bufsd;
+
+    for (inout=KUsbcScIn; inout<KUsbcScDirections; inout++)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("Realize:   Direction: %d", inout));
+
+
+        bufsd = &(iBufs[inout]);
+        // for each row, ie, buffer, find largest buffer need.
+        for (endpoint=0; endpoint<iMaxEndpoints; endpoint++)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("Realize:     endpoint %d", endpoint));
+            TInt bufMaxSize=0;
+            for (altSetting=0; altSetting< iAltSettings; altSetting++)
+                {
+                __KTRACE_OPT(KUSB, Kern::Printf("Realize:       altSetting %d", altSetting));
+                nextEp= bufsd->iEp[altSetting* iMaxEndpoints + endpoint];
+                if (nextEp!=NULL)
+                    {
+                    bufferSize = nextEp->EndpointInfo()->iBufferSize;
+                    __KTRACE_OPT(KUSB, Kern::Printf("Realize:       comparing size %d", bufferSize));
+                    if (bufferSize> bufMaxSize)
+                         bufMaxSize = bufferSize;
+                    }
+                } // for altsetting
+            __KTRACE_OPT(KUSB, Kern::Printf("Realize:     bufMaxSize %d", bufMaxSize));
+            bufsd->iSizes[endpoint] = bufMaxSize;
+            if (bufMaxSize>0) 
+                {
+                iTotalSize += bufsd->iSizes[endpoint];
+                iTotalBuffers++;
+                }
+            } // for endpoint
+        } // for in/out    
+}
+
+// Free
+//
+// Cleans up after Init()
+
+void TRealizeInfo::Free()
+    {
+    TInt inout;
+    for (inout=KUsbcScIn; inout<KUsbcScDirections; inout++)
+        {
+        Kern::Free(iBufs[inout].iEp);
+        Kern::Free(iBufs[inout].iSizes);
+        }
+    }
+
+// End TRealizeInfo
+
+
+// LayoutChunkHeader
+//
+// Sets up some geometry for the chunk;
+
+void TRealizeInfo::LayoutChunkHeader(TUsbcScChunkInfo* aChunkInfo)
+{ 
+    // First set up the indexes to the header structures.
+    TUsbcScChunkHdrOffs* chkHdr = (TUsbcScChunkHdrOffs*) aChunkInfo->iChunkMem;
+
+    chkHdr->iBuffers = sizeof(TUsbcScChunkHdrOffs); // First struct just after this one.
+    iChunkStuct = (TUsbcScChunkBuffersHeader*) ( (TInt) aChunkInfo->iChunkMem + chkHdr->iBuffers);
+
+    // Store number of buffers in chunk
+    iChunkStuct->iRecordSize = sizeof(TUsbcScBufferRecord);
+    iChunkStuct->iNumOfBufs=iTotalBuffers;
+
+    iAltSettingsTbl = (TUsbcScChunkAltSettingHeader*) &(iChunkStuct->iBufferOffset[(iTotalBuffers+2)*sizeof(TUsbcScBufferRecord)]); // 2 extra for EP0 in and out.
+
+    chkHdr->iAltSettings = (TUint) iAltSettingsTbl - (TUint) aChunkInfo->iChunkMem;
+
+    iAltSettingsTbl->iEpRecordSize = sizeof(TUint);
+    iAltSettingsTbl->iNumOfAltSettings = iAltSettings;
+
+
+    TInt tableOffset  = (TUint) iAltSettingsTbl->iAltTableOffset - (TUint) aChunkInfo->iChunkMem + iAltSettings*sizeof(TInt);
+    __KTRACE_OPT(KUSB, Kern::Printf("Realize: table offset: 0x%x, altTble %x iChnkMem %x altSettings %x",tableOffset, iAltSettingsTbl, aChunkInfo->iChunkMem, iAltSettings ));
+
+    __KTRACE_OPT(KUSB, Kern::Printf("Realize: populate chunk - create alt settings table"));
+
+    // Create alt settings table.  Set each element of altsettings table, to each induivatual alt setting table.
+    // then fill in the number of endpoints for that alt setting, in the table.
+
+    TInt* noEpForAlt;
+    TInt altSetting;
+    TUsbcScAlternateSetting* alt;
+    if (iAlternateSettingList)
+        {
+        alt = iAlternateSettingList->iHead;
+        for (altSetting=0; altSetting<iAltSettings; altSetting++) 
+            {
+                __KTRACE_OPT(KUSB, Kern::Printf("Realize:   altSetting %d, tableOffset %d", altSetting, tableOffset));
+
+                iAltSettingsTbl->iAltTableOffset[altSetting] = tableOffset;
+                noEpForAlt = (TInt*) &aChunkInfo->iChunkMem[tableOffset];
+             
+                *noEpForAlt = alt->iNumberOfEndpoints;  // Set NumberofEndpoints field in Altsetting table
+                tableOffset+= sizeof(TInt)+ alt->iNumberOfEndpoints*sizeof(TUsbcScHdrEndpointRecord);
+                alt = alt->iNext;
+            }
+        }        
+
+} // end LayoutChunkHeader
+
+
+
+/*****************************************************************************\
+*   DLddUsbcScChannel                                                         *
+*                                                                             *
+*   Inherits from DLogicalDevice, the USB Shared Chunk LDD factory class      *
+*                                                                             *
+\*****************************************************************************/
+
+//
+// Constructor
+//
+DLddUsbcScChannel::DLddUsbcScChannel()
+    : iValidInterface(EFalse),
+      iAlternateSettingList(NULL),
+      iEndpoint(NULL),
+      iCompleteAllCallbackInfo(this, DLddUsbcScChannel::EmergencyCompleteDfc, KUsbRequestCallbackPriority),
+      iStatusChangePtr(NULL),
+      iStatusCallbackInfo(this, DLddUsbcScChannel::StatusChangeCallback, KUsbRequestCallbackPriority),
+      iEndpointStatusChangePtr(NULL),
+      iEndpointStatusCallbackInfo(this, DLddUsbcScChannel::EndpointStatusChangeCallback,
+                                  KUsbRequestCallbackPriority),
+      iOtgFeatureChangePtr(NULL),
+      iOtgFeatureCallbackInfo(this, DLddUsbcScChannel::OtgFeatureChangeCallback, KUsbRequestCallbackPriority),
+      iNumberOfEndpoints(0),
+      iDeviceState(UsbShai::EUsbPeripheralStateUndefined),
+      iOwnsDeviceControl(EFalse),
+      iAlternateSetting(0),
+      iAsSeq(0),
+      iStatusFifo(NULL),
+      iUserKnowsAltSetting(ETrue),
+      iDeviceStatusNeeded(EFalse),
+      iChannelClosing(EFalse),
+      iRealizeCalled(EFalse),
+      iChunkInfo(NULL),
+      iNumBuffers(-1),
+      iBuffers(NULL),
+      iEp0Endpoint(NULL)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DLddUsbcScChannel()"));
+    iClient = &Kern::CurrentThread();
+    iClient->Open();
+    for (TInt i = 1; i < KUsbcMaxRequests; i++)
+        {
+        iRequestStatus[i] = NULL;
+        }
+    }
+
+
+//
+// Destructor
+//
+
+DLddUsbcScChannel::~DLddUsbcScChannel()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::~DLddUsbcScChannel()"));
+    if (iController)
+        {
+        iController->DeRegisterClient(this);
+        iStatusCallbackInfo.Cancel();
+        iEndpointStatusCallbackInfo.Cancel();
+        iOtgFeatureCallbackInfo.Cancel();
+        iCompleteAllCallbackInfo.Cancel();
+        DestroyAllInterfaces();
+        if (iOwnsDeviceControl)
+            {
+            iController->ReleaseDeviceControl(this);
+            iOwnsDeviceControl = EFalse;
+            }
+        iController=NULL;
+        DestroyEp0();
+        if (iStatusFifo!=NULL)
+            {
+            delete iStatusFifo;
+            }
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("Closing buffers"));
+    if (iBuffers)
+        {
+        TInt i;
+        for (i=0; i<(iNumBuffers+2); i++) 
+            {
+            iBuffers[i].Destroy();
+            }
+        Kern::Free(iBuffers);
+        }
+
+    if (iRealizeCalled)
+        {
+        // Close Chunk
+        iChunkInfo->Close();
+        // ChunkInfo will delete itself with DFC, but the pointer here is no longer needed.        
+        iChunkInfo=NULL;
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("about to SafeClose"));
+    Kern::SafeClose((DObject*&)iClient, NULL);
+    }
+
+
+//
+// DoCreate - Create channel
+//
+
+TInt DLddUsbcScChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& aVer)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("LDD DoCreateL 1 Ver = %02d %02d %02d",
+                                    aVer.iMajor, aVer.iMinor, aVer.iBuild));
+    if (!Kern::CurrentThreadHasCapability(ECapabilityCommDD,
+                                          __PLATSEC_DIAGNOSTIC_STRING("Checked by USBCSC.LDD (USB Driver)")))
+        {
+        return KErrPermissionDenied;
+        }
+
+    iController = DUsbClientController::UsbcControllerPointer();
+
+    if (!iController)
+        {
+        return KErrGeneral;
+        }
+
+    iStatusFifo = new TUsbcDeviceStatusQueue;
+    if (iStatusFifo == NULL)
+        {
+        return KErrNoMemory;
+        }
+
+      if (!Kern::QueryVersionSupported(TVersion(KUsbcScMajorVersion, KUsbcScMinorVersion, KUsbcScBuildVersion), aVer))
+        {
+        return KErrNotSupported;
+        }
+
+    // set up the correct DFC queue
+    SetDfcQ(iController->DfcQ(0));                            // sets the channel's dfc queue
+    iCompleteAllCallbackInfo.SetDfcQ(iDfcQ);
+    iStatusCallbackInfo.SetDfcQ(iDfcQ);                        // use the channel's dfcq for this dfc
+    iEndpointStatusCallbackInfo.SetDfcQ(iDfcQ);                // use the channel's dfcq for this dfc
+    iOtgFeatureCallbackInfo.SetDfcQ(iDfcQ);
+    iMsgQ.Receive();                                        //start up the message q
+    TInt r = iController->RegisterClientCallback(iCompleteAllCallbackInfo);
+    if (r != KErrNone)
+        return r;
+    r = iController->RegisterForStatusChange(iStatusCallbackInfo);
+    if (r != KErrNone)
+        return r;
+    r = iController->RegisterForEndpointStatusChange(iEndpointStatusCallbackInfo);
+    if (r != KErrNone)
+        return r;
+    r = iController->RegisterForOtgFeatureChange(iOtgFeatureCallbackInfo);
+    if (r != KErrNone)
+        return r;
+
+    return r;
+    }
+// end DoCreate.
+
+
+//
+// HandleMsg
+//
+// Events from userside arrive here, and delegated to either DoRequest, DoControl or DoCancel.
+//
+
+void DLddUsbcScChannel::HandleMsg(TMessageBase* aMsg)
+    {
+    TThreadMessage& m = *(TThreadMessage*)aMsg;
+    TInt id = m.iValue;
+    __KTRACE_OPT(KUSB, Kern::Printf("HandleMsg 0x%x", id));
+
+    if (id == (TInt) ECloseMsg)
+        {
+        iChannelClosing = ETrue;
+        m.Complete(KErrNone, EFalse);
+        return;
+        }
+
+    TInt r;
+    if (id < 0)
+        {
+        // DoRequest
+        TRequestStatus* pS = (TRequestStatus*) m.Ptr0();
+        r = DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
+        m.Complete(r, ETrue);
+        }
+    else if (id & RDevUsbcScClient::ERequestCancel)
+        {
+        // DoCancel
+        r = DoCancel(id, (TUint) m.Ptr0(), (TUint) m.Ptr1());
+        m.Complete(r, ETrue);
+    }
+    else
+        {
+        // DoControl
+        r = DoControl(id, m.Ptr0(), m.Ptr1());
+        m.Complete(r, ETrue);
+        }
+    }
+// end HandleMsg.
+
+
+#define BREAK_IF_NULL_ARG(a,r) if (a==NULL) { r = KErrArgument; __KTRACE_OPT(KUSB,Kern::Printf("NULL Argument")); break; }
+
+//
+// DoRequest - Asynchronous requests
+//
+// Overrides pure virtual, called by HandleMsg. (Above)
+//
+TInt DLddUsbcScChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
+    {
+    TInt reqNo = aReqNo & RDevUsbcScClient::KFieldIdMask;
+    TInt r = KErrNone;  // return via request notify
+    TBool needsCompletion =EFalse;
+
+    __KTRACE_OPT(KUSB, Kern::Printf("DoRequest 0x%08x", aReqNo));
+
+    if ((reqNo>RDevUsbcScClient::ERequestReadDataNotify) &&
+        (reqNo<RDevUsbcScClient::ERequestMaxRequests))
+        {
+        if (iRequestStatus[reqNo])
+            {
+            PanicClientThread(ERequestAlreadyPending);
+            return 0;
+            }
+        iRequestStatus[reqNo] = aStatus;
+        }
+
+    switch (reqNo)
+        {
+    case RDevUsbcScClient::ERequestWriteData:
+        {
+        TInt buffer =  (aReqNo>>RDevUsbcScClient::KFieldBuffPos)&RDevUsbcScClient::KFieldBuffMask;
+        __KTRACE_OPT(KUSB, Kern::Printf("ERequestWriteData"));
+        BREAK_IF_NULL_ARG(a2,r);
+
+        r = DoWriteData( aStatus, buffer, (TInt) a1 /*Start*/, (TInt) a2 /* Length */,
+                         aReqNo>>RDevUsbcScClient::KFieldFlagsPos ); // Flags
+        break;
+        }
+    case RDevUsbcScClient::ERequestReadDataNotify:
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("ERequestReadDataNotify"));
+        return DoReadDataNotify(aStatus, (TInt) a1, (TInt) a2); // a1 = aBufferNumber, a2 - aLength;
+        } 
+
+    case RDevUsbcScClient::ERequestAlternateDeviceStatusNotify:
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("ERequestAlternateDeviceStatusNotify"));
+        BREAK_IF_NULL_ARG(a1,r);
+        iDeviceStatusNeeded = ETrue;
+        iStatusChangePtr = a1;
+        needsCompletion = AlternateDeviceStateTestComplete();
+        break;
+        }
+    case RDevUsbcScClient::ERequestReEnumerate:
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("ERequestReEnumerate"));
+        // If successful, this will complete via the status notification.
+        r = iController->ReEnumerate();
+        break;
+        }
+    case RDevUsbcScClient::ERequestEndpointStatusNotify:
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("ERequestEndpointStatusNotify"));
+        BREAK_IF_NULL_ARG(a1,r);
+        
+        iEndpointStatusChangePtr = a1;
+        break;
+        }
+    case RDevUsbcScClient::ERequestOtgFeaturesNotify:
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("ERequestOtgFeaturesNotify"));
+        BREAK_IF_NULL_ARG(a1,r);
+            
+        iOtgFeatureChangePtr = a1;
+        break;
+        }
+    default:
+        r = KErrNotSupported;
+        }
+
+    if ((needsCompletion) || (r != KErrNone))
+        {
+        iRequestStatus[reqNo] = aStatus;
+        Kern::RequestComplete(iClient, iRequestStatus[reqNo], r);
+        }
+    return KErrNone;
+    }
+// end DoRequest.
+
+
+//
+// DoReadDataNotify
+//
+// This method sets up the request to facilitate the userside being notifed when new data has been read.
+//
+TInt DLddUsbcScChannel::DoReadDataNotify(TRequestStatus* aStatus, TInt aBufferNum, TInt aLength)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoReadDataNotify(x, %d, 0x%x)", aBufferNum, aLength));
+    TInt r = KErrNone;
+    // check range
+    if ((aBufferNum<0) ||  (aBufferNum>=iNumBuffers))  // Indirectly checks that we are set up.
+        {
+        if (aBufferNum!=KUsbcScEndpointZero)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoReadDataNotify : Bad Buffer Number!"));
+            return KErrArgument;
+            }
+        else
+            {
+            aBufferNum = iEP0OutBuff;
+            }
+        }
+    else
+        {
+        // check direction
+        if (iBuffers[aBufferNum].iDirection!=KUsbcScOut)
+            {
+                __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoReadDataNotify : Bad Buffer Direction!"));
+            return KErrNotSupported;
+            }
+        if (!Configured())
+            return KErrUsbInterfaceNotReady;
+        }
+    SUsbcScBufferHeader* scBuffer = (SUsbcScBufferHeader*) iBuffers[aBufferNum].iBufferStart;
+
+    __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoReadDataNotify  head %x tail %x", iBuffers[aBufferNum].iHead , scBuffer->iTail ));
+
+    if (iBuffers[aBufferNum].iHead != scBuffer->iBilTail)
+        r = KErrCompletion;
+    else
+        if (iBuffers[aBufferNum].iStalled)
+            {
+            iBuffers[aBufferNum].PopStall();
+            return KErrCompletion;
+            }
+        else
+            r = iBuffers[aBufferNum].iStatusList.Add(aStatus, aLength, 0,0);
+
+    if (iBuffers[aBufferNum].iStatusList.iState==ENotRunning)
+        {
+        iBuffers[aBufferNum].StartDataRead();
+        }
+    else
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("Job in Progress!"));
+        }
+    return r;
+    }
+// end DoReadDataNotify.
+
+
+
+//
+// DoWriteData
+//
+// This method sets up the request to write data to USB from userside.
+//
+TInt DLddUsbcScChannel::DoWriteData(TRequestStatus* aStatus,TInt aBufferNum, TUint aStart, TUint aLength, TUint aFlags)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoWriteData(%d, 0x%x, 0x%x, 0x%x)",  aBufferNum, aStart, aLength, aFlags));
+    if (!iUserKnowsAltSetting)
+        return KErrEof;
+    // Check Buffer Number
+    if ((aBufferNum<0) ||  (aBufferNum>=iNumBuffers))
+        {
+        if ((TUint)aBufferNum!=RDevUsbcScClient::KFieldBuffMask)  // KUsbcScEndpointZero & KFieldBuffMas = KFieldBuffMas;
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoWriteData : Bad Buffer Number!"));
+            return KErrArgument;
+            }
+        else
+            {
+            aBufferNum = iEP0InBuff;
+            }
+        }
+    else
+        {
+        // check direction
+        if (iBuffers[aBufferNum].iDirection!=KUsbcScIn)
+            {
+                __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoWriteData Bad endpoint Direction"));
+                return KErrArgument;
+            }
+        }
+
+    TUsbcScBuffer& buf=iBuffers[aBufferNum];
+
+    if ((aStart< (((TLinAddr) buf.iBufferStart)-buf.iChunkAddr)) || ((aStart+aLength)>iBuffers[aBufferNum].iBufferEnd))
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoWriteData Bad Range aStart or aLength 0x%x > 0x%x + 0x%x < 0x%x", (((TLinAddr) buf.iBufferStart)-buf.iChunkAddr),aStart, aLength, iBuffers[aBufferNum].iBufferEnd ));
+        return KErrArgument;
+        }
+
+    if ( (aBufferNum != iEP0InBuff) && !Configured())
+        return KErrUsbInterfaceNotReady;
+
+    if (aStart & ~buf.iAlignMask)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::DoDataWrite: address 0x%x unaligned.",aStart));
+        return KErrArgument;
+        }
+            
+    TInt r = iBuffers[aBufferNum].iStatusList.Add(aStatus, aLength, aStart, aFlags); //update
+
+    if (iBuffers[aBufferNum].iStatusList.iState==ENotRunning)
+        {
+            iBuffers[aBufferNum].StartDataWrite();
+        }
+    else
+        {    
+        __KTRACE_OPT(KUSB, Kern::Printf("Job in Progress!"));
+        }
+
+
+    return r;
+    }
+// end DoWriteData.
+
+
+//
+// Cancel an outstanding request                        // Cancel need reworking.
+//
+TInt DLddUsbcScChannel::DoCancel(TInt aReqNo, TUint aBuff, TUint aSpair)
+    {
+    TInt r = KErrNone;
+    TInt direction=KUsbcScOut;
+
+    __KTRACE_OPT(KUSB, Kern::Printf("DoCancel: 0x%x aBuff 0x%x", aReqNo, aBuff));
+    switch (aReqNo)
+        {
+    case RDevUsbcScClient::ERequestCancel:
+        TInt buffer;
+        TInt mask;
+
+        for (buffer=1, mask=1; buffer<iNumBuffers; buffer++,mask<<=1)
+            if (aBuff&mask)
+                iBuffers[buffer].Cancel(KErrCancel);
+
+        return KErrNone;
+
+    // coverity[missing_break]
+    case RDevUsbcScClient::ERequestWriteDataCancel:
+        direction = KUsbcScIn;
+    case RDevUsbcScClient::ERequestReadDataNotifyCancel:
+        __KTRACE_OPT(KUSB, Kern::Printf("DoCancel Direction %d endpoints: 0x%x",direction, aReqNo));
+
+        if (((TInt)aBuff)==KUsbcScEndpointZero) // EP0 is bi-directional, so pick correct buffer for call type
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("DoCancel Cancel Endpoint 0/%d",direction));
+            iEp0Endpoint->AbortTransfer();
+            if (direction==KUsbcScIn)
+                aBuff=iEP0InBuff;
+            else
+                aBuff=iEP0OutBuff;
+            } 
+        else if ((TInt)aBuff >= iNumBuffers) // check buff no range.
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("DoCancel Error: Bad buffer number"));
+            return KErrArgument;
+            }
+
+        if ((iBuffers[aBuff].iDirection&1)!=direction) // Does direction match call type?
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("DoCancel Error: Bad buffer direction"));
+            return KErrArgument;
+            }    
+        iBuffers[aBuff].iStatusList.CancelQueued();
+        iBuffers[aBuff].Cancel(KErrCancel);
+        
+        return KErrNone;
+
+    case RDevUsbcScClient::ERequestAlternateDeviceStatusNotifyCancel:
+        __KTRACE_OPT(KUSB, Kern::Printf("DoCancel: ERequestAlternateDeviceStatusNotify 0x%x", aReqNo));
+        iDeviceStatusNeeded = EFalse;
+        iStatusFifo->FlushQueue();
+        if (iStatusChangePtr)
+            {
+            TInt deviceState = iController->GetDeviceStatus();
+            r = Kern::ThreadRawWrite(iClient, iStatusChangePtr, &deviceState, sizeof(deviceState), iClient);
+            if (r != KErrNone)
+                PanicClientThread(r);
+            iStatusChangePtr = NULL; 
+            }
+    break;
+
+    case RDevUsbcScClient::ERequestReEnumerateCancel:
+        __KTRACE_OPT(KUSB, Kern::Printf("DoCancel ERequestReEnumerate: 0x%x", aReqNo));
+    break;
+
+    case RDevUsbcScClient::ERequestEndpointStatusNotifyCancel:
+        __KTRACE_OPT(KUSB, Kern::Printf("DoCancel ERequestEndpointStatusNotify: 0x%x", aReqNo));
+        CancelNotifyEndpointStatus();
+    break;
+
+     case RDevUsbcScClient::ERequestOtgFeaturesNotifyCancel:
+        __KTRACE_OPT(KUSB, Kern::Printf("DoCancel ERequestOtgFeaturesNotify: 0x%x", aReqNo));
+        CancelNotifyOtgFeatures();
+    break;
+
+    default:
+        __KTRACE_OPT(KUSB, Kern::Printf("DoCancel Unknown! 0x%x", aReqNo));
+        return KErrArgument;
+        }
+
+    Kern::RequestComplete(iClient,iRequestStatus[aReqNo & ~RDevUsbcScClient::ERequestCancel], KErrCancel);
+    return r;
+    }
+
+
+void DLddUsbcScChannel::CancelNotifyEndpointStatus()
+    {
+    if (iEndpointStatusChangePtr)
+        {
+        TUint epBitmap = 0;
+        for (TInt i = 1; i <= iNumberOfEndpoints; i++)
+            {
+            TInt v = iController->GetEndpointStatus(this, iEndpoint[i]->RealEpNumber());
+            TUint b;
+            (v == EEndpointStateStalled) ? b = 1 : b = 0;
+            epBitmap |= b << i;
+            }
+        TInt r=Kern::ThreadRawWrite(iClient, iEndpointStatusChangePtr, (TUint8*) &epBitmap, sizeof(epBitmap), iClient);
+        if (r != KErrNone)
+            PanicClientThread(r);
+        iEndpointStatusChangePtr = NULL;
+        }
+    }
+
+void DLddUsbcScChannel::CancelNotifyOtgFeatures()
+    {
+    if (iOtgFeatureChangePtr)
+        {
+        TUint8 features;
+        iController->GetCurrentOtgFeatures(features);
+        TInt r=Kern::ThreadRawWrite(iClient, iOtgFeatureChangePtr, (TUint8*)&features, sizeof(features), iClient);
+        if (r != KErrNone)
+            PanicClientThread(r);
+        iOtgFeatureChangePtr = NULL;
+        }
+    }
+
+
+
+//
+// DoControl - Synchronous requests
+//
+// Called from HandleMsg.
+
+TInt DLddUsbcScChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DoControl: %d", aFunction));
+
+    TInt r = KErrNone;
+    TInt ep, param;
+    TUsbcScEndpoint* pEndpoint;
+    TPtrC8 pZeroDesc(NULL, 0);
+    TEndpointDescriptorInfo epInfo;
+    TUsbcScIfcInfo ifcInfo;
+    TCSDescriptorInfo desInfo;
+    TUsbcEndpointResource epRes;
+
+    switch (aFunction)
+        {
+    case RDevUsbcScClient::EControlEndpointZeroRequestError:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointZeroRequestError"));
+        r = KErrNone;
+        if (iOwnsDeviceControl || (iValidInterface && iDeviceState == UsbShai::EUsbPeripheralStateConfigured))
+            {
+            iController->Ep0Stall(this);
+            }
+        else
+            {
+            if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured)
+                r = KErrUsbDeviceNotConfigured;
+            else
+                r = KErrUsbInterfaceNotReady;
+            }
+        break;
+
+    case RDevUsbcScClient::EControlGetAlternateSetting:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetAlternateSetting"));
+        if (iValidInterface && iDeviceState == UsbShai::EUsbPeripheralStateConfigured)
+            {
+            r = iController->GetInterfaceNumber(this, param);
+            if (r == KErrNone)
+                {
+                r = Kern::ThreadRawWrite(iClient, a1, &param, sizeof(param), iClient);
+                if (r != KErrNone)
+                    PanicClientThread(r);
+                }
+            }
+        else
+            {
+            if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured)
+                r = KErrUsbDeviceNotConfigured;
+            else
+                r = KErrUsbInterfaceNotReady;
+            }
+        break;
+
+    case RDevUsbcScClient::EControlDeviceStatus:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceStatus"));
+        param = iController->GetDeviceStatus();
+        r = Kern::ThreadRawWrite(iClient, a1, &param, sizeof(param), iClient);
+        if (r != KErrNone)
+            PanicClientThread(r);
+        break;
+
+    case RDevUsbcScClient::EControlEndpointStatus:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointStatus"));
+        if (iValidInterface && ValidEndpoint((TInt) a1))
+            {
+            pEndpoint = iEndpoint[(TInt)a1];
+            if (pEndpoint == NULL)
+                r = KErrNotSupported;
+            else
+                {
+                param = iController->GetEndpointStatus(this, iEndpoint[(TInt)a1]->RealEpNumber());
+                r = Kern::ThreadRawWrite(iClient, a2, &param, sizeof(param), iClient);
+                if (r != KErrNone)
+                    PanicClientThread(r);
+                }
+            }
+        else
+            {
+            if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured)
+                r = KErrUsbDeviceNotConfigured;
+            else
+                r = KErrUsbInterfaceNotReady;
+            }
+        break;
+
+    case RDevUsbcScClient::EControlEndpointCaps:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointCaps"));
+        r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
+        if (r != KErrNone)
+            PanicClientThread(r);
+        iController->EndpointCaps(this, *((TDes8*) a1));
+        break;
+
+    case RDevUsbcScClient::EControlDeviceCaps:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceCaps"));
+        r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
+        if (r != KErrNone)
+            PanicClientThread(r);
+        iController->DeviceCaps(this, *((TDes8*) a1));
+        break;
+
+    case RDevUsbcScClient::EControlSendEp0StatusPacket:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSendEp0StatusPacket"));
+        iController->SendEp0StatusPacket(this);
+        break;
+
+    case RDevUsbcScClient::EControlHaltEndpoint:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlHaltEndpoint"));
+        if (iValidInterface && ValidEndpoint((TInt) a1))
+            {
+            r = iController->HaltEndpoint(this, iEndpoint[(TInt)a1]->RealEpNumber());
+            }
+        else
+            {
+            if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured)
+                r = KErrUsbDeviceNotConfigured;
+            else
+                r = KErrUsbInterfaceNotReady;
+            }
+        break;
+
+    case RDevUsbcScClient::EControlClearHaltEndpoint:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlClearHaltEndpoint"));
+        if (iValidInterface && ValidEndpoint((TInt) a1))
+            {
+            r = iController->ClearHaltEndpoint(this, iEndpoint[(TInt)a1]->RealEpNumber());
+            }
+        else
+            {
+            if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured)
+                r = KErrUsbDeviceNotConfigured;
+            else
+                r = KErrUsbInterfaceNotReady;
+            }
+        break;
+
+    case RDevUsbcScClient::EControlDumpRegisters:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlDumpRegisters"));
+        iController->DumpRegisters();
+        break;
+
+    case RDevUsbcScClient::EControlReleaseDeviceControl:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlReleaseDeviceControl"));
+        iController->ReleaseDeviceControl(this);
+        iOwnsDeviceControl = EFalse;
+        break;
+
+    case RDevUsbcScClient::EControlEndpointZeroMaxPacketSizes:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointZeroMaxPacketSizes"));
+        r = iController->EndpointZeroMaxPacketSizes();
+        break;
+
+    case RDevUsbcScClient::EControlSetEndpointZeroMaxPacketSize:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetEndpointZeroMaxPacketSize"));
+        r = iController->SetEndpointZeroMaxPacketSize(reinterpret_cast<TInt>(a1));
+        break;
+
+    case RDevUsbcScClient::EControlGetEndpointZeroMaxPacketSize:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetEndpointZeroMaxPacketSize"));
+        r = iController->Ep0PacketSize();
+        break;
+
+    case RDevUsbcScClient::EControlGetDeviceDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetDeviceDescriptor"));
+        r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
+        if (r != KErrNone)
+            PanicClientThread(r);
+        r = iController->GetDeviceDescriptor(iClient, *((TDes8*) a1));
+        break;
+
+    case RDevUsbcScClient::EControlSetDeviceDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceDescriptor"));
+        BREAK_IF_NULL_ARG(a1,r);
+        r = iController->SetDeviceDescriptor(iClient, *((TDes8*) a1));
+        break;
+
+    case RDevUsbcScClient::EControlGetDeviceDescriptorSize:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetDeviceDescriptorSize"));
+        BREAK_IF_NULL_ARG(a1,r);
+        r = iController->GetDeviceDescriptorSize(iClient, *((TDes8*) a1));
+        break;
+
+    case RDevUsbcScClient::EControlGetConfigurationDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetConfigurationDescriptor"));
+        r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0 , 0, iClient);
+        if (r != KErrNone)
+            PanicClientThread(r);
+        r = iController->GetConfigurationDescriptor(iClient, *((TDes8*) a1));
+        break;
+
+    case RDevUsbcScClient::EControlGetConfigurationDescriptorSize:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetConfigurationDescriptorSize"));
+        if (a1 != NULL)
+            {
+            r = iController->GetConfigurationDescriptorSize(iClient, *((TDes8*) a1));
+            }
+        else
+            r = KErrArgument;
+        break;
+
+    case RDevUsbcScClient::EControlSetConfigurationDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetConfigurationDescriptor"));
+        r = iController->SetConfigurationDescriptor(iClient, *((TDes8*) a1));
+        break;
+
+    case RDevUsbcScClient::EControlGetInterfaceDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetInterfaceDescriptor"));
+        r = iController->GetInterfaceDescriptor(iClient, this, (TInt) a1, *((TDes8*) a2));
+        break;
+
+    case RDevUsbcScClient::EControlGetInterfaceDescriptorSize:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetInterfaceDescriptorSize"));
+        r = iController->GetInterfaceDescriptorSize(iClient, this, (TInt) a1, *(TDes8*) a2);
+        break;
+
+    case RDevUsbcScClient::EControlSetInterfaceDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetInterfaceDescriptor"));
+        r = iController->SetInterfaceDescriptor(iClient, this, (TInt) a1, *((TDes8*) a2));
+        break;
+
+    case RDevUsbcScClient::EControlGetEndpointDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetEndpointDescriptor"));
+        r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
+        if (r != KErrNone)
+            PanicClientThread(r);
+        ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
+        r = (ep<0)?ep:iController->GetEndpointDescriptor(iClient, this, epInfo.iSetting,
+                                               ep, *(TDes8*) epInfo.iArg);
+        break;
+
+    case RDevUsbcScClient::EControlGetEndpointDescriptorSize:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetEndpointDescriptorSize"));
+        r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
+        if (r != KErrNone)
+            PanicClientThread(r);
+        ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
+        r = iController->GetEndpointDescriptorSize(iClient, this, epInfo.iSetting,
+                                                   ep, *(TDes8*) epInfo.iArg);
+        break;
+
+    case RDevUsbcScClient::EControlSetEndpointDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetEndpointDescriptor"));
+        r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
+        if (r != KErrNone)
+            PanicClientThread(r);
+        ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
+        r = iController->SetEndpointDescriptor(iClient, this, epInfo.iSetting,
+                                               ep, *(TDes8*)epInfo.iArg);
+        break;
+
+    case RDevUsbcScClient::EControlGetDeviceQualifierDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetDeviceQualifierDescriptor"));
+        r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
+        if (r != KErrNone)
+            PanicClientThread(r);
+        r = iController->GetDeviceQualifierDescriptor(iClient, *((TDes8*) a1));
+        break;
+
+    case RDevUsbcScClient::EControlSetDeviceQualifierDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceQualifierDescriptor"));
+        BREAK_IF_NULL_ARG(a1,r);
+        r = iController->SetDeviceQualifierDescriptor(iClient, *((TDes8*) a1));
+        break;
+
+    case RDevUsbcScClient::EControlGetOtherSpeedConfigurationDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetOtherSpeedConfigurationDescriptor"));
+        r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0 , 0, iClient);
+        if (r != KErrNone)
+            PanicClientThread(r);
+        r = iController->GetOtherSpeedConfigurationDescriptor(iClient, *((TDes8*) a1));
+        break;
+
+    case RDevUsbcScClient::EControlSetOtherSpeedConfigurationDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetOtherSpeedConfigurationDescriptor"));
+        r = iController->SetOtherSpeedConfigurationDescriptor(iClient, *((TDes8*) a1));
+        break;
+
+
+    case RDevUsbcScClient::EControlGetCSInterfaceDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSInterfaceDescriptor"));
+        r = iController->GetCSInterfaceDescriptorBlock(iClient, this, (TInt) a1, *((TDes8*) a2));
+        break;
+
+    case RDevUsbcScClient::EControlGetCSInterfaceDescriptorSize:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSInterfaceDescriptorSize"));
+        r = iController->GetCSInterfaceDescriptorBlockSize(iClient, this, (TInt) a1, *(TDes8*) a2);
+        break;
+
+    case RDevUsbcScClient::EControlGetCSEndpointDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSEndpointDescriptor"));
+        r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
+        if (r != KErrNone)
+            PanicClientThread(r);
+        ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
+        r = iController->GetCSEndpointDescriptorBlock(iClient, this, epInfo.iSetting,
+                                                      ep, *(TDes8*) epInfo.iArg);
+        break;
+
+    case RDevUsbcScClient::EControlGetCSEndpointDescriptorSize:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSEndpointDescriptorSize"));
+        r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
+        if (r != KErrNone)
+            PanicClientThread(r);
+        ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
+        r = iController->GetCSEndpointDescriptorBlockSize(iClient, this, epInfo.iSetting,
+                                                          ep, *(TDes8*) epInfo.iArg);
+        break;
+
+    case RDevUsbcScClient::EControlSignalRemoteWakeup:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSignalRemoteWakeup"));
+        r = iController->SignalRemoteWakeup();
+        break;
+
+    case RDevUsbcScClient::EControlDeviceDisconnectFromHost:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceDisconnectFromHost"));
+        r = iController->UsbDisconnect();
+        break;
+
+    case RDevUsbcScClient::EControlDeviceConnectToHost:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceConnectToHost"));
+        r = iController->UsbConnect();
+        break;
+
+    case RDevUsbcScClient::EControlDevicePowerUpUdc:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlDevicePowerUpUdc"));
+        r = iController->PowerUpUdc();
+        break;
+
+    case RDevUsbcScClient::EControlSetDeviceControl:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceControl"));
+        r = iController->SetDeviceControl(this);
+        if (r == KErrNone)
+            {
+            iOwnsDeviceControl = ETrue;
+            if (iEp0Endpoint == NULL)
+                {
+                __KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceControl"));
+                r = SetupEp0();
+                if (r != KErrNone)
+                    {
+                    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: SetupEp0() failed"));
+                    iController->ReleaseDeviceControl(this);
+                    iOwnsDeviceControl=EFalse;
+                    DestroyEp0();
+                    }
+                }
+            }
+        else
+            r = KErrInUse;
+        break;
+
+    case RDevUsbcScClient::EControlCurrentlyUsingHighSpeed:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlCurrentlyUsingHighSpeed"));
+        r = iController->CurrentlyUsingHighSpeed();
+        break;
+
+    case RDevUsbcScClient::EControlSetInterface:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetInterface"));
+        r = Kern::ThreadRawRead(iClient, a2, &ifcInfo, sizeof(ifcInfo));
+        if (r != KErrNone)
+            PanicClientThread(r);
+        r = SetInterface((TInt) a1, &ifcInfo);
+        break;
+
+    case RDevUsbcScClient::EControlReleaseInterface: 
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlReleaseInterface"));
+        if (!iRealizeCalled)
+            {
+            r = iController->ReleaseInterface(this, (TInt) a1);
+            if (r == KErrNone)
+                {
+                DestroyInterface((TUint) a1);
+                }
+            else
+                {
+                __KTRACE_OPT(KPANIC, Kern::Printf("  Error in PIL: LDD interface won't be released."));
+                }
+            }
+        else
+            r = KErrUsbAlreadyRealized;
+        break;
+
+    case RDevUsbcScClient::EControlSetCSInterfaceDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetCSInterfaceDescriptor"));
+        r = Kern::ThreadRawRead(iClient, a1, &desInfo, sizeof(desInfo));
+        if (r != KErrNone)
+            PanicClientThread(r);
+        r = iController->SetCSInterfaceDescriptorBlock(iClient, this, desInfo.iSetting,
+                                                       *reinterpret_cast<const TDes8*>(desInfo.iArg),
+                                                       desInfo.iSize);
+        break;
+
+    case RDevUsbcScClient::EControlSetCSEndpointDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetCSEndpointDescriptor"));
+        r = Kern::ThreadRawRead(iClient, a1, &desInfo, sizeof(desInfo));
+        if (r != KErrNone)
+            PanicClientThread(r);
+        ep = EpFromAlternateSetting(desInfo.iSetting, desInfo.iEndpoint);
+        r = iController->SetCSEndpointDescriptorBlock(iClient, this, desInfo.iSetting, ep,
+                                                      *reinterpret_cast<const TDes8*>(desInfo.iArg),
+                                                      desInfo.iSize);
+        break;
+
+    case RDevUsbcScClient::EControlGetStringDescriptorLangId:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetStringDescriptorLangId"));
+        r = iController->GetStringDescriptorLangId(iClient, *((TDes8*) a1));
+        break;
+
+    case RDevUsbcScClient::EControlSetStringDescriptorLangId:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetStringDescriptorLangId"));
+        r = iController->SetStringDescriptorLangId(reinterpret_cast<TUint>(a1));
+        break;
+
+    case RDevUsbcScClient::EControlGetManufacturerStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetManufacturerStringDescriptor"));
+        r = iController->GetManufacturerStringDescriptor(iClient, *((TPtr8*) a1));
+        break;
+
+    case RDevUsbcScClient::EControlSetManufacturerStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetManufacturerStringDescriptor"));
+        r = iController->SetManufacturerStringDescriptor(iClient, *((TPtr8*) a1));
+        break;
+
+    case RDevUsbcScClient::EControlRemoveManufacturerStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveManufacturerStringDescriptor"));
+        r = iController->RemoveManufacturerStringDescriptor();
+        break;
+
+    case RDevUsbcScClient::EControlGetProductStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetProductStringDescriptor"));
+        r = iController->GetProductStringDescriptor(iClient, *((TPtr8*) a1));
+        break;
+
+    case RDevUsbcScClient::EControlSetProductStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetProductStringDescriptor"));
+        r = iController->SetProductStringDescriptor(iClient, *((TPtr8*) a1));
+        break;
+
+    case RDevUsbcScClient::EControlRemoveProductStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveProductStringDescriptor"));
+        r = iController->RemoveProductStringDescriptor();
+        break;
+
+    case RDevUsbcScClient::EControlGetSerialNumberStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetSerialNumberStringDescriptor"));
+        r = iController->GetSerialNumberStringDescriptor(iClient, *((TPtr8*) a1));
+        break;
+
+    case RDevUsbcScClient::EControlSetSerialNumberStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetSerialNumberStringDescriptor"));
+        r = iController->SetSerialNumberStringDescriptor(iClient, *((TPtr8*) a1));
+        break;
+
+    case RDevUsbcScClient::EControlRemoveSerialNumberStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveSerialNumberStringDescriptor"));
+        r = iController->RemoveSerialNumberStringDescriptor();
+        break;
+
+    case RDevUsbcScClient::EControlGetConfigurationStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetConfigurationStringDescriptor"));
+        r = iController->GetConfigurationStringDescriptor(iClient, *((TPtr8*) a1));
+        break;
+
+    case RDevUsbcScClient::EControlSetConfigurationStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetConfigurationStringDescriptor"));
+        r = iController->SetConfigurationStringDescriptor(iClient, *((TPtr8*) a1));
+        break;
+
+    case RDevUsbcScClient::EControlRemoveConfigurationStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveConfigurationStringDescriptor"));
+        r = iController->RemoveConfigurationStringDescriptor();
+        break;
+
+    case RDevUsbcScClient::EControlGetStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetStringDescriptor"));
+        r = iController->GetStringDescriptor(iClient, (TUint8) (TInt) a1, *((TPtr8*) a2));
+        break;
+
+    case RDevUsbcScClient::EControlSetStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetStringDescriptor"));
+        r = iController->SetStringDescriptor(iClient, (TUint8) (TInt) a1, *((TPtr8*) a2));
+        break;
+
+    case RDevUsbcScClient::EControlRemoveStringDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveStringDescriptor"));
+        r = iController->RemoveStringDescriptor((TUint8) (TInt) a1);
+        break;
+
+    case RDevUsbcScClient::EControlQueryEndpointResourceUse:
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlQueryEndpointResourceUse"));
+        epRes = (TUsbcEndpointResource)((TInt) a2);
+        TInt realEp=-1;
+        r = GetRealEpForEpResource((TInt)a1, realEp);
+        if (r==KErrNone)
+            r = iController->QueryEndpointResource(this, realEp, epRes);
+        break;
+        }
+    case RDevUsbcScClient::EControlSetOtgDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlSetOtgDescriptor"));
+        r = iController->SetOtgDescriptor(iClient, *((const TDesC8*)a1));
+        break;
+
+    case RDevUsbcScClient::EControlGetOtgDescriptor:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetOtgDescriptor"));
+        r = iController->GetOtgDescriptor(iClient, *((TDes8*)a1));
+        break;
+
+    case RDevUsbcScClient::EControlGetOtgFeatures:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlGetOtgFeatures"));
+        r = iController->GetOtgFeatures(iClient, *((TDes8*)a1));
+        break;
+
+    case RDevUsbcScClient::EControlRealizeInterface:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlRealizeInterface"));
+        r = RealizeInterface();
+        break;
+    case RDevUsbcScClient::EControlStartNextInAlternateSetting:
+        __KTRACE_OPT(KUSB, Kern::Printf("EControlStartNextInAlternateSetting"));
+        r = StartNextInAlternateSetting();
+        break;
+
+    default:
+        __KTRACE_OPT(KUSB, Kern::Printf("Function code not supported"));
+        r = KErrNotSupported;
+        }
+
+    return r;
+    }
+// end DoControl.
+
+
+
+//
+// Overriding DObject virtual
+//
+TInt DLddUsbcScChannel::RequestUserHandle(DThread* aThread, TOwnerType /*aType*/)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::RequestUserHandle"));
+    // The USB client LDD is not designed for a channel to be shared between
+    // threads. It saves a pointer to the current thread when it is opened, and
+    // uses this to complete any asynchronous requests.
+    // It is therefore not acceptable for the handle to be duplicated and used
+    // by another thread:
+    if (aThread == iClient)
+        {
+        return KErrNone;
+        }
+    else
+        {
+        return KErrAccessDenied;
+        }
+    }
+
+inline TInt DLddUsbcScChannel::GetRealEpForEpResource(TInt aEndpoint, TInt& aRealEp)
+    {
+    if (iEndpoint) // if we've enumerated at least once, proceed as normal.
+        {
+        if  (aEndpoint <= iNumberOfEndpoints && aEndpoint >= 0)
+            {
+            aRealEp=iEndpoint[aEndpoint]->RealEpNumber();
+            return KErrNone;
+            }
+        }
+    else // Assume alternate setting 0.
+        {
+        if (iAlternateSettingList)   // Check it has been set up.
+            {
+            TUsbcScAlternateSetting* alt = iAlternateSettingList->iHead;
+            if (alt &&  (aEndpoint <= alt->iNumberOfEndpoints && aEndpoint >= 0))
+                {
+                aRealEp= alt->iEndpoint[aEndpoint]->RealEpNumber();
+                return KErrNone;
+                }
+            }
+        }
+    return KErrUsbDeviceNotConfigured;
+    }
+
+
+TUsbcEndpointInfoArray::TUsbcEndpointInfoArray(const TUsbcScEndpointInfo* aData, TInt aDataSize)
+    {
+    iType = EUsbcScEndpointInfo;
+    iData = (TUint8*) aData;    
+    if (aDataSize>0)
+        iDataSize = aDataSize;
+    else
+        iDataSize = sizeof(TUsbcScEndpointInfo);
+    }
+
+
+//
+// SetInterface
+//
+// Called from DoControl.  Sets the configuration of a given Interface.                    // Needs changing
+// All interfaces must be configured before one can be used.  
+//
+
+TInt DLddUsbcScChannel::SetInterface(TInt aInterfaceNumber, TUsbcScIfcInfo* aInfoBuf)
+    {
+    // Copy interface description.
+
+    if (iRealizeCalled)
+        return KErrUsbAlreadyRealized;
+
+    if (!iAlternateSettingList)
+        {
+        iAlternateSettingList = new TUsbcScAlternateSettingList;
+        if (iAlternateSettingList==NULL)
+            {
+            return KErrNoMemory;
+            }
+        }
+
+    // Read descriptor in
+    TUsbcScInterfaceInfoBuf ifc_info_buf;
+    TUsbcScInterfaceInfoBuf* const ifc_info_buf_ptr = aInfoBuf->iInterfaceData;
+    const TInt srcLen = Kern::ThreadGetDesLength(iClient, ifc_info_buf_ptr);
+
+    __KTRACE_OPT(KUSB, Kern::Printf("SetInterface srcLen = %d len = %d", srcLen, ifc_info_buf.Length() ));
+
+    if (srcLen < ifc_info_buf.Length())
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("SetInterface can't copy"));
+        PanicClientThread(EDesOverflow);
+        }
+
+    TInt r = Kern::ThreadDesRead(iClient, ifc_info_buf_ptr, ifc_info_buf, 0, KChunkShiftBy0);
+    if (r != KErrNone)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("SetInterface Copy failed reason=%d", r));
+        PanicClientThread(r);
+        }
+
+    // The list of endpoints is within the interface info.
+    TUsbcScEndpointInfo* pEndpointData = ifc_info_buf().iEndpointData;
+
+    const TInt num_endpoints = ifc_info_buf().iTotalEndpointsUsed;
+    __KTRACE_OPT(KUSB, Kern::Printf("SetInterface num_endpoints=%d", num_endpoints));
+    if (num_endpoints>KMaxEndpointsPerClient)
+        return KErrOverflow;
+
+
+    // Initialize real ep numbers list.
+    TInt i;
+    TInt real_ep_numbers[KMaxEndpointsPerClient+1]; // range 1->KMaxEndpointsPerClient (0 not used)
+    for (i=0; i<=KMaxEndpointsPerClient; i++)
+        real_ep_numbers[i] = -1;
+
+
+    // See if PIL will accept this interface
+    __KTRACE_OPT(KUSB, Kern::Printf("SetInterface Calling controller"));
+    TUsbcEndpointInfoArray endpointData = TUsbcEndpointInfoArray(ifc_info_buf().iEndpointData);
+
+    r = iController->SetInterface(this,
+                                  iClient,
+                                  aInterfaceNumber,
+                                  ifc_info_buf().iClass,
+                                  aInfoBuf->iString,
+                                  (TInt) ifc_info_buf().iTotalEndpointsUsed,
+                                  endpointData,
+                                  &real_ep_numbers[0],
+                                  ifc_info_buf().iFeatureWord);
+
+    __KTRACE_OPT(KUSB, Kern::Printf("SetInterface controller returned %d", r));
+    if (r != KErrNone)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("SetInterface failed reason=%d", r));
+        return r;
+        }
+
+    // create alternate setting record
+    TUsbcScAlternateSetting* alternateSettingListRec = new TUsbcScAlternateSetting;
+    if (!alternateSettingListRec)
+        {
+        r = KErrNoMemory;
+        goto ReleaseInterface;
+        }
+    
+    // other endpoints
+    for (TInt i = 1; i <= num_endpoints; i++, pEndpointData++)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("SetInterface for ep=%d", i));
+
+        if ((pEndpointData->iType==UsbShai::KUsbEpTypeControl)
+            || (pEndpointData->iDir != UsbShai::KUsbEpDirIn && pEndpointData->iDir != UsbShai::KUsbEpDirOut)
+            || (pEndpointData->iSize > 1024) || (pEndpointData->iSize<=0))
+            {
+            r = KErrUsbBadEndpoint;
+            goto CleanUp;
+            }
+        // Check data
+
+        TUint* bufferSize = &(pEndpointData->iBufferSize);
+        if (*bufferSize==0)
+            *bufferSize= KUsbcScDefaultBufferSize;
+
+        TInt pageSize = Kern::RoundToPageSize(1);
+        // Round buffersize up to nearest pagesize.
+        *bufferSize = (*bufferSize+pageSize-1) & ~(pageSize-1);
+
+        TUsbcScEndpoint* ep = new TUsbcScEndpoint(this, iController, pEndpointData, i);
+        alternateSettingListRec->iEndpoint[i] = ep;
+        if (!ep)
+            {
+            r = KErrNoMemory;
+            goto CleanUp;
+            }
+        if (ep->Construct() != KErrNone)
+            {
+            r = KErrNoMemory;
+            goto CleanUp;
+            }
+
+    
+        __KTRACE_OPT(KUSB, Kern::Printf("SetInterface for ep=%d rec=0x%08x ep==0x%08x",
+                                        i, alternateSettingListRec, ep));
+        }
+
+    if (iAlternateSettingList->iHead)
+        {
+        iAlternateSettingList->iTail->iNext = alternateSettingListRec;
+        alternateSettingListRec->iPrevious = iAlternateSettingList->iTail;
+        iAlternateSettingList->iTail = alternateSettingListRec;    
+        }
+    else
+        {
+        iAlternateSettingList->iHead = alternateSettingListRec;    
+        iAlternateSettingList->iTail = alternateSettingListRec;    
+        }    
+    
+    alternateSettingListRec->iNext = NULL;
+    alternateSettingListRec->iSetting = aInterfaceNumber;
+    alternateSettingListRec->iNumberOfEndpoints = num_endpoints;
+
+    // Record the 'real' endpoint number used by the PDD in both the Ep and
+    // the Req callback:
+    for (TInt i = 1; i <= num_endpoints; i++)
+        {
+        alternateSettingListRec->iEndpoint[i]->SetRealEpNumber(real_ep_numbers[i]);
+        }
+
+    return KErrNone;
+
+ CleanUp:
+    delete alternateSettingListRec;
+    //Fall Through
+
+ ReleaseInterface:
+#if _DEBUG
+    TInt r1 = iController->ReleaseInterface(this, aInterfaceNumber);
+    __KTRACE_OPT(KUSB, Kern::Printf("Release Interface controller returned %d", r1));
+#else
+    (void)    iController->ReleaseInterface(this, aInterfaceNumber);
+#endif
+    return r;
+    }
+// end SetInterface
+
+
+
+#ifdef _DEBUG
+void RealizeInterface_Dump(TUint* aMem)
+    {
+    TUint *mem= NULL;
+    __KTRACE_OPT(KUSB, mem = aMem);
+    if (mem!=NULL)
+        {
+        TInt j;
+         Kern::Printf("Final chunk header State:");
+        for (j=0; j<30; j+=8)
+             Kern::Printf("%2x: %8x %8x %8x %8x %8x %8x %8x %8x", j, mem[j], mem[j+1], mem[j+2], mem[j+3], mem[j+4], mem[j+5], mem[j+6], mem[j+7] );
+        };
+    };
+#endif
+
+
+/*
+Chunk Created, filled with structure, and passed back to userside.
+*/
+TInt DLddUsbcScChannel::RealizeInterface(void)
+{
+    if (iRealizeCalled) 
+        return KErrUsbAlreadyRealized;
+
+    TRealizeInfo bufInfo;
+    
+    TInt errorOrChunk = KErrNone;
+    TBool openedCS = EFalse;
+    TInt offset =0;
+        
+    // Start by creating a temporary scratchpad for endpoint calculations.
+    bufInfo.Init(iAlternateSettingList);
+
+    // Fill in our scratchpad with all the required endpoints, sorting them
+    // in order of size required.
+    errorOrChunk = bufInfo.CopyAndSortEndpoints();
+    if (errorOrChunk!=KErrNone)
+        {
+        goto realize_end;
+        }
+
+    // We now have endpoints sorted in order of size for each altsetting.
+    // The very largest for each endpoint will share the first buffer, and all of
+    // the second largest ends points will share the second buffer, and so on.
+    // Find the highest buffer size for each row, to determine the buffer size,
+    // and keep a total of total space needed. 
+    bufInfo.CalcBuffSizes();
+
+    // We now have the max sizes wanted for each endpoint buffer.
+    // we also have to total size for all endpoints.
+    // and finally we have the total number of buffers.
+
+    // Add on size for header, then add on size for guard pages.
+    bufInfo.iTotalSize+= KHeaderSize + bufInfo.iTotalBuffers * KGuardSize;
+
+    // Create shared Chunk .  .  .  .  .  .  .  .  .  . 
+    if (iChunkInfo==NULL)
+        {
+            NKern::ThreadEnterCS();
+            openedCS = ETrue;
+            errorOrChunk = TUsbcScChunkInfo::New(iChunkInfo, bufInfo.iTotalSize, (DLogicalDevice*) iDevice);
+            if (errorOrChunk!=KErrNone)
+                {
+                goto realize_end;
+                }
+        }
+    else
+        {
+        // As of writing, the was no way for iChunk to be anything other then NULL.  
+        // You cannot 'unrealise' and iChunk cannot be set any other way.
+        Kern::Fault("DLddUsbcScChannel::RealizeInterface", __LINE__);
+        }
+
+    // Populate the shared chunk . .  . . . . . 
+
+
+    // First create chunk header.
+    errorOrChunk = iChunkInfo->ChunkAlloc(offset, KHeaderSize);
+    if (errorOrChunk!=KErrNone)
+        {
+        if (errorOrChunk==-KErrNoMemory)
+            errorOrChunk=KErrNoMemory;
+        goto realize_end;
+        } 
+
+
+    offset+=KHeaderSize + KGuardSize; // Also any more for EP0?
+
+    // Next, lay out the geometry of the chunk header.
+
+    bufInfo.LayoutChunkHeader(iChunkInfo);        
+
+
+    { // Scope ep0Size
+    TInt ep0Size=0;
+    
+    // Create K-side buffer table
+    if (!iBuffers)
+        iBuffers = (TUsbcScBuffer *) Kern::AllocZ(sizeof(TUsbcScBuffer) * (bufInfo.iTotalBuffers+2)); // +2 is for ep0.
+    if (!iBuffers)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("Realize: Error: Alloc iBufers failed!"));
+        errorOrChunk = KErrNoMemory;
+        goto realize_end;
+        }
+
+
+    errorOrChunk = SetupEp0();
+    if (errorOrChunk)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("Realize: SetupEp0 . ERROR %d",errorOrChunk));
+        goto realize_end;
+        }
+
+    ep0Size = iEp0Endpoint->EndpointInfo()->iSize;
+    __KTRACE_OPT(KUSB, Kern::Printf("Realize: Setup EP0. max packet size %d", ep0Size));
+
+    // Create EP0 buffers
+    iEP0OutBuff=bufInfo.iTotalBuffers;
+    errorOrChunk = iBuffers[iEP0OutBuff].Construct(KUsbcScBiOut,  this,   KUsbScEP0OutBufPos, KUsbScEP0OutBufEnd, ep0Size, ep0Size, ep0Size);
+    if (errorOrChunk)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("Realize: Setup EP0 Out. ERROR %d",errorOrChunk));
+        goto realize_end;
+        }
+
+    iBuffers[iEP0OutBuff].CreateChunkBufferHeader();
+    iBuffers[iEP0OutBuff].iCallback =  iEp0Endpoint->iRequestCallbackInfo;
+    ((TUsbcScBufferRecord*) &(
+                            bufInfo.iChunkStuct->iBufferOffset[KUsbcScEp0OutBuff*sizeof(TUsbcScBufferRecord)]
+                            )) ->Set(KUsbScEP0OutBufPos, KUsbScEP0OutBufEnd);
+
+
+    iEP0InBuff=bufInfo.iTotalBuffers+1;
+    errorOrChunk = iBuffers[iEP0InBuff].Construct( KUsbcScBiIn ,  this,   KUsbScEP0InBufPos , KUsbScEP0InBufEnd , ep0Size, ep0Size, ep0Size);    
+    if (errorOrChunk)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("Realize: Setup EP0 In. ERROR %d",errorOrChunk));
+        goto realize_end;
+        }
+    
+    iBuffers[iEP0InBuff].iCallback =  iEp0Endpoint->iRequestCallbackInfo;
+
+      ((TUsbcScBufferRecord*) &(
+                                  bufInfo.iChunkStuct->iBufferOffset[KUsbcScEp0InBuff*sizeof(TUsbcScBufferRecord)]
+                                ))->Set(KUsbScEP0InBufPos, KUsbScEP0InBufEnd);
+
+
+    } // end ep0Size scope
+
+    // Create resources and tables.  .   .   .   .   .
+    __KTRACE_OPT(KUSB, Kern::Printf("Realize: Create resources tables"));
+
+    { // scope of bufNum
+    // For each EP buffer
+    TInt buffNum=0;
+    TInt buffMinSize;
+    TInt endpointNumber;
+    TUsbcScEndpoint* endpointRecord;
+    TInt endpoint;
+    TInt inout;
+    TEndpointSortBufs* bufsd;
+    TUsbcScHdrEndpointRecord* epRecord;
+    for (endpoint=0; endpoint<bufInfo.iMaxEndpoints; endpoint++)  // endpoint = buf row.
+        {
+        for (inout=KUsbcScIn; inout<KUsbcScDirections; inout++)
+            {
+            buffMinSize = KUsbSc_BigBuff_MinimumRamRun;
+
+            TInt needed =  bufInfo.iBufs[inout].iSizes[endpoint];
+            if (needed) 
+                {
+                TInt bufStart = offset;
+
+                __KTRACE_OPT(KUSB, Kern::Printf("Realize:    buf row:%d inout %d, iBufferOffset[%d+2]=%x",endpoint, inout, buffNum, bufStart));
+
+                bufsd =  &(bufInfo.iBufs[inout]);
+                // and then point all endpoints that use it, towards it.
+                TInt altSetting;    
+                TUint maxReadSize = ~0;
+                for (altSetting=0; altSetting < bufInfo.iAltSettings; altSetting++)
+                    {
+                    endpointRecord =bufsd->iEp[altSetting*bufInfo.iMaxEndpoints + endpoint];
+                    if (endpointRecord)
+                        {
+                        endpointNumber = endpointRecord->EpNumber();
+                        endpointRecord->SetBuffer(&iBuffers[buffNum]);
+                
+                        epRecord = (TUsbcScHdrEndpointRecord*) &iChunkInfo->iChunkMem[
+                                                                (bufInfo.iAltSettingsTbl->iAltTableOffset[altSetting])     // i.e. Just after altSettingsTbl
+                                                                +sizeof(TInt)                                    // after number of endpoints field
+                                                                +(endpointNumber-1)*sizeof(TUsbcScHdrEndpointRecord)
+                                                                ];
+                        epRecord->iBufferNo = (TUint8) buffNum;
+
+                    TInt epType=(endpointRecord->EndpointInfo()->iType);
+                    epType= (epType& UsbShai::KUsbEpTypeControl)?KUsbScHdrEpTypeControl:
+                            (epType& UsbShai::KUsbEpTypeIsochronous)?KUsbScHdrEpTypeIsochronous:
+                            (epType& UsbShai::KUsbEpTypeBulk)?KUsbScHdrEpTypeBulk:
+                            (epType& UsbShai::KUsbEpTypeInterrupt)?KUsbScHdrEpTypeInterrupt:KUsbScHdrEpTypeUnknown;
+
+                    epRecord->iType = (inout+1) | (epType<<2);
+
+                    if (endpointRecord->EndpointInfo()->iReadSize)
+                        maxReadSize = (maxReadSize <= endpointRecord->EndpointInfo()->iReadSize) ? maxReadSize : endpointRecord->EndpointInfo()->iReadSize;
+                    
+                    __KTRACE_OPT(KUSB, Kern::Printf("Realize:      endpointNum %d in altSetting %d, alt table @ %d",
+                                                     endpointNumber, altSetting,bufInfo.iAltSettingsTbl->iAltTableOffset[altSetting]));
+                        }
+                    else
+                        {
+                        __KTRACE_OPT(KUSB, Kern::Printf("Realize:      endpointNum NA in altSetting %d", altSetting));
+                        }
+
+                    } // end for
+
+
+                // Alloc memory for buffer.
+                TInt grabSize = needed;
+                // Generally, a buffer fragmented into smaller memory regions will reduce the efficiency 
+                // of reading or writing data, and so avoiding the allocation of very small sections
+                // is advantageous.
+                // However, if only a small amount is being allocated to start with, it is likely
+                // smaller amounts of data are to be sent (reducing this advantage), and 1 memory page 
+                // is a much bigger proportion of the buffer, and so more worth allocating individually.
+
+                TInt minimumGrab;
+                if (needed<KUsbScBigBuffIs)
+                    {
+                    minimumGrab=Kern::RoundToPageSize(1);
+                    buffMinSize = KUsbSc_SmallBuff_MinimumRamRun; // 1k
+                    }
+                else
+                    {
+                    minimumGrab = buffMinSize+Kern::RoundToPageSize(1);
+                    }
+
+                // Grab required memory, in bits as big as possible, down to the minimum size. 
+                while (needed >= minimumGrab)
+                    {
+                    TInt r;
+                    r = iChunkInfo->ChunkAlloc(offset, grabSize);
+                    if (r==KErrNone)
+                        {
+                        offset+=grabSize;    
+                        needed-=grabSize;
+                        }
+                    else
+                        {
+                        if (r==-KErrNoMemory)
+                            {
+                            grabSize>>=1;
+                            }
+                        if ((grabSize<minimumGrab) || (r!=-KErrNoMemory))
+                            {
+                            errorOrChunk = r;
+                            goto realize_end;
+                            }
+                        }
+                    } // end while needed
+                
+                // Initialize buffer
+                iBuffers[buffNum].Construct(inout,  this,   bufStart, offset, buffMinSize, 0, maxReadSize);
+                iBuffers[buffNum].CreateChunkBufferHeader();
+                ((TUsbcScBufferRecord*) &(
+                                        bufInfo.iChunkStuct->iBufferOffset[(buffNum+2)*sizeof(TUsbcScBufferRecord)]
+                                        ))->Set(bufStart, offset);
+
+
+                // inc pointers for next buffer
+                buffNum++;
+                offset+=KGuardSize;
+                } // end if needed
+
+            } // end for inout
+        } // end for each buffer
+    } // scope of bufNum 
+
+#ifdef _DEBUG
+ RealizeInterface_Dump((TUint*) iChunkInfo->iChunkMem); // Debug only tracing
+#endif
+
+realize_end:
+    __KTRACE_OPT(KUSB, Kern::Printf("Realize: cleanup.  Err=%d", errorOrChunk));
+    // Here we clean up after either success, or after bailing out early.
+
+    bufInfo.Free();
+    
+    if (iChunkInfo)
+        {
+        if (errorOrChunk==KErrNone)
+            { 
+            // Everything is looking good - create RChunk for Userside.
+            errorOrChunk = Kern::MakeHandleAndOpen(iClient, iChunkInfo->iChunk);
+            iRealizeCalled = (errorOrChunk>=0);
+            } // endif errorOrChunk
+
+        if (errorOrChunk<0)  // If error, destroy the chunk.
+            {
+            iChunkInfo->Close();
+            // ChunkInfo will delete itself with DFC, but the pointer here is no longer needed.
+            iChunkInfo=NULL;
+
+            // Destroy iBuffers
+            if (iBuffers)
+                {
+                TInt i;
+                for (i=0; i<(iNumBuffers+2); i++) 
+                    {
+                    iBuffers[i].iStatusList.Destroy();
+                    }
+                Kern::Free(iBuffers);
+                iBuffers=NULL;
+                }
+
+            }
+        else
+            {
+            iNumBuffers = bufInfo.iTotalBuffers;
+            iValidInterface = ETrue;  // Let the games commence!
+            }
+
+        } // endif iChunkInfo
+    if (openedCS)
+        NKern::ThreadLeaveCS();
+
+    __KTRACE_OPT(KUSB, Kern::Printf("Realize: returning %x (%d)", errorOrChunk, errorOrChunk));
+    return errorOrChunk;
+} // End RealizeInterface
+
+
+//
+// DestroyAllInterfaces
+//
+
+void DLddUsbcScChannel::DestroyAllInterfaces()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DestroyAllInterfaces"));
+    // Removes all interfaces
+    if (iAlternateSettingList)
+        {
+        if (iAlternateSettingList->iHead != NULL)
+            {
+            TUsbcScAlternateSetting* alternateSettingListRec = iAlternateSettingList->iTail;
+            while (alternateSettingListRec)
+                {
+                iAlternateSettingList->iTail = alternateSettingListRec->iPrevious; 
+                // If this contains NULL now that is only possible if the record to be deleted was at the head
+                __KTRACE_OPT(KUSB, Kern::Printf("Release interface %d \n", alternateSettingListRec->iSetting));
+                iController->ReleaseInterface(this, alternateSettingListRec->iSetting);
+                delete alternateSettingListRec;
+                if (iAlternateSettingList->iTail == NULL) //No more interfaces left 
+                    break;
+                else
+                    {
+                    iAlternateSettingList->iTail->iNext = NULL;
+                    alternateSettingListRec = iAlternateSettingList->iTail;
+                    }
+                }
+            }
+        delete iAlternateSettingList;    
+        }
+
+    iNumberOfEndpoints = 0;
+    iAlternateSettingList = NULL;
+    iValidInterface = EFalse;
+
+    __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DestroyAllInterfaces done"));
+    }
+
+
+        
+
+
+//
+// DestroyInterface
+//
+
+void DLddUsbcScChannel::DestroyInterface(TUint aInterfaceNumber)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DestroyInterface \n"));
+    
+    if (iAlternateSetting == aInterfaceNumber)
+        {
+        ResetInterface(KErrUsbInterfaceNotReady);
+        iValidInterface = EFalse;
+        iNumberOfEndpoints = 0;
+        }
+    if (iAlternateSettingList)
+        {
+        TUsbcScAlternateSetting* alternateSettingListRec = iAlternateSettingList->iTail;
+        TUsbcScAlternateSetting* alternateSettingListRecFound = NULL;
+        while (alternateSettingListRec)
+            {
+            if (alternateSettingListRec->iSetting == aInterfaceNumber)
+                {
+                alternateSettingListRecFound = alternateSettingListRec;
+                if (alternateSettingListRec->iPrevious == NULL)    //Interface is at HEAD OF List, Should only be if Interface is also at Tail of list
+                    {
+                    iAlternateSettingList->iHead = alternateSettingListRec->iNext;    // Should be NULL
+                    if (alternateSettingListRec->iNext)
+                        iAlternateSettingList->iHead->iPrevious = NULL;
+                    }
+                else if (alternateSettingListRec->iNext == NULL) //Interface is at TAIL OF List
+                    {
+                    iAlternateSettingList->iTail = alternateSettingListRecFound->iPrevious;
+                    iAlternateSettingList->iTail->iNext = NULL;
+                    }
+                else    //Somewhere in the middle (would not expect this in normal operation, but here for completeness)
+                    {
+                    __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DestroyInterface Middle interface!\n"));
+                    alternateSettingListRec->iPrevious->iNext = alternateSettingListRec->iNext;
+                    alternateSettingListRec->iNext->iPrevious = alternateSettingListRec->iPrevious;
+                    }    
+
+                delete alternateSettingListRecFound;
+                break;
+                }
+             alternateSettingListRec = alternateSettingListRec->iPrevious;
+            }
+        }
+    }
+
+//
+// SetupEp0
+//
+
+TInt DLddUsbcScChannel::SetupEp0()
+    {
+    __ASSERT_ALWAYS(iEp0Endpoint==NULL, Kern::Fault("DLddUsbcScChannel::SetupEp0", __LINE__));
+
+    TUsbcScEndpointInfo ep0Info = TUsbcScEndpointInfo(UsbShai::KUsbEpTypeControl, UsbShai::KUsbEpDirBidirect);
+    ep0Info.iSize =  iController->Ep0PacketSize();
+
+    TUsbcScEndpoint* ep0 = new TUsbcScEndpoint(this, iController, &ep0Info, 0);
+    if (ep0 == NULL)
+        {
+        return KErrNoMemory;
+        }
+
+    TInt r = ep0->Construct();
+    if (r != KErrNone)
+        {
+        delete ep0;
+        return KErrNoMemory;
+        }
+
+    ep0->SetRealEpNumber(0);
+    ep0->SetBuffer(NULL); // Cannot find it this way.
+
+    iEp0Endpoint = ep0;
+    return KErrNone;
+    }
+
+//
+// DestroyEp0
+//
+
+void DLddUsbcScChannel::DestroyEp0()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DestroyEp0"));
+    delete iEp0Endpoint;
+    iEp0Endpoint = NULL;
+    }
+
+
+void DLddUsbcScChannel::RequestCallbackEp0(TAny* aDLddUsbcScChannel)
+    {
+    DLddUsbcScChannel* channel = (DLddUsbcScChannel*) aDLddUsbcScChannel;
+
+    __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::RequestCallbackEp0"));
+
+    if (channel->ChannelClosing())
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("Channel Closing: Completion not accepted!"));
+        return;
+        }
+
+    switch (channel->iEp0Endpoint->iRequestCallbackInfo->iTransferDir)
+        {
+    case UsbShai::EControllerWrite:
+        channel->iBuffers[channel->iEP0InBuff].CompleteWrite();
+        return;
+    case UsbShai::EControllerRead:
+        channel->iBuffers[channel->iEP0OutBuff].CompleteRead();
+        return;
+    default:
+        Kern::Printf("DLddUsbcScChannel::RequestCallbackEp0 - Unexpected completion direction %d",channel->iEp0Endpoint->iRequestCallbackInfo->iTransferDir);
+        Kern::Fault("DLddUsbcScChannel::RequestCallbackEp0", __LINE__);
+        } 
+    }
+
+
+
+
+
+
+//
+// EndpointStatusChangeCallback
+//
+
+void DLddUsbcScChannel::EndpointStatusChangeCallback(TAny* aDLddUsbcScChannel)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("EndpointStatusChangeCallback"));
+    DLddUsbcScChannel* dUsbc = (DLddUsbcScChannel*) aDLddUsbcScChannel;
+    if (dUsbc->iChannelClosing)
+        return;
+    TUint endpointState = dUsbc->iEndpointStatusCallbackInfo.State();
+    const TInt reqNo = (TInt) RDevUsbcScClient::ERequestEndpointStatusNotify;
+    if (dUsbc->iRequestStatus[reqNo])
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("EndpointStatusChangeCallback Notify status"));
+        DThread* client = dUsbc->iClient;
+        // set client descriptor length to zero
+        TInt r = Kern::ThreadRawWrite(client, dUsbc->iEndpointStatusChangePtr, &endpointState,
+                                      sizeof(TUint), client);
+        if (r != KErrNone)
+            dUsbc->PanicClientThread(r);
+        Kern::RequestComplete(dUsbc->iClient, dUsbc->iRequestStatus[reqNo], r);
+        dUsbc->iEndpointStatusChangePtr = NULL;
+        }
+    }
+
+
+//
+// StatusChangeCallback
+//
+
+void DLddUsbcScChannel::StatusChangeCallback(TAny* aDLddUsbcScChannel)
+    {
+    DLddUsbcScChannel* dUsbc = (DLddUsbcScChannel*) aDLddUsbcScChannel;
+    if (dUsbc->iChannelClosing)
+        return;
+
+    TUsbcDeviceState deviceState;
+    TInt i;
+     for (i = 0;
+          (i < KUsbcDeviceStateRequests) && ((deviceState = dUsbc->iStatusCallbackInfo.State(i)) != UsbShai::EUsbPeripheralNoState);
+          ++i)
+        {
+         __KTRACE_OPT(KUSB, Kern::Printf("StatusChangeCallBack status=%d", deviceState));
+        if (deviceState & KUsbAlternateSetting)
+            {
+            dUsbc->ProcessAlternateSetting(deviceState);
+            }
+        else
+            {
+            dUsbc->ProcessDeviceState(deviceState);
+            // Send Status to EP0 buffer.        
+            // Before the client calls RDevUsbcScClient::FinalizeInterface(),
+            // this function might be called.
+            // So we add a guard for dUsbc->iBuffers
+            if( dUsbc->iBuffers )
+                {
+                dUsbc->iBuffers[dUsbc->iEP0OutBuff].SendEp0StatusPacket(deviceState);
+                }
+            }
+
+        // Only queue if userside is interested
+        if (dUsbc->iDeviceStatusNeeded)
+            {
+            dUsbc->iStatusFifo->AddStatusToQueue(deviceState);
+            const TInt reqNo = (TInt) RDevUsbcScClient::ERequestAlternateDeviceStatusNotify;
+            if (dUsbc->AlternateDeviceStateTestComplete())
+                Kern::RequestComplete(dUsbc->iClient, dUsbc->iRequestStatus[reqNo], KErrNone);
+            }
+        }
+     // We don't want to be interrupted in the middle of this:
+    const TInt irqs = NKern::DisableInterrupts(2);
+     dUsbc->iStatusCallbackInfo.ResetState();
+    NKern::RestoreInterrupts(irqs);
+    }
+
+
+void DLddUsbcScChannel::OtgFeatureChangeCallback(TAny* aDLddUsbcScChannel)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("OtgFeatureChangeCallback"));
+    DLddUsbcScChannel* dUsbc = (DLddUsbcScChannel*) aDLddUsbcScChannel;
+    if (dUsbc->iChannelClosing)
+        return;
+
+    TUint8 features;
+    // No return value check. Assume OTG always supported here
+    dUsbc->iController->GetCurrentOtgFeatures(features);
+
+    const TInt reqNo = (TInt) RDevUsbcScClient::ERequestOtgFeaturesNotify;
+    if (dUsbc->iRequestStatus[reqNo])
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("OtgFeatureChangeCallback Notify status"));
+        TInt r = Kern::ThreadRawWrite(dUsbc->iClient, dUsbc->iOtgFeatureChangePtr,
+                                      &features, sizeof(TUint8), dUsbc->iClient);
+        if (r != KErrNone)
+            dUsbc->PanicClientThread(r);
+        Kern::RequestComplete(dUsbc->iClient, dUsbc->iRequestStatus[reqNo], r);
+        dUsbc->iOtgFeatureChangePtr = NULL;
+        }
+    }
+
+
+//
+// SelectAlternateSetting
+//
+
+TInt DLddUsbcScChannel::SelectAlternateSetting(TUint aAlternateSetting)
+    {
+    TUsbcScEndpoint* ep;
+
+    // First, find the alt setting record, which corresponds to the alt setting number.
+    TUsbcScAlternateSetting* alternateSettingListRec;
+    if(iAlternateSettingList)
+        {
+        for (alternateSettingListRec = iAlternateSettingList->iHead; alternateSettingListRec; alternateSettingListRec = alternateSettingListRec->iNext)
+            if (alternateSettingListRec->iSetting == aAlternateSetting)
+                {
+                // Record has been located.
+
+                // Update current ep setting vars 
+                iEndpoint = alternateSettingListRec->iEndpoint;
+                iNumberOfEndpoints = alternateSettingListRec->iNumberOfEndpoints;
+
+
+
+                // Reset buffers for new ep set
+                for (TInt i = 1; i <= KMaxEndpointsPerClient; i++)
+                    {
+                    ep = alternateSettingListRec->iEndpoint[i];
+                    if (ep!=NULL)
+                        ep->StartBuffer(); // Buffer::StartEndpoint(...)   sets the necessary parameters to the buffer, for use for a perticular endpoint.
+                    }
+
+                return KErrNone;
+                }
+        }
+    return KErrGeneral;
+    }
+
+/* The user calls this to move into the next alternate setting.  After this call, it is assumed the user wants to
+Transmit using endpoints belonging to this alternate Setting.  Writes to the IN endpoints will be allowed until
+the host changed the alternate setting again
+Returns a 32 int with the top 16 bits represents the sequance, and the botten, the alternatre setting no.
+*/
+TInt32 DLddUsbcScChannel::StartNextInAlternateSetting()
+    {
+    iUserKnowsAltSetting = ETrue;
+    return iAsSeq<<16 | iAlternateSetting;
+    } 
+
+
+//
+// EpFromAlternateSetting
+//
+
+TInt DLddUsbcScChannel::EpFromAlternateSetting(TUint aAlternateSetting, TInt aEndpoint)
+    {
+    TUsbcScAlternateSetting* alternateSettingListRec = iAlternateSettingList->iHead;
+    while (alternateSettingListRec)
+        {
+        if (alternateSettingListRec->iSetting == aAlternateSetting)
+            {
+            if ((aEndpoint <= alternateSettingListRec->iNumberOfEndpoints) &&
+                (aEndpoint > 0))
+                {
+                return alternateSettingListRec->iEndpoint[aEndpoint]->RealEpNumber();
+                }
+            else
+                {
+                __KTRACE_OPT(KPANIC, Kern::Printf("  Error: aEndpoint %d wrong for aAlternateSetting %d",
+                                                  aEndpoint, aAlternateSetting));
+                return KErrNotFound;
+                }
+            }
+        alternateSettingListRec = alternateSettingListRec->iNext;
+        }
+    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: no aAlternateSetting %d found", aAlternateSetting));
+    return KErrNotFound;
+    }
+
+//
+// ProcessAlternateSetting
+//
+
+TInt DLddUsbcScChannel::ProcessAlternateSetting(TUint aAlternateSetting)
+    {
+
+    TUint newSetting = aAlternateSetting&(~KUsbAlternateSetting);
+    __KTRACE_OPT(KUSB, Kern::Printf("ProcessAlternateSetting 0x%08x selecting alternate setting 0x%08x", aAlternateSetting, newSetting));
+    iUserKnowsAltSetting=EFalse;
+    iAlternateSetting = newSetting;
+    iAsSeq++; 
+    
+    ResetInterface(KErrUsbInterfaceChange);                    // kill any outstanding IN transfers
+
+    TInt r = SelectAlternateSetting(newSetting);
+    if (r != KErrNone)
+        return r;
+
+
+    StartEpReads();
+    return KErrNone;
+    }
+
+
+//
+//  ProcessDeviceState
+//
+// Called from StatusChangeCallback.
+
+TInt DLddUsbcScChannel::ProcessDeviceState(TUsbcDeviceState aDeviceState)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::ProcessDeviceState(%d -> %d)", iDeviceState, aDeviceState));
+    if (iDeviceState == aDeviceState)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  No state change => nothing to be done."));
+        return KErrNone;
+        }
+    if (iDeviceState == UsbShai::EUsbPeripheralStateSuspended)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Coming out of Suspend: old state = %d", iOldDeviceState));
+        iDeviceState = iOldDeviceState;
+        if (iDeviceState == aDeviceState)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  New state same as before Suspend => nothing to be done."));
+            return KErrNone;
+            }
+        }
+    TBool renumerateState = (aDeviceState == UsbShai::EUsbPeripheralStateConfigured);
+    TBool deconfigured = EFalse;
+    TInt cancellationCode = KErrNone;
+    if (aDeviceState == UsbShai::EUsbPeripheralStateSuspended)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Suspending..."));
+        iOldDeviceState = iDeviceState;
+        // Put PSL into low power mode here
+        }
+    else
+        {
+        deconfigured = (iDeviceState == UsbShai::EUsbPeripheralStateConfigured &&
+                        aDeviceState != UsbShai::EUsbPeripheralStateConfigured);
+        if (iDeviceState == UsbShai::EUsbPeripheralStateConfigured)
+            {
+            if (aDeviceState == UsbShai::EUsbPeripheralStateUndefined)
+                cancellationCode = KErrUsbCableDetached;
+            else if (aDeviceState == UsbShai::EUsbPeripheralStateAddress)
+                cancellationCode = KErrUsbDeviceNotConfigured;
+            else if (aDeviceState == UsbShai::EUsbPeripheralStateDefault)
+                cancellationCode = KErrUsbDeviceBusReset;
+            else
+                cancellationCode = KErrUsbDeviceNotConfigured;
+            }
+        }
+    iDeviceState = aDeviceState;
+    if (iValidInterface || iOwnsDeviceControl)
+        {
+
+        // This LDD may not own an interface. It could be some manager reenumerating
+        // after its subordinate LDDs have setup their interfaces.
+        if (deconfigured)
+            {
+            DeConfigure(cancellationCode);
+            }
+        else if (renumerateState)
+            {
+             __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChannel:: Reumerated!"));
+            // Select main interface & latch in new endpoint set
+            SelectAlternateSetting(0);
+            __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChannel:: StartReads!"));
+            StartEpReads();
+            }
+        }
+
+    const TInt reqNo = (TInt) RDevUsbcScClient::ERequestReEnumerate;
+    if (renumerateState && iRequestStatus[reqNo])
+        {
+        // This lot must be done if we are reenumerated
+        Kern::RequestComplete(iClient, iRequestStatus[reqNo], KErrNone);
+        }
+
+    return KErrNone;
+    }
+
+
+TBool DLddUsbcScChannel::AlternateDeviceStateTestComplete()
+    {
+    TBool completeNow = EFalse;
+    const TInt reqNo = (TInt) RDevUsbcScClient::ERequestAlternateDeviceStatusNotify;
+    if (iRequestStatus[reqNo])
+        {
+        // User req is outstanding
+        TUint32 deviceState;
+        if (iStatusFifo->GetDeviceQueuedStatus(deviceState) == KErrNone)
+            {
+            // Device state waiting to be sent userside
+            completeNow = ETrue;
+            __KTRACE_OPT(KUSB, Kern::Printf("StatusChangeCallback Notify status"));
+            // set client descriptor length to zero
+            TInt r = Kern::ThreadRawWrite(iClient, iStatusChangePtr, &deviceState,
+                                          sizeof(TUint32), iClient);
+            if (r != KErrNone)
+                PanicClientThread(r);
+            iStatusChangePtr = NULL;
+            }
+        }
+    return completeNow;
+    }
+
+
+void DLddUsbcScChannel::DeConfigure(TInt aErrorCode)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DeConfigure()"));
+    // Called after deconfiguration. Cancels transfers on all endpoints.
+    ResetInterface(aErrorCode);
+    // Cancel the endpoint status notify request if it is outstanding.
+    const TInt KEpNotReq = RDevUsbcScClient::ERequestEndpointStatusNotify;
+    if (iRequestStatus[KEpNotReq])
+        {
+        CancelNotifyEndpointStatus();
+        Kern::RequestComplete(iClient, iRequestStatus[KEpNotReq], aErrorCode);
+        }
+    // We have to reset the alternate setting number when the config goes away.
+     SelectAlternateSetting(0);
+    iAlternateSetting = 0;
+    }
+
+
+void DLddUsbcScChannel::StartEpReads()
+    {
+    // Queued after enumeration. Starts reads on all endpoints.
+    // The endpoint itself decides if it can do a read
+    __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 1"));
+    
+    TInt i;
+    TInt8 needsPacket;
+
+    for (i=0; i<iNumBuffers; i++)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 2 %d",i));
+
+        needsPacket = iBuffers[i].iNeedsPacket;
+        if (needsPacket)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 3"));
+            iBuffers[i].UpdateBufferList(0,0,(needsPacket==TUsbcScBuffer::KEpIsStarting));
+            }
+        }
+
+    __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 4"));
+
+        // now update ep0
+        iBuffers[iEP0OutBuff].Ep0CancelLddRead();
+        iBuffers[iEP0OutBuff].UpdateBufferList(0,0);
+    __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 5"));
+
+    }
+
+
+void DLddUsbcScChannel::ResetInterface(TInt aErrorCode)
+    {
+    if (!iValidInterface && !iOwnsDeviceControl)
+            return;
+        
+    TInt i;
+    for (i=0; i<iNumBuffers; i++)
+        {
+        iBuffers[i].iNeedsPacket=TUsbcScBuffer::KNoEpAssigned;
+        }
+
+    TUsbcScBuffer* buffer;
+
+    for (i = 1; i <= iNumberOfEndpoints; i++)
+        {
+        // Firstly, cancel ('garbge collect') any stale reads/writes into PIL.
+
+        __KTRACE_OPT(KUSB, Kern::Printf("Cancelling transfer ep=%d", i));
+        iEndpoint[i]->AbortTransfer();
+
+        // All OUT endpoints need a packet sent, to indicate the termination of the current ep 'pipe'.
+        // This will complete any current read, or will be read later.
+        // All IN endpoints must be simply cancelled, including anything queued.
+        // Ep0 operates outside alt settings, and so we don't cancel anything.
+
+        buffer=iEndpoint[i]->GetBuffer();
+        if (buffer->iDirection==KUsbcScIn)
+            {
+            buffer->iStatusList.Complete(KErrCancel);    //aErrorCode 
+            buffer->iStatusList.CancelQueued();            //aErrorCode
+            }
+        else
+            buffer->iNeedsPacket=TUsbcScBuffer::KEpIsEnding;    // We will send a packet on re-start, which doubles as a 'cancel'
+                                                                 // for the old alt setting.
+        }
+    }
+
+
+
+void DLddUsbcScChannel::EmergencyCompleteDfc(TAny* aDLddUsbcScChannel)
+    {
+    ((DLddUsbcScChannel*) aDLddUsbcScChannel)->DoEmergencyComplete();
+    }
+
+TInt DLddUsbcScChannel::DoEmergencyComplete()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DoEmergencyComplete"));
+    // cancel any pending DFCs
+    // complete all client requests
+
+    TUsbcScBuffer* buffer;
+    TInt i;    
+    // Complete EP0 request
+
+    TInt direction=iEp0Endpoint->iRequestCallbackInfo->iTransferDir;
+    if (direction==UsbShai::EControllerWrite)
+        {
+        iBuffers[iEP0InBuff].iStatusList.CancelQueued();
+        iBuffers[iEP0InBuff].iStatusList.Complete(KErrDisconnected);
+        }
+    else if (direction==UsbShai::EControllerRead)
+        {
+        iBuffers[iEP0OutBuff].iStatusList.CancelQueued();
+        iBuffers[iEP0OutBuff].iStatusList.Complete(KErrDisconnected);
+        }
+        
+    // Complete other Eps request
+    for (i = 1; i <= iNumberOfEndpoints; i++)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("Cancelling transfer ep=%d", i));
+        buffer=iEndpoint[i]->GetBuffer();
+        buffer->iStatusList.CancelQueued();
+        buffer->iStatusList.Complete(KErrDisconnected);
+        }
+
+    // Complete remaining requests
+
+    for (TInt i = 0; i < KUsbcMaxRequests; i++)
+        {
+        if (iRequestStatus[i])
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("Complete request 0x%x", iRequestStatus[i]));
+            Kern::RequestComplete(iClient, iRequestStatus[i], KErrDisconnected);
+            }
+        }
+    iStatusCallbackInfo.Cancel();
+    iEndpointStatusCallbackInfo.Cancel();
+    iOtgFeatureCallbackInfo.Cancel();
+
+    return KErrNone;
+    }
+
+
+void DLddUsbcScChannel::PanicClientThread(TInt aReason)
+    {
+    Kern::ThreadKill(iClient, EExitPanic, aReason, KUsbLDDKillCat);
+    }
+
+// End DLddUsbcScChannel
+
+/*****************************************************************************\
+*    TUsbcScEndpoint                                                          *
+*                                                                             *
+*                                                                             *
+*                                                                             *
+\*****************************************************************************/
+
+
+// Constructor
+TUsbcScEndpoint::TUsbcScEndpoint(DLddUsbcScChannel* aLDD, DUsbClientController* aController,
+                             const TUsbcScEndpointInfo* aEndpointInfo, TInt aEndpointNum
+                             )
+    : iRequestCallbackInfo(NULL),
+      iController(aController),
+      iEndpointInfo(*aEndpointInfo),
+      iClientReadPending(EFalse),
+      iClientWritePending(EFalse),
+      iEndpointNumber(aEndpointNum),
+      iRealEpNumber(-1),
+      iLdd(aLDD),
+      iError(KErrNone),
+      iBytesTransferred(0),
+      iBuffer(NULL)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::TUsbcScEndpoint"));
+    }
+
+
+TInt TUsbcScEndpoint::Construct()
+    {
+    __KTRACE_OPT(KUSB,Kern::Printf("TUsbcScEndpoint::TUsbcScEndpoint iEndpointNumber %d\n",iEndpointNumber));
+
+    iRequestCallbackInfo = new TUsbcRequestCallback(iLdd,
+                                                    iEndpointNumber,
+                                                    (iEndpointNumber==0)?DLddUsbcScChannel::RequestCallbackEp0:TUsbcScEndpoint::RequestCallback,
+                                                    (iEndpointNumber==0)?  (TAny*) iLdd:  (TAny*) this,
+                                                    iLdd->iDfcQ,
+                                                    KUsbRequestCallbackPriority);
+
+    return (iRequestCallbackInfo == NULL)?KErrNoMemory:KErrNone;
+    }
+
+
+TUsbcScEndpoint::~TUsbcScEndpoint()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::~TUsbcScEndpoint(%d)", iEndpointNumber));
+    AbortTransfer();
+    delete iRequestCallbackInfo;
+    }
+
+// This is called by the PIL, on return from a read or write.
+// Inturn it calls either the read or write function for that buffer.
+
+void TUsbcScEndpoint::RequestCallback(TAny* aTUsbcScEndpoint)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::RequestCallback"));
+
+    if (((TUsbcScEndpoint*)aTUsbcScEndpoint)->iLdd->ChannelClosing())
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("Channel Closing: Completion not accepted!"));
+        return;
+        }
+
+    switch (((TUsbcScEndpoint*) aTUsbcScEndpoint)->iRequestCallbackInfo->iTransferDir)
+    {
+    case UsbShai::EControllerWrite:
+        ((TUsbcScEndpoint*) aTUsbcScEndpoint)->iBuffer->CompleteWrite();
+        return;
+    case UsbShai::EControllerRead:
+        ((TUsbcScEndpoint*) aTUsbcScEndpoint)->iBuffer->CompleteRead();
+        return;
+    default:
+        Kern::Printf("TUsbcScEndpoint::RequestCallback - Unexpected compleation direction %d",((TUsbcScEndpoint*) aTUsbcScEndpoint)->iRequestCallbackInfo->iTransferDir);
+        Kern::Fault("TUsbcScEndpoint::RequestCallback", __LINE__);
+    } 
+    }
+
+
+/*
+
+This is used to tidy up cancel calls into the PIL, regardless of them being reads or writes
+
+*/
+
+void TUsbcScEndpoint::AbortTransfer()
+    {
+    if (!iLdd->iRealizeCalled)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::AbortTransfer Ep# %d Real Ep # %d - N.R.",iEndpointNumber, iRealEpNumber));
+        return;
+        } 
+    else
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::AbortTransfer Ep# %d Real Ep # %d",iEndpointNumber, iRealEpNumber));
+        }
+
+    
+    if (iBuffer && (iBuffer->iStatusList.iState) || (!iRealEpNumber))
+        {
+        if (iRequestCallbackInfo->iTransferDir==UsbShai::EControllerWrite)
+            iController->CancelWriteBuffer(iLdd, iRealEpNumber);
+        else if (iRequestCallbackInfo->iTransferDir==UsbShai::EControllerRead)
+            iController->CancelReadBuffer(iLdd, iRealEpNumber);
+        else
+            {
+            if (iEndpointNumber!=0) // endpoint zero starts off not sent in any direction, then keeps changing.
+                {
+                __KTRACE_OPT(KUSB,Kern::Printf("\nTUsbcScEndpoint::AbortTransfer WARNING: Invalid Direction %d on (%d,%d)!\n",iRequestCallbackInfo->iTransferDir,iEndpointNumber, iRealEpNumber));
+                }
+            else
+                {
+                __KTRACE_OPT(KUSB, Kern::Printf("\nTUsbcScEndpoint::AbortTransfer Can't stop direction %d on (%d,%d)!\n",iRequestCallbackInfo->iTransferDir,iEndpointNumber, iRealEpNumber));
+                }
+            }
+        }
+    else if (!iBuffer)
+        {
+        __KTRACE_OPT(KUSB,Kern::Printf("\nTUsbcScEndpoint::AbortTransfer WARNING: iBuffer is NULL on (%d,%d)\n",iEndpointNumber, iRealEpNumber));
+        return;
+        }
+    
+    if (iRequestCallbackInfo)
+        iRequestCallbackInfo->iDfc.Cancel();
+    else
+        {
+        __KTRACE_OPT(KUSB,Kern::Printf("\nTUsbcScEndpoint::AbortTransfer WARNING: iRequestCallbackInfo is NULL\n"));
+        }
+        
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint Done."));
+    }
+
+// End TUsbcScEndpoint
+
+
+/*****************************************************************************\
+*    TUsbcScAlternateSettingList                                              *
+*                                                                             *
+*                                                                             *
+*                                                                             *
+\*****************************************************************************/
+
+
+TUsbcScAlternateSetting::TUsbcScAlternateSetting()
+    : iNext(NULL),
+      iPrevious(NULL),
+      iNumberOfEndpoints(0),
+      iSetting(0)
+    {
+    for (TInt i = 0; i <= KMaxEndpointsPerClient; i++)
+        {
+        iEndpoint[i] = NULL;
+        }
+    }
+
+
+TUsbcScAlternateSetting::~TUsbcScAlternateSetting()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScAlternateSetting::~TUsbcScAlternateSetting()"));
+    for (TInt i = 0; i <= KMaxEndpointsPerClient; i++)
+        {
+        delete iEndpoint[i];
+        }
+    }
+
+// End TUsbcScAlternateSettingList
+
+
+
+TUsbcScAlternateSettingList::TUsbcScAlternateSettingList()
+    : iHead(NULL),
+      iTail(NULL)
+    {
+    }
+
+TUsbcScAlternateSettingList::~TUsbcScAlternateSettingList()
+    {
+    }
+
+
+
+/*****************************************************************************\
+*   TUsbcDeviceStatusQueue                                                    *
+*                                                                             *
+*                                                                             *
+*                                                                             *
+\*****************************************************************************/
+
+
+TUsbcDeviceStatusQueue::TUsbcDeviceStatusQueue()
+    {
+    FlushQueue();
+    }
+
+
+void TUsbcDeviceStatusQueue::FlushQueue()
+    {
+    for (TInt i = 0; i < KUsbDeviceStatusQueueDepth; i++)
+        {
+        iDeviceStatusQueue[i] = KUsbDeviceStatusNull;
+        }
+    iStatusQueueHead = 0;
+    }
+
+
+void TUsbcDeviceStatusQueue::AddStatusToQueue(TUint32 aDeviceStatus)
+    {
+    // Only add a new status if it is not a duplicate of the one at the head of the queue
+    if (!(iStatusQueueHead != 0 &&
+          iDeviceStatusQueue[iStatusQueueHead - 1] == aDeviceStatus))
+        {
+        if (iStatusQueueHead == KUsbDeviceStatusQueueDepth)
+            {
+            // Discard item at tail of queue
+            TUint32 status;
+            GetDeviceQueuedStatus(status);
+            }
+        iDeviceStatusQueue[iStatusQueueHead] = aDeviceStatus;
+        iStatusQueueHead++;
+        }
+    }
+
+
+TInt TUsbcDeviceStatusQueue::GetDeviceQueuedStatus(TUint32& aDeviceStatus)
+    {
+    TInt r = KErrNone;
+    if (iStatusQueueHead <= 0)
+        {
+        r = KErrGeneral;
+        aDeviceStatus = KUsbDeviceStatusNull;
+        }
+    else
+        {
+        aDeviceStatus = iDeviceStatusQueue[0];
+        for(TInt i = 1; i < KUsbDeviceStatusQueueDepth; i++)
+            {
+            TUint32 s = iDeviceStatusQueue[i];
+            iDeviceStatusQueue[i - 1] = s;
+            }
+        iStatusQueueHead--;
+        iDeviceStatusQueue[KUsbDeviceStatusQueueDepth - 1] = KUsbDeviceStatusNull;
+        }
+    return r;
+    }
+
+// End TUsbcDeviceStatusQueue
+
+//---
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/pdd/pil/eabi/usbperipheralpilu.def	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,95 @@
+EXPORTS
+	_ZN20DUsbClientController10PowerUpUdcEv @ 1 NONAME
+	_ZN20DUsbClientController10UsbConnectEv @ 2 NONAME
+	_ZN20DUsbClientController11ReEnumerateEv @ 3 NONAME
+	_ZN20DUsbClientController12HaltEndpointEPK5DBasei @ 4 NONAME
+	_ZN20DUsbClientController12SetInterfaceEPK5DBaseP7DThreadiR14TUsbcClassInfoP6TDesC8i22TUsbcEndpointInfoArrayPim @ 5 NONAME
+	_ZN20DUsbClientController12SetInterfaceEPK5DBaseP7DThreadiR14TUsbcClassInfoP6TDesC8iPK17TUsbcEndpointInfoPA6_im @ 6 NONAME
+	_ZN20DUsbClientController13DumpRegistersEv @ 7 NONAME
+	_ZN20DUsbClientController13UsbDisconnectEv @ 8 NONAME
+	_ZN20DUsbClientController15SetupReadBufferER20TUsbcRequestCallback @ 9 NONAME
+	_ZN20DUsbClientController16CancelReadBufferEPK5DBasei @ 10 NONAME
+	_ZN20DUsbClientController16DeRegisterClientEPK5DBase @ 11 NONAME
+	_ZN20DUsbClientController16ReleaseInterfaceEPK5DBasei @ 12 NONAME
+	_ZN20DUsbClientController16SetDeviceControlEPK5DBase @ 13 NONAME
+	_ZN20DUsbClientController16SetOtgDescriptorEP7DThreadRK6TDesC8 @ 14 NONAME
+	_ZN20DUsbClientController16SetupWriteBufferER20TUsbcRequestCallback @ 15 NONAME
+	_ZN20DUsbClientController17CancelWriteBufferEPK5DBasei @ 16 NONAME
+	_ZN20DUsbClientController17ClearHaltEndpointEPK5DBasei @ 17 NONAME
+	_ZN20DUsbClientController17EnableClientStackEv @ 18 NONAME
+	_ZN20DUsbClientController18DisableClientStackEv @ 19 NONAME
+	_ZN20DUsbClientController18EndpointPacketSizeEPK5DBasei @ 20 NONAME
+	_ZN20DUsbClientController18SignalRemoteWakeupEv @ 21 NONAME
+	_ZN20DUsbClientController19GetDeviceDescriptorEP7DThreadR5TDes8 @ 22 NONAME
+	_ZN20DUsbClientController19GetStringDescriptorEP7DThreadhR5TDes8 @ 23 NONAME
+	_ZN20DUsbClientController19SendEp0StatusPacketEPK5DBase @ 24 NONAME
+	_ZN20DUsbClientController19SetDeviceDescriptorEP7DThreadRK5TDes8 @ 25 NONAME
+	_ZN20DUsbClientController19SetStringDescriptorEP7DThreadhRK5TDes8 @ 26 NONAME
+	_ZN20DUsbClientController20ReleaseDeviceControlEPK5DBase @ 27 NONAME
+	_ZN20DUsbClientController21GetEndpointDescriptorEP7DThreadPK5DBaseiiR5TDes8 @ 28 NONAME
+	_ZN20DUsbClientController21QueryEndpointResourceEPK5DBasei21TUsbcEndpointResource @ 29 NONAME
+	_ZN20DUsbClientController21SetEndpointDescriptorEP7DThreadPK5DBaseiiRK5TDes8 @ 30 NONAME
+	_ZN20DUsbClientController21UsbcControllerPointerEi @ 31 NONAME
+	_ZN20DUsbClientController22GetInterfaceDescriptorEP7DThreadPK5DBaseiR5TDes8 @ 32 NONAME
+	_ZN20DUsbClientController22RegisterClientCallbackER19TUsbcClientCallback @ 33 NONAME
+	_ZN20DUsbClientController22RemoveStringDescriptorEh @ 34 NONAME
+	_ZN20DUsbClientController22SetInterfaceDescriptorEP7DThreadPK5DBaseiRK5TDes8 @ 35 NONAME
+	_ZN20DUsbClientController23CurrentlyUsingHighSpeedEv @ 36 NONAME
+	_ZN20DUsbClientController23GetDeviceDescriptorSizeEP7DThreadR5TDes8 @ 37 NONAME
+	_ZN20DUsbClientController23RegisterForStatusChangeER19TUsbcStatusCallback @ 38 NONAME
+	_ZN20DUsbClientController25DeRegisterForStatusChangeEPK5DBase @ 39 NONAME
+	_ZN20DUsbClientController25GetEndpointDescriptorSizeEP7DThreadPK5DBaseiiR5TDes8 @ 40 NONAME
+	_ZN20DUsbClientController25GetStringDescriptorLangIdEP7DThreadR5TDes8 @ 41 NONAME
+	_ZN20DUsbClientController25SetStringDescriptorLangIdEt @ 42 NONAME
+	_ZN20DUsbClientController26GetConfigurationDescriptorEP7DThreadR5TDes8 @ 43 NONAME
+	_ZN20DUsbClientController26GetInterfaceDescriptorSizeEP7DThreadPK5DBaseiR5TDes8 @ 44 NONAME
+	_ZN20DUsbClientController26GetProductStringDescriptorEP7DThreadR5TDes8 @ 45 NONAME
+	_ZN20DUsbClientController26SetConfigurationDescriptorEP7DThreadRK5TDes8 @ 46 NONAME
+	_ZN20DUsbClientController26SetProductStringDescriptorEP7DThreadRK5TDes8 @ 47 NONAME
+	_ZN20DUsbClientController27RegisterForOtgFeatureChangeER23TUsbcOtgFeatureCallback @ 48 NONAME
+	_ZN20DUsbClientController28GetCSEndpointDescriptorBlockEP7DThreadPK5DBaseiiR5TDes8 @ 49 NONAME
+	_ZN20DUsbClientController28GetDeviceQualifierDescriptorEP7DThreadR5TDes8 @ 50 NONAME
+	_ZN20DUsbClientController28SetCSEndpointDescriptorBlockEP7DThreadPK5DBaseiiRK5TDes8i @ 51 NONAME
+	_ZN20DUsbClientController28SetDeviceQualifierDescriptorEP7DThreadRK5TDes8 @ 52 NONAME
+	_ZN20DUsbClientController28SetEndpointZeroMaxPacketSizeEi @ 53 NONAME
+	_ZN20DUsbClientController29DeRegisterForOtgFeatureChangeEPK5DBase @ 54 NONAME
+	_ZN20DUsbClientController29GetCSInterfaceDescriptorBlockEP7DThreadPK5DBaseiR5TDes8 @ 55 NONAME
+	_ZN20DUsbClientController29RemoveProductStringDescriptorEv @ 56 NONAME
+	_ZN20DUsbClientController29SetCSInterfaceDescriptorBlockEP7DThreadPK5DBaseiRK5TDes8i @ 57 NONAME
+	_ZN20DUsbClientController30GetConfigurationDescriptorSizeEP7DThreadR5TDes8 @ 58 NONAME
+	_ZN20DUsbClientController31GetManufacturerStringDescriptorEP7DThreadR5TDes8 @ 59 NONAME
+	_ZN20DUsbClientController31GetSerialNumberStringDescriptorEP7DThreadR5TDes8 @ 60 NONAME
+	_ZN20DUsbClientController31RegisterForEndpointStatusChangeER27TUsbcEndpointStatusCallback @ 61 NONAME
+	_ZN20DUsbClientController31SetManufacturerStringDescriptorEP7DThreadRK5TDes8 @ 62 NONAME
+	_ZN20DUsbClientController31SetSerialNumberStringDescriptorEP7DThreadRK5TDes8 @ 63 NONAME
+	_ZN20DUsbClientController32GetCSEndpointDescriptorBlockSizeEP7DThreadPK5DBaseiiR5TDes8 @ 64 NONAME
+	_ZN20DUsbClientController32GetConfigurationStringDescriptorEP7DThreadR5TDes8 @ 65 NONAME
+	_ZN20DUsbClientController32SetConfigurationStringDescriptorEP7DThreadRK5TDes8 @ 66 NONAME
+	_ZN20DUsbClientController33DeRegisterForEndpointStatusChangeEPK5DBase @ 67 NONAME
+	_ZN20DUsbClientController33GetCSInterfaceDescriptorBlockSizeEP7DThreadPK5DBaseiR5TDes8 @ 68 NONAME
+	_ZN20DUsbClientController34RemoveManufacturerStringDescriptorEv @ 69 NONAME
+	_ZN20DUsbClientController34RemoveSerialNumberStringDescriptorEv @ 70 NONAME
+	_ZN20DUsbClientController35RemoveConfigurationStringDescriptorEv @ 71 NONAME
+	_ZN20DUsbClientController36GetOtherSpeedConfigurationDescriptorEP7DThreadR5TDes8 @ 72 NONAME
+	_ZN20DUsbClientController36SetOtherSpeedConfigurationDescriptorEP7DThreadRK5TDes8 @ 73 NONAME
+	_ZN20DUsbClientController4DfcQEi @ 74 NONAME
+	_ZN20DUsbClientController6CreateERN7UsbShai23MPeripheralControllerIfERKNS0_31TPeripheralControllerPropertiesEi @ 75 NONAME
+	_ZN20DUsbClientController8Ep0StallEPK5DBase @ 76 NONAME
+	_ZN20DUsbClientController8IsActiveEv @ 77 NONAME
+	_ZN20TUsbcRequestCallback15SetRxBufferInfoEPhmPmS1_i @ 78 NONAME
+	_ZN20TUsbcRequestCallback15SetTxBufferInfoEPhmi @ 79 NONAME
+	_ZN7UsbShai16UsbPeripheralPil28RegisterPeripheralControllerERNS_23MPeripheralControllerIfERKNS_31TPeripheralControllerPropertiesE @ 80 NONAME
+	_ZN7UsbShai21TUsbPeripheralRequestC1Ei @ 81 NONAME
+	_ZN7UsbShai21TUsbPeripheralRequestC2Ei @ 82 NONAME
+	_ZN7UsbShai22UsbChargerDetectionPil23RegisterChargerDetectorERNS_18MChargerDetectorIfERNS_26TChargerDetectorPropertiesE @ 83 NONAME
+	_ZNK20DUsbClientController10DeviceCapsEPK5DBaseR5TDes8 @ 84 NONAME
+	_ZNK20DUsbClientController12EndpointCapsEPK5DBaseR5TDes8 @ 85 NONAME
+	_ZNK20DUsbClientController13Ep0PacketSizeEv @ 86 NONAME
+	_ZNK20DUsbClientController14GetOtgFeaturesEP7DThreadR5TDes8 @ 87 NONAME
+	_ZNK20DUsbClientController15GetDeviceStatusEv @ 88 NONAME
+	_ZNK20DUsbClientController16GetOtgDescriptorEP7DThreadR5TDes8 @ 89 NONAME
+	_ZNK20DUsbClientController17GetEndpointStatusEPK5DBasei @ 90 NONAME
+	_ZNK20DUsbClientController18GetInterfaceNumberEPK5DBaseRi @ 91 NONAME
+	_ZNK20DUsbClientController21GetCurrentOtgFeaturesERh @ 92 NONAME
+	_ZNK20DUsbClientController26EndpointZeroMaxPacketSizesEv @ 93 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/pdd/pil/group/bld.inf	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). 
+  All rights reserved.
+
+  This program and the accompanying materials are made available 
+  under the terms of the Eclipse Public License v1.0 which accompanies 
+  this distribution, and is available at 
+  http://www.eclipse.org/legal/epl-v10.html
+
+  Initial Contributors:
+  Nokia Corporation - initial contribution.
+
+  Contributors:
+*/
+#include <platform_paths.hrh>
+
+PRJ_PLATFORMS
+ARMV5
+
+PRJ_MMPFILES
+usbperipheralpil
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/pdd/pil/group/usbperipheralpil.mmp	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,45 @@
+/*
+  Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). 
+  All rights reserved.
+
+  This program and the accompanying materials are made available 
+  under the terms of the Eclipse Public License v1.0 which accompanies 
+  this distribution, and is available at 
+  http://www.eclipse.org/legal/epl-v10.html
+
+  Initial Contributors:
+  Nokia Corporation - initial contribution.
+
+  Contributors:
+*/
+
+#include <platform_paths.hrh>
+
+#include        "kernel/kern_ext.mmh"
+
+target          usbperipheralpil.dll
+targettype      kext
+linkas          usbperipheralpil.dll
+deffile         ../~/usbperipheralpil.def
+VENDORID        0x70000001
+uid             0x00000000  0x2002E6DB
+capability      all
+epocallowdlldata
+
+// The sytem include paths are declared by using the following macros
+
+OS_LAYER_SYSTEMINCLUDE
+
+
+
+// Include dirs of the HS-USB component
+userinclude     ../inc
+
+// PIL layer source files
+sourcepath   ../src
+source       chapter9.cpp
+source       descriptors.cpp
+source       misc.cpp
+source       ps_usbc.cpp
+source       queue.cpp
+source       controltransfersm.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/pdd/pil/src/chapter9.cpp	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,1599 @@
+// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32/drivers/usbcc/chapter9.cpp
+// Platform independent layer (PIL) of the USB Device controller driver:
+// Processing of USB spec chapter 9 standard requests.
+// 
+//
+
+/**
+ @file chapter9.cpp
+ @internalTechnology
+*/
+
+#include <usb/usbc.h>
+
+#include "controltransfersm.h"
+
+//#define ENABLE_EXCESSIVE_DEBUG_OUTPUT
+//
+// === USB Controller member function implementation - PSL API (protected) ========================
+//
+
+/** Used to synchronize the Ep0 state machine between the PSL and PIL.
+    Accepts a SETUP packet and returns the next Ep0 state.
+
+    @param aSetupBuf The SETUP packet just received by the PSL.
+    @return The next Ep0 state.
+
+    @publishedPartner @released
+*/
+UsbShai::TControlStage DUsbClientController::EnquireEp0NextStage(const TUint8* aSetupBuf) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EnquireEp0NextState()"));
+
+    // This function may be called by the PSL from within an ISR -- so we have
+    // to take care what we do here (and also in all functions that get called
+    // from here).
+
+    if (SWAP_BYTES_16((reinterpret_cast<const TUint16*>(aSetupBuf)[3])) == 0) // iLength
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  --> EControlTransferStageStatusIn"));
+        return UsbShai::EControlTransferStageStatusIn;                            // No-data Control => Status_IN
+        }
+    else if ((aSetupBuf[0] & KUsbRequestType_DirMask) == KUsbRequestType_DirToDev)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  --> EControlTransferStageDataOut"));
+        return UsbShai::EControlTransferStageDataOut;                            // Control Write => Data_OUT
+        }
+    else
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  --> EControlTransferStageDataIn"));
+        return UsbShai::EControlTransferStageDataIn;                                // Control Read => Data_IN
+        }
+    }
+
+//
+// About iLastError.
+// This member is used to remember the last error happend during a
+// processXXX likewise function.
+//
+// Before entry of each ProcessXXX, iLastError will be cleared to KErrNone.
+//
+
+// --- The USB Spec Chapter 9 Standard Endpoint Zero Device Requests ---
+// Record error happend with iLastError, the value already been set to zero
+// before entering ProcessSetupPacket call.
+void DUsbClientController::ProcessGetDeviceStatus(const TUsbcSetup& aPacket)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetDeviceStatus()"));
+    if ( iDeviceState < UsbShai::EUsbPeripheralStateAddress)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
+        iLastError = KErrGeneral;
+        }
+    else
+        {
+        // We always assume Device is bus-powered, even though mobile phone almost always
+        // has a battry there, because self-powered device can not required more then 100ma current
+        // which is not acceptable for Usb charging.
+        TBool selfPowered = EFalse;         
+        
+        /*  FIXME: modify selfPowered to make it compilance with following rule.
+           
+             1. If current draw exceeds 100mA, the device must report itself 
+                as bus-powered during enumeration.
+             
+             2. In all cases, the GetStatus(DEVICE) call must accurately report 
+                whether the device is currently operating on self- or bus-power.
+                
+             3. A device that is actively drawing more than 100mA from USB must 
+                report itself as bus-powered in the GetStatus(DEVICE) call.
+             
+             4. Peripherals that return "Self-powered" in the GetStatus(DEVICE) 
+                call are prohibited from drawing more than 100mA at any time.
+        */
+        /*   
+        TBuf8<KUsbDescSize_Config> config;
+        
+        if(iDescriptors.GetConfigurationDescriptorTC(&Kern::CurrentThread(),config) == KErrNone)
+            {
+            TUint8 maxPower = config[8];
+            if(maxPower <= 50)
+                {
+                selfPowered = EFalse;
+                }
+            }
+        */
+        
+        const TUint16 status = ((selfPowered ? KUsbDevStat_SelfPowered : 0) |
+                        (iRmWakeupStatus_Enabled ? KUsbDevStat_RemoteWakeup : 0));
+        __KTRACE_OPT(KUSB, Kern::Printf("  Reporting device status: 0x%02x", status));
+        *reinterpret_cast<TUint16*>(iEp0_TxBuf) = SWAP_BYTES_16(status);
+        if (iConTransferMgr->SetupEndpointZeroWrite(iEp0_TxBuf, sizeof(status)) == KErrNone)
+            {
+            iEp0WritePending = ETrue;
+            }
+        else
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  Wrong: Write to Ep0 Failed"));
+            }
+        }
+    }
+
+void DUsbClientController::ProcessGetInterfaceStatus(const TUsbcSetup& aPacket)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetInterfaceStatus()"));
+    if ( iDeviceState < UsbShai::EUsbPeripheralStateConfigured)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
+        iLastError = KErrGeneral;
+        }
+    else
+        {
+        if (InterfaceExists(aPacket.iIndex) == EFalse)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface does not exist"));
+            iLastError = KErrGeneral;
+            }
+        else
+            {        
+            const TUint16 status = 0x0000;                            // as of USB Spec 2.0
+            __KTRACE_OPT(KUSB, Kern::Printf("  Reporting interface status: 0x%02x", status));
+            *reinterpret_cast<TUint16*>(iEp0_TxBuf) = SWAP_BYTES_16(status);
+            if (iConTransferMgr->SetupEndpointZeroWrite(iEp0_TxBuf, sizeof(status)) == KErrNone)
+                {
+                iEp0WritePending = ETrue;
+                }
+            else
+                {
+                __KTRACE_OPT(KUSB, Kern::Printf("  Wrong: Write to Ep0 Failed"));
+                }
+            }
+        }
+    }
+
+
+void DUsbClientController::ProcessGetEndpointStatus(const TUsbcSetup& aPacket)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetEndpointStatus()"));
+    if (
+        ((iDeviceState < UsbShai::EUsbPeripheralStateAddress) ||
+         (iDeviceState == UsbShai::EUsbPeripheralStateAddress && (aPacket.iIndex & KUsbEpAddress_Portmask) != 0)))
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
+        iLastError = KErrGeneral;
+        }
+    else
+        {
+        if (EndpointExists(aPacket.iIndex) == EFalse)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Endpoint does not exist"));
+            iLastError = KErrGeneral;
+            }
+        else
+            {
+            const TInt ep = EpAddr2Idx(aPacket.iIndex);
+            const TUint16 status = (iRealEndpoints[ep].iHalt) ?     KUsbEpStat_Halt : 0;
+            __KTRACE_OPT(KUSB, Kern::Printf("  Reporting endpoint status 0x%02x for real endpoint %d",
+                                            status, ep));
+            *reinterpret_cast<TUint16*>(iEp0_TxBuf) = SWAP_BYTES_16(status);
+            if (iConTransferMgr->SetupEndpointZeroWrite(iEp0_TxBuf, 2) == KErrNone)
+                {
+                iEp0WritePending = ETrue;
+                }
+            else
+                {
+                __KTRACE_OPT(KUSB, Kern::Printf("  Wrong: Write to Ep0 Failed"));
+                }
+            }
+        }
+    }
+
+
+void DUsbClientController::ProcessSetClearDevFeature(const TUsbcSetup& aPacket)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetClearDevFeature()"));
+    if ( iDeviceState < UsbShai::EUsbPeripheralStateDefault)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
+        iLastError = KErrGeneral;
+        return;
+        }
+
+    TInt test_sel = 0;
+
+    if (aPacket.iRequest == KUsbRequest_SetFeature)
+        {
+        switch (aPacket.iValue)
+            {
+            case KUsbFeature_RemoteWakeup:
+                if ( iDeviceState < UsbShai::EUsbPeripheralStateAddress)
+                    {
+                    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
+                    iLastError = KErrGeneral;                
+                    }
+                else
+                    {
+                    iRmWakeupStatus_Enabled = ETrue;
+                    }
+                break;
+                
+            case KUsbFeature_TestMode:
+                if (!iHighSpeed)
+                    {
+                    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Request only supported in High-Speed mode"));
+                    iLastError = KErrGeneral;
+                    }
+                else if (LowByte(aPacket.iIndex) != 0)
+                    {
+                    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Lower byte of wIndex must be zero"));
+                    iLastError = KErrGeneral;
+                    }
+                else
+                    {
+                    test_sel = HighByte(aPacket.iIndex);
+                    if ((test_sel < UsbShai::EUsbTestSelector_Test_J) || (test_sel > UsbShai::EUsbTestSelector_Test_Force_Enable))
+                        {
+                        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid test selector: %d", test_sel));
+                        iLastError = KErrGeneral;
+                        }
+                    }
+                break;
+                
+            case KUsbFeature_B_HnpEnable:
+                if (!iOtgSupport)
+                    {
+                    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Request only supported on a OTG device"));
+                    iLastError = KErrGeneral;
+                    }            
+                else if (!(iOtgFuncMap & KUsbOtgAttr_HnpSupp))
+                    {
+                    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Request only valid if OTG device supports HNP"));
+                    iLastError = KErrGeneral;
+                    }
+                else
+                    {
+                    iOtgFuncMap |= KUsbOtgAttr_B_HnpEnable;
+                    OtgFeaturesNotify();
+                    }
+                break;
+                
+            case KUsbFeature_A_HnpSupport:
+                if (!iOtgSupport)
+                    {
+                    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Request only supported on a OTG device"));
+                    iLastError = KErrGeneral;
+                    }
+                else if (!(iOtgFuncMap & KUsbOtgAttr_HnpSupp))
+                    {
+                    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Request only valid if OTG device supports HNP"));
+                    iLastError = KErrGeneral;
+                    }
+                else
+                    {
+                    iOtgFuncMap |= KUsbOtgAttr_A_HnpSupport;
+                    OtgFeaturesNotify();
+                    }
+                break;
+                
+            case KUsbFeature_A_AltHnpSupport:
+                if (!iOtgSupport)
+                    {
+                    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Request only supported on a OTG device"));
+                    iLastError = KErrGeneral;
+                    }
+                else if (!(iOtgFuncMap & KUsbOtgAttr_HnpSupp))
+                    {
+                    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Request only valid if OTG device supports HNP"));
+                    iLastError = KErrGeneral;
+                    }
+                else
+                    {
+                    iOtgFuncMap |= KUsbOtgAttr_A_AltHnpSupport;
+                    OtgFeaturesNotify();
+                    }
+                break;
+                
+            default:
+                __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Unknown feature requested"));
+                iLastError = KErrGeneral;                
+            }
+        }
+    else // KUsbRequest_ClearFeature
+        {
+        switch (aPacket.iValue)
+            {
+            case KUsbFeature_RemoteWakeup:
+                if ( iDeviceState < UsbShai::EUsbPeripheralStateAddress)
+                    {
+                    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
+                    iLastError = KErrGeneral;
+                    }
+                else
+                    {
+                    iRmWakeupStatus_Enabled = EFalse;
+                    }
+                break;
+                
+            default:
+                __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Unknown feature requested"));
+                iLastError = KErrGeneral;
+            }
+        }
+    
+    if(iLastError == KErrNone)
+        {
+        // Sent out status packet if no error found.
+        iConTransferMgr->SendEp0ZeroByteStatusPacket();                            // success: zero bytes data during status stage
+        
+        // 9.4.9: "The transition to test mode of an upstream facing port must not happen until
+        // after the status stage of the request."
+        if (test_sel)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Entering HS Test Mode %d", test_sel));
+            iController.EnterTestMode((UsbShai::TUsbTestModeSelector)test_sel);
+            }
+        }
+    }
+
+
+void DUsbClientController::ProcessSetClearIfcFeature(const TUsbcSetup& aPacket)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetClearIfcFeature()"));
+    if ( iDeviceState < UsbShai::EUsbPeripheralStateConfigured)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
+        iLastError = KErrGeneral;
+        }
+    else
+        {
+        // No interface features defined in USB spec, thus
+        iLastError = KErrGeneral;
+        }
+    }
+
+
+void DUsbClientController::ProcessSetClearEpFeature(const TUsbcSetup& aPacket)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetClearEpFeature()"));
+    if (
+        ((iDeviceState < UsbShai::EUsbPeripheralStateAddress) ||
+         (iDeviceState == UsbShai::EUsbPeripheralStateAddress && (aPacket.iIndex & KUsbEpAddress_Portmask) != 0)))
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
+        iLastError = KErrGeneral;
+        }
+    else if (aPacket.iValue != KUsbFeature_EndpointHalt)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Unknown feature requested"));
+        iLastError = KErrGeneral;
+        }
+    else if (EndpointExists(aPacket.iIndex) == EFalse)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Endpoint does not exist"));
+        iLastError = KErrGeneral;
+        }
+    else
+        {
+        const TInt ep = EpAddr2Idx(aPacket.iIndex);
+        if (iRealEndpoints[ep].iLEndpoint->iInfo.iType == UsbShai::KUsbEpTypeControl ||
+            iRealEndpoints[ep].iLEndpoint->iInfo.iType == UsbShai::KUsbEpTypeIsochronous)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Endpoint is Control or Isochronous"));
+            iLastError = KErrGeneral;
+            }
+        else
+            {
+            SetClearHaltFeature(ep, aPacket.iRequest);
+        
+            // success: zero bytes data during status stage
+            iConTransferMgr->SendEp0ZeroByteStatusPacket();
+            }
+        }
+    }
+
+
+void DUsbClientController::ProcessSetAddress(const TUsbcSetup& aPacket)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetAddress()"));
+    if ( iDeviceState > UsbShai::EUsbPeripheralStateAddress)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
+        iLastError = KErrGeneral;
+        }
+    else
+        {
+        const TUint16 addr = aPacket.iValue;
+        
+        if (addr > 127)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Bad address value: %d (>127)", addr));
+            iLastError = KErrGeneral;
+            }
+        else if (addr == 0)
+            {
+            // Enter Default state (from Default or Address)
+            NextDeviceState(UsbShai::EUsbPeripheralStateDefault);
+            }
+        
+        __KTRACE_OPT(KUSB, Kern::Printf("  USB address: %d", addr));
+        
+        // If controller support hw acceleration,call set address first and then status
+        if(iControllerProperties.iControllerCaps & UsbShai::KDevCapSetAddressAcceleration)
+            {
+            iController.SetDeviceAddress(addr);
+            }
+
+        // The spec says, under section 9.4.6:
+        // "Stages after the initial Setup packet assume the same device address as the Setup packet. The USB
+        // device does not change its device address until after the Status stage of this request is completed
+        // successfully. Note that this is a difference between this request and all other requests. For all other
+        // requests, the operation indicated must be completed before the Status stage."
+        // Therefore, here we first send the status packet and only then actually execute the request.
+        iConTransferMgr->SendEp0ZeroByteStatusPacket();
+        
+        // If controller doesn't support hw acceleration, call set address after status
+        if((iControllerProperties.iControllerCaps & UsbShai::KDevCapSetAddressAcceleration) == 0)
+            {
+            iController.SetDeviceAddress(addr);
+            }
+        }
+    }
+
+
+void DUsbClientController::ProcessGetDescriptor(const TUsbcSetup& aPacket)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetDescriptor()"));
+    if ( iDeviceState < UsbShai::EUsbPeripheralStateDefault)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
+        iLastError = KErrGeneral;
+        return ;
+        }
+
+    // Make sure we assume the correct speed
+    __ASSERT_DEBUG((iHighSpeed == CurrentlyUsingHighSpeed()), Kern::Fault(KUsbPILPanicCat, __LINE__));
+
+    TInt size = 0;
+    const TInt result = iDescriptors.FindDescriptor(HighByte(aPacket.iValue), // Type
+                                                    LowByte(aPacket.iValue), // Index
+                                                    aPacket.iIndex, // Language ID
+                                                    size);
+
+    if ((result != KErrNone) || (size == 0))
+        {
+        // This doesn't have to be an error - protocol-wise it's OK.
+        __KTRACE_OPT(KUSB, Kern::Printf("  Couldn't retrieve descriptor"));
+        iLastError = KErrGeneral;
+        return;
+        }
+
+    __KTRACE_OPT(KUSB, Kern::Printf("  Descriptor found, size: %d (requested: %d)",
+                                    size, aPacket.iLength));
+    if (size > KUsbcBufSz_Ep0Tx)
+        {
+        // This should actually not be possible (i.e. we should never get here).
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Ep0_Tx buffer too small"));
+        }
+    if (size > aPacket.iLength)
+        {
+        // Send only as much data as requested by the host
+        size = aPacket.iLength;
+        }
+
+#ifdef ENABLE_EXCESSIVE_DEBUG_OUTPUT
+    __KTRACE_OPT(KUSB,
+                 Kern::Printf("  Data: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x ...",
+                              iEp0_TxBuf[0], iEp0_TxBuf[1], iEp0_TxBuf[2], iEp0_TxBuf[3],
+                              iEp0_TxBuf[4], iEp0_TxBuf[5], iEp0_TxBuf[6], iEp0_TxBuf[7]));
+#endif
+    // If we're about to send less bytes than expected by the host AND our number is a
+    // multiple of the packet size, in order to indicate the end of the control transfer,
+    // we must finally send a zero length data packet (ZLP):
+    const TBool zlp = ((size < aPacket.iLength) && (size % iEp0MaxPacketSize == 0));
+    if (iConTransferMgr->SetupEndpointZeroWrite(iEp0_TxBuf, size, zlp) == KErrNone)
+        {
+        iEp0WritePending = ETrue;
+        }
+    else
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Wrong: Write to Ep0 Failed"));
+        }
+    }
+
+
+void DUsbClientController::ProcessSetDescriptor(const TUsbcSetup& aPacket)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetDescriptor()"));
+#ifndef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST
+    iLastError = KErrGeneral;
+    return;
+#else
+    if ( iDeviceState < UsbShai::EUsbPeripheralStateAddress)
+        {
+        // Error: Invalid device state!
+        iLastError = KErrGeneral;
+        }
+    else if (aPacket.iLength > KUsbcBufSz_Ep0Rx)
+        {
+        // Error: Our Rx buffer is too small! (Raise a defect to make it larger)
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Ep0_Rx buffer too small"));
+        iLastError = KErrGeneral;
+        }
+    else
+        {
+        SetEp0DataOutVars();
+        iConTransferMgr->SetupEndpointZeroRead();
+        }
+#endif
+    }
+
+void DUsbClientController::ProcessGetConfiguration(const TUsbcSetup& aPacket)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetConfiguration()"));
+    if ( iDeviceState < UsbShai::EUsbPeripheralStateAddress)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
+        iLastError = KErrGeneral;
+        }
+    else if ( iDeviceState == UsbShai::EUsbPeripheralStateAddress && iCurrentConfig != 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: DeviceState Address && Config != 0"));
+        iLastError = KErrGeneral;
+        }
+    else if ( iDeviceState == UsbShai::EUsbPeripheralStateConfigured && iCurrentConfig == 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: DeviceState Configured && Config == 0"));
+        iLastError = KErrGeneral;
+        }
+    else
+        {
+        if (aPacket.iLength != 1)                                // "unspecified behavior"
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  Warning: wLength != 1 (= %d)", aPacket.iLength));
+            }
+        __KTRACE_OPT(KUSB, Kern::Printf("  Reporting configuration value %d", iCurrentConfig));
+        if (iConTransferMgr->SetupEndpointZeroWrite(&iCurrentConfig, sizeof(iCurrentConfig)) == KErrNone)
+            {
+            iEp0WritePending = ETrue;
+            }
+        else
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  Wrong: Write to Ep0 Failed"));
+            }
+        }
+    }
+
+
+/** Changes the device's configuration value, including interface setup and/or
+    teardown and state change notification of higher-layer clients.
+    May also be called by the PSL in special cases - therefore publishedPartner.
+
+    @param aPacket The received Ep0 SET_CONFIGURATION setup request packet.
+    @return KErrGeneral in case of a protocol error, KErrNone otherwise.
+
+    @publishedPartner @released
+*/
+TInt DUsbClientController::ProcessSetConfiguration(const TUsbcSetup& aPacket)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetConfiguration()"));
+
+    // This function may be called by the PSL from within an ISR -- so we have
+    // to take care what we do here (and also in all functions that get called
+    // from here).
+    const TInt value = aPacket.iValue;
+    
+    if ( iDeviceState < UsbShai::EUsbPeripheralStateAddress)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
+        iLastError = KErrGeneral;
+        }    
+    else if (value > 1)                                            // we support only one configuration
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Configuration value too large: %d", value));
+        iLastError = KErrGeneral;
+        }
+    else
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Configuration value: %d", value));
+        ChangeConfiguration(value);
+
+        // In 9.4.5 under GET_STATUS we read, that after SET_CONFIGURATION the HALT feature
+        // for all endpoints is reset to zero.
+        TInt num = 0;
+        (TAny) DoForEveryEndpointInUse(&DUsbClientController::ClearHaltFeature, num);
+        __KTRACE_OPT(KUSB, Kern::Printf("  Called ClearHaltFeature() for %d endpoints", num));
+        // success: zero bytes data during status stage
+        iConTransferMgr->SendEp0ZeroByteStatusPacket();
+        }
+        
+    return iLastError;
+    }
+
+void DUsbClientController::ProcessGetInterface(const TUsbcSetup& aPacket)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetInterface()"));
+    
+    const TInt number = aPacket.iIndex;
+    
+    if ( iDeviceState < UsbShai::EUsbPeripheralStateConfigured)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
+        iLastError = KErrGeneral;
+        }
+    else if (iCurrentConfig == 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Device not configured"));
+        iLastError = KErrGeneral;
+        }    
+    else if (!InterfaceExists(number))
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Bad interface index: %d", number));
+        iLastError = KErrGeneral;
+        }
+    else
+        {
+        // Send alternate setting code of iCurrentInterface of Interface(set) <number> of the current
+        // config (iCurrentConfig).
+        const TUint8 setting = InterfaceNumber2InterfacePointer(number)->iCurrentInterface;
+        __KTRACE_OPT(KUSB, Kern::Printf("  Reporting interface setting %d", setting));
+        if (iConTransferMgr->SetupEndpointZeroWrite(&setting, 1) == KErrNone)
+            {
+            iEp0WritePending = ETrue;
+            }
+        else
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  Wrong: Write to Ep0 Failed"));
+            }
+        }
+    }
+
+
+void DUsbClientController::ProcessSetInterface(const TUsbcSetup& aPacket)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetInterface()"));
+    
+    const TInt number = aPacket.iIndex;
+    
+    if ( iDeviceState < UsbShai::EUsbPeripheralStateConfigured)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
+        iLastError = KErrGeneral;
+        }
+    else if (iCurrentConfig == 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Device not configured"));
+        iLastError = KErrGeneral;
+        }    
+    else if (!InterfaceExists(number))
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Bad interface index: %d", number));
+        iLastError = KErrGeneral;
+        }
+    else
+        {
+        const TInt setting = aPacket.iValue;
+        TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(number);
+        RPointerArray<TUsbcInterface>& ifcs = ifcset_ptr->iInterfaces;
+        if (setting >= ifcs.Count())
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Alt Setting >= bNumAltSettings: %d", setting));
+            iLastError = KErrGeneral;
+            }
+        else
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  Interface setting:: %d", setting));
+            // Set iCurrentInterface of Interface(set) <number> of the current config
+            // (iCurrentConfig) to alternate setting <setting>.
+            ChangeInterface(ifcs[setting]);
+            // In 9.4.5 under GET_STATUS we read, that after SET_INTERFACE the HALT feature
+            // for all endpoints (of the now current interface setting) is reset to zero.
+            RPointerArray<TUsbcLogicalEndpoint>& eps = ifcset_ptr->CurrentInterface()->iEndpoints;
+            const TInt num_eps = eps.Count();
+            for (TInt i = 0; i < num_eps; i++)
+                {
+                const TInt ep_num = EpAddr2Idx(eps[i]->iPEndpoint->iEndpointAddr);
+                (TAny) ClearHaltFeature(ep_num);
+                }
+            // success: zero bytes data during status stage
+            iConTransferMgr->SendEp0ZeroByteStatusPacket();    
+            }
+        }
+    }
+
+
+void DUsbClientController::ProcessSynchFrame(const TUsbcSetup& aPacket)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSynchFrame()"));
+    
+    const TInt ep = aPacket.iIndex;
+    
+    if ( iDeviceState < UsbShai::EUsbPeripheralStateConfigured)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
+        iLastError = KErrGeneral;
+        }    
+    else if (EndpointExists(ep) == EFalse)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Endpoint does not exist"));
+        iLastError = KErrGeneral;
+        }
+    else if (iRealEndpoints[EpAddr2Idx(ep)].iLEndpoint->iInfo.iType != UsbShai::KUsbEpTypeIsochronous)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Endpoint is not isochronous"));
+        iLastError = KErrGeneral;
+        }
+    else 
+        {
+        // We always send 0:
+        *reinterpret_cast<TUint16*>(iEp0_TxBuf) = 0x00;
+        if (iConTransferMgr->SetupEndpointZeroWrite(iEp0_TxBuf, 2) == KErrNone)
+            {
+            iEp0WritePending = ETrue;
+            }
+        else
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  Wrong: Write to Ep0 Failed"));
+            }
+        }
+    }
+
+
+#ifdef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST
+void DUsbClientController::ProceedSetDescriptor()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProceedSetDescriptor()"));
+    // iEp0DataReceived already reflects the current buffer state
+    if (iEp0DataReceived < iConTransferMgr->PktParser().DataLength())
+        {
+        // Not yet all data received => proceed
+        return;
+        }
+    if (iEp0DataReceived > iConTransferMgr->PktParser().DataLength())
+        {
+        // Error: more data received than expected
+        // but we don't care...
+        }
+    const TUint8 type = HighByte(iConTransferMgr->PktParser().Value());
+    if (type == KUsbDescType_String)
+        {
+        // set/add new string descriptor
+        }
+    else
+        {
+        // set/add new ordinary descriptor
+        }
+    TUint8 index = LowByte(iConTransferMgr->PktParser().Value());
+    TUint16 langid = iConTransferMgr->PktParser().Index();
+    TUint16 length_total = iConTransferMgr->PktParser().DataLength();
+
+    iConTransferMgr->SendEp0ZeroByteStatusPacket();
+    }
+#endif
+
+
+// --- Secondary (Helper) Functions
+
+void DUsbClientController::SetClearHaltFeature(TInt aRealEndpoint, TUint8 aRequest)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetClearHaltFeature()"));
+    if (aRequest == KUsbRequest_SetFeature)
+        {
+        if (iRealEndpoints[aRealEndpoint].iHalt)
+            {
+            // (This condition is not really an error)
+            __KTRACE_OPT(KUSB, Kern::Printf("  Warning: HALT feature already set"));
+            return;
+            }
+        __KTRACE_OPT(KUSB, Kern::Printf("  setting HALT feature for real endpoint %d",
+                                        aRealEndpoint));
+        iController.StallEndpoint(aRealEndpoint);
+        iRealEndpoints[aRealEndpoint].iHalt = ETrue;
+        }
+    else                                                    // KUsbRequest_ClearFeature
+        {
+        if (iRealEndpoints[aRealEndpoint].iHalt == EFalse)
+            {
+            // In this case, before we return, the data toggles are reset to DATA0.
+            __KTRACE_OPT(KUSB, Kern::Printf("  Warning: HALT feature already cleared"));
+            iController.ResetDataToggle(aRealEndpoint);
+            return;
+            }
+        __KTRACE_OPT(KUSB, Kern::Printf("  clearing HALT feature for real endpoint %d",
+                                        aRealEndpoint));
+        iController.ResetDataToggle(aRealEndpoint);
+        iController.ClearStallEndpoint(aRealEndpoint);
+        iRealEndpoints[aRealEndpoint].iHalt = EFalse;
+        }
+    EpStatusNotify(aRealEndpoint);                            // only called if actually something changed
+    }
+
+
+TInt DUsbClientController::ClearHaltFeature(TInt aRealEndpoint)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ClearHaltFeature()"));
+    if (iRealEndpoints[aRealEndpoint].iHalt != EFalse)
+        {
+        iController.ClearStallEndpoint(aRealEndpoint);
+        iRealEndpoints[aRealEndpoint].iHalt = EFalse;
+        }
+    return KErrNone;
+    }
+
+
+void DUsbClientController::ChangeConfiguration(TUint16 aValue)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ChangeConfiguration()"));
+    // New configuration is the same as the old one: 0
+    if (iCurrentConfig == 0 && aValue == 0)
+        {
+        // no-op
+        __KTRACE_OPT(KUSB, Kern::Printf("  Configuration: New == Old == 0 --> exiting"));
+        return;
+        }
+    // New configuration is the same as the old one (but not 0)
+    if (iCurrentConfig == aValue)
+        {
+        // no-op
+        __KTRACE_OPT(KUSB, Kern::Printf("  Configuration: New == Old == %d --> exiting", aValue));
+        return;
+        }
+    // Device is already configured
+    if (iCurrentConfig != 0)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Device was configured: %d", iCurrentConfig));
+        // Tear down all interface(set)s of the old configuration
+        RPointerArray<TUsbcInterfaceSet>& ifcsets = CurrentConfig()->iInterfaceSets;
+        for (TInt i = 0; i < ifcsets.Count(); ++i)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  Tearing down InterfaceSet %d", i));
+            InterfaceSetTeardown(ifcsets[i]);
+            }
+        iCurrentConfig = 0;
+        // Enter Address state (from Configured)
+        if (iDeviceState == UsbShai::EUsbPeripheralStateConfigured)
+            NextDeviceState(UsbShai::EUsbPeripheralStateAddress);
+        }
+    // Device gets a new configuration
+    if (aValue != 0)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Device gets new configuration..."));
+        // Setup all alternate settings 0 of all interfaces
+        // (Don't separate the next two lines of code.)
+        iCurrentConfig = aValue;
+        RPointerArray<TUsbcInterfaceSet>& ifcsets = CurrentConfig()->iInterfaceSets;
+        const TInt n = ifcsets.Count();
+        for (TInt i = 0; i < n; ++i)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  Setting up InterfaceSet %d", i));
+            InterfaceSetup(ifcsets[i]->iInterfaces[0]);
+            }
+        // Enter Configured state (from Address or Configured)
+        NextDeviceState(UsbShai::EUsbPeripheralStateConfigured);
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("  New configuration: %d", iCurrentConfig));
+    return;
+    }
+
+
+void DUsbClientController::InterfaceSetup(TUsbcInterface* aIfc)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::InterfaceSetup()"));
+    const TInt num_eps = aIfc->iEndpoints.Count();
+    for (TInt i = 0; i < num_eps; i++)
+        {
+        // Prepare this endpoint for I/O
+        TUsbcLogicalEndpoint* const ep = aIfc->iEndpoints[i];
+        // (TUsbcLogicalEndpoint's FS/HS endpoint sizes and interval values got
+        //  adjusted in its constructor.)
+        if (iHighSpeed)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  Setting Ep info size to %d (HS)", ep->iEpSize_Hs));
+            ep->iInfo.iSize = ep->iEpSize_Hs;
+            }
+        else
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  Setting Ep info size to %d (FS)", ep->iEpSize_Fs));
+            ep->iInfo.iSize = ep->iEpSize_Fs;
+            }
+        const TInt idx = EpAddr2Idx(ep->iPEndpoint->iEndpointAddr);
+        if (iController.ConfigureEndpoint(idx, ep->iInfo) != KErrNone)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Endpoint %d configuration failed", idx));
+            continue;
+            }
+        // Should there be a problem with it then we could try resetting the ep
+        // data toggle at this point (or before the Configure) as well.
+        __KTRACE_OPT(KUSB, Kern::Printf("  Connecting real ep addr 0x%02x & logical ep #%d",
+                                        ep->iPEndpoint->iEndpointAddr, ep->iLEndpointNum));
+        ep->iPEndpoint->iLEndpoint = ep;
+        }
+    aIfc->iInterfaceSet->iCurrentInterface = aIfc->iSettingCode;
+    return;
+    }
+
+
+void DUsbClientController::InterfaceSetTeardown(TUsbcInterfaceSet* aIfcSet)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::InterfaceSetTeardown()"));
+    if (aIfcSet->iInterfaces.Count() == 0)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  No interfaces exist - returning"));
+        return;
+        }
+    RPointerArray<TUsbcLogicalEndpoint>& eps = aIfcSet->CurrentInterface()->iEndpoints;
+    const TInt num_eps = eps.Count();
+    for (TInt i = 0; i < num_eps; i++)
+        {
+        TUsbcLogicalEndpoint* const ep = eps[i];
+        const TInt idx = EpAddr2Idx(ep->iPEndpoint->iEndpointAddr);
+
+        CancelTransferRequests(idx);
+
+        if (!ep->iPEndpoint->iLEndpoint)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  real ep %d not configured: skipping", idx));
+            continue;
+            }
+        if (iController.ResetDataToggle(idx) != KErrNone)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Endpoint %d data toggle reset failed", idx));
+            }
+        if (iController.DeConfigureEndpoint(idx) != KErrNone)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Endpoint %d de-configuration failed", idx));
+            }
+
+        __KTRACE_OPT(KUSB, Kern::Printf("  disconnecting real ep & logical ep"));
+        ep->iPEndpoint->iLEndpoint = NULL;
+        }
+    if (aIfcSet->CurrentInterface() != 0)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Resetting alternate interface setting to 0"));
+        //Add this mutex to protect the interface set data structure
+        if (NKern::CurrentContext() == EThread)
+            {
+            NKern::FMWait(&iMutex);
+            }
+        
+        aIfcSet->iCurrentInterface = 0;
+        if (NKern::CurrentContext() == EThread)
+            {
+            NKern::FMSignal(&iMutex);
+            }        
+        }
+    return;
+    }
+
+
+void DUsbClientController::ChangeInterface(TUsbcInterface* aIfc)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ChangeInterface()"));
+    TUsbcInterfaceSet* ifcset = aIfc->iInterfaceSet;
+    const TUint8 setting = aIfc->iSettingCode;
+    if (ifcset->iCurrentInterface == setting)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  New Ifc == old Ifc: nothing to do"));
+        return;
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("  Setting new interface setting #%d", setting));
+    InterfaceSetTeardown(ifcset);
+    InterfaceSetup(aIfc);
+    StatusNotify(static_cast<UsbShai::TUsbPeripheralState>(KUsbAlternateSetting | setting), ifcset->iClientId);
+    }
+
+
+// aFunction gets called, successively, with the endpoint index of every ep in-use as its argument.
+// (BTW: The declaration "type (class::*name)(params)" makes <name> a "pointer to element function".)
+//
+TInt DUsbClientController::DoForEveryEndpointInUse(TInt (DUsbClientController::*aFunction)(TInt), TInt& aCount)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DoForEveryEndpointInUse()"));
+    aCount = 0;
+    TUsbcConfiguration* const config = CurrentConfig();
+    if (!config)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Device is not configured - returning"));
+        return KErrNone;
+        }
+    RPointerArray<TUsbcInterfaceSet>& ifcsets = config->iInterfaceSets;
+    const TInt num_ifcsets = ifcsets.Count();
+    for (TInt i = 0; i < num_ifcsets; i++)
+        {
+        RPointerArray<TUsbcLogicalEndpoint>& eps = ifcsets[i]->CurrentInterface()->iEndpoints;
+        const TInt num_eps = eps.Count();
+        for (TInt j = 0; j < num_eps; j++)
+            {
+            const TInt ep_num = EpAddr2Idx(eps[j]->iPEndpoint->iEndpointAddr);
+            const TInt result = (this->*aFunction)(ep_num);
+            ++aCount;
+            if (result != KErrNone)
+                {
+                return result;
+                }
+            }
+        }
+    return KErrNone;
+    }
+
+// Data Tx is done.
+void DUsbClientController::ProcessDataInPacket(TInt aCount,TInt aErrCode)
+    {
+    // Clear Error Code
+    iLastError = KErrNone;
+    
+    // For tx, no premature end is allowed.
+    if(aErrCode != KErrNone)
+        {
+        // something wrong in hardware, we can do nothing as remedy
+        // just stall the endpoint.
+        iConTransferMgr->StallEndpoint(KEp0_In);
+        iConTransferMgr->SetupEndpointZeroRead();
+        
+        // set err code to Error general if end point is stalled
+        iLastError = KErrGeneral;
+        }
+    else
+        {
+        // no longer a write pending
+        iEp0WritePending = EFalse;
+        
+        // If it was a client who set up this transmission, we report to that client
+        if (iEp0ClientDataTransmitting)
+            {
+            iEp0ClientDataTransmitting = EFalse;
+            TUsbcRequestCallback* const p = iRequestCallbacks[KEp0_Tx];
+            
+            if (p)
+                {
+                __ASSERT_DEBUG((p->iTransferDir == UsbShai::EControllerWrite), Kern::Fault(KUsbPILPanicCat, __LINE__));
+                p->iError = aErrCode;
+                p->iTxBytes = aCount;
+                
+                // tell the client that the sending is done
+                // later, it is possible that a status out packet comes in,
+                // just ignore it.
+                ProcessDataTransferDone(*p);
+                }
+            else
+                {
+                // we should never goes here
+                iConTransferMgr->StallEndpoint(KEp0_In);
+                
+                // request not found
+                iLastError = KErrNotFound;
+                }
+            }
+        // else
+        //   it is our own who sending the data, no more action needed
+        }
+    }
+
+// Status Rx is done    
+void DUsbClientController::ProcessStatusOutPacket(TInt aErrCode)
+    {
+    // Clear Error Code
+    iLastError = KErrNone;
+    
+    // Dangdang, psl saying a status out packet recieved from
+    // host, but, we already completed user's writting request, just ignore it.
+    
+    // any way, receiving this means no write is pending.
+    iEp0WritePending = EFalse;
+    }
+    
+// Data Rx is (partial) done
+void DUsbClientController::ProcessDataOutPacket(TInt aCount,TInt aErrCode)
+    {
+    // Clear Error Code
+    iLastError = KErrNone;
+    
+    if (aErrCode != KErrNone && aErrCode != KErrPrematureEnd)
+        {
+        // something wrong in hardware, we can do nothing as remedy
+        // just stall the endpoint.
+        iConTransferMgr->StallEndpoint(KEp0_Out);
+        iConTransferMgr->SetupEndpointZeroRead();
+        
+        // set err code to Error general if end point is stalled
+        iLastError = KErrGeneral;       
+        }
+    else
+        {
+        // Trim aCount with iEp0MaxPacketSize per packet
+        if (aCount > iEp0MaxPacketSize)
+            {
+            aCount = iEp0MaxPacketSize;
+            }
+               
+        iEp0DataReceived += aCount;
+        
+        if (iEp0ClientId == NULL)
+            {
+            // it is us( not an app), who owns this transaction
+            switch( iConTransferMgr->PktParser().Request())
+                {
+#ifdef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST                
+                case KUsbRequest_SetDescriptor:
+                    {
+                    memcpy(iEp0_RxCollectionBuf + iEp0DataReceived, iEp0_RxBuf, aCount);                    
+                    
+                    // Status will be sent in side this function
+                    // if we had recieved enough bytes
+                    ProceedSetDescriptor();
+                    }
+                    break;
+#endif                    
+                default:
+                    {
+                    iConTransferMgr->StallEndpoint(KEp0_In);
+                    ResetEp0DataOutVars();
+                    
+                    // set err code to Error general if end point is stalled
+                    iLastError = KErrGeneral;
+                    }
+                    break;
+                }
+            
+            if (iEp0DataReceived >= iConTransferMgr->PktParser().DataLength())
+                {                
+                // all data seems now to be here
+                ResetEp0DataOutVars();
+                }                
+            }
+        else
+            {
+            // it is an application who is requesting this data
+            // pass the data on to a client
+            
+            // it is the client's responsibility of sending a status
+            // packet back to host to indicate the whole transfer is
+            // done
+            
+            // Find the client Request callback
+            TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks);
+            TUsbcRequestCallback* p;
+            while ((p = iter++) != NULL)
+                {
+                if (p->Owner() == iEp0ClientId)
+                    {
+                    memcpy(p->iBufferStart, iEp0_RxBuf, aCount);
+                    p->iError = KErrNone;
+                    *(p->iPacketSize) = aCount;
+                    p->iRxPackets = 1;
+                    *(p->iPacketIndex) = 0;
+                    break;
+                    }
+                }
+            
+            // pass data to client if found one.
+            if ( p != NULL)
+                {
+                ProcessDataTransferDone(*p);
+                    
+                if (iEp0DataReceived >= iConTransferMgr->PktParser().DataLength())
+                    {
+                    // all data seems now to be here
+                    ResetEp0DataOutVars();
+                    }
+                
+                iLastError = KErrNone;
+                
+                }
+            else
+                {
+                // that's bad, we found a client is request this data
+                // but no matching request callback found.
+                
+                iEp0_RxExtraCount = aCount;
+                //iEp0_RxExtraData = ETrue;
+                //iEp0_RxExtraError = aErrCode;
+                iEp0DataReceived -= aCount;
+                
+                // No status packet will be send to host since no client is reading this data,
+                // waiting client to send a status packet.
+                
+                iLastError = KErrNotFound;
+                }
+            }
+        }
+    }
+
+// Status Tx is done    
+void DUsbClientController::ProcessStatusInPacket(TInt aErrCode)
+    {
+    // Clear Error Code
+    iLastError = KErrNone; 
+
+    // it is time to start a new read
+    iEp0WritePending = EFalse;
+    }
+
+//
+// Setup Rx is done
+//
+void DUsbClientController::ProcessSetupPacket(TInt aCount,TInt aErrCode)
+    {
+    
+    if (aErrCode != KErrNone)
+        {
+        // something wrong in hardware, we can do nothing as remedy
+        // just stall the endpoint.
+        iConTransferMgr->StallEndpoint(KEp0_Out);
+        iConTransferMgr->SetupEndpointZeroRead();
+        
+        // set err code to Error general if end point is stalled
+        iLastError = KErrGeneral;       
+        }
+    
+    TUsbcSetup packet;
+    Buffer2Setup(iEp0_RxBuf, packet);
+    
+    // Clear Error Code
+    iLastError = KErrNone;
+    
+    // If this is a standard request, we can handle it here
+    // not need to bother app layer
+    if ((packet.iRequestType & KUsbRequestType_TypeMask) == KUsbRequestType_TypeStd)
+        {
+        // Fixme: this may not needed any more
+        iEp0ReceivedNonStdRequest = EFalse;
+        ProcessStandardRequest(aCount,packet);
+        }
+    else
+        {
+        // Fixme: This may not needed anymore
+        iEp0ReceivedNonStdRequest = ETrue;
+        ProcessNonStandardRequest(aCount,packet);
+        }
+    }
+
+#define USB_PROCESS_REQUEST(request,param) \
+    do \
+    { \
+    Process ## request(param); \
+    if (iLastError != KErrNone) \
+        { \
+        __KTRACE_OPT(KUSB, \
+                    Kern::Printf("  ProcessEp0SetupReceived: Stalling Ep0")); \
+        iConTransferMgr->StallEndpoint(KEp0_In); \
+        } \
+    }while(0)
+    
+    
+//
+// Standard request
+// Please note that:Macro USB_PROCESS_REQUEST(xxx) will stall endpoint
+// if anything wrong during the process, in which case status packet is 
+// not needed.
+//
+void DUsbClientController::ProcessStandardRequest(TInt /*aCount*/,const TUsbcSetup& aPacket)
+    {
+    switch (aPacket.iRequest)
+        {
+        case KUsbRequest_GetStatus:
+            switch (aPacket.iRequestType & KUsbRequestType_DestMask)
+                { // Recipient
+                case KUsbRequestType_DestDevice:
+                    USB_PROCESS_REQUEST(GetDeviceStatus,aPacket);
+                    break;
+                    
+                case KUsbRequestType_DestIfc:
+                    USB_PROCESS_REQUEST(GetInterfaceStatus,aPacket);
+                    break;
+                    
+                case KUsbRequestType_DestEp:
+                    USB_PROCESS_REQUEST(GetEndpointStatus,aPacket);
+                    break;
+                    
+                default:
+                    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: GET STATUS - Other or Unknown recipient"));
+                    __KTRACE_OPT(KPANIC, Kern::Printf("  -> DUsbClientController::ProcessEp0SetupReceived: "
+                                                      "Stalling Ep0"));
+                    iConTransferMgr->StallEndpoint(KEp0_In);
+                    iLastError = KErrGeneral;
+                    break;
+                }
+                break;
+        
+        case KUsbRequest_ClearFeature:
+        case KUsbRequest_SetFeature:
+            switch (aPacket.iRequestType & KUsbRequestType_DestMask)
+                { // Recipient
+                case KUsbRequestType_DestDevice:
+                    USB_PROCESS_REQUEST(SetClearDevFeature,aPacket);
+                    break;
+                case KUsbRequestType_DestIfc:
+                    // will 100% stall endpoint
+                    USB_PROCESS_REQUEST(SetClearIfcFeature,aPacket);
+                    break;
+                case KUsbRequestType_DestEp:
+                    USB_PROCESS_REQUEST(SetClearEpFeature,aPacket);
+                    break;
+                default:
+                    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: SET/CLEAR FEATURE - "
+                                                      "Other or Unknown recipient"));
+                    __KTRACE_OPT(KPANIC, Kern::Printf("  -> Stalling Ep0"));
+                    iConTransferMgr->StallEndpoint(KEp0_In);
+                    iLastError = KErrGeneral;
+                    break;
+                }
+                break;
+                
+        case KUsbRequest_SetAddress:
+            USB_PROCESS_REQUEST(SetAddress,aPacket);
+            break;
+            
+        case KUsbRequest_GetDescriptor:
+            USB_PROCESS_REQUEST(GetDescriptor,aPacket);
+            break;
+            
+        case KUsbRequest_SetDescriptor:
+            USB_PROCESS_REQUEST(SetDescriptor,aPacket);
+            break;
+            
+        case KUsbRequest_GetConfig:
+            USB_PROCESS_REQUEST(GetConfiguration,aPacket);
+            break;
+            
+        case KUsbRequest_SetConfig:
+            USB_PROCESS_REQUEST(SetConfiguration,aPacket);
+            break;
+            
+        case KUsbRequest_GetInterface:
+            USB_PROCESS_REQUEST(GetInterface,aPacket);
+            break;
+            
+        case KUsbRequest_SetInterface:
+            USB_PROCESS_REQUEST(SetInterface,aPacket);
+            break;
+            
+        case KUsbRequest_SynchFrame:
+            USB_PROCESS_REQUEST(SynchFrame,aPacket);
+            break;
+            
+        default:
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Unknown/unsupported Std Setup Request"));
+            __KTRACE_OPT(KPANIC, Kern::Printf("  -> Stalling Ep0"));
+            iConTransferMgr->StallEndpoint(KEp0_In);
+            iLastError = KErrGeneral;
+            break;
+        }       
+    }
+
+#undef USB_PROCESS_REQUEST
+    
+//
+// class- or vendor-specific request    
+// we dont send back any status to host in PIL for class- or vendor-specific request
+// if no client is waiting, stall the endpoint
+// if client is not ready, just record them and waiting for client to read them
+// (and, send a status packet)
+//
+void DUsbClientController::ProcessNonStandardRequest(TInt aCount,const TUsbcSetup& aPacket)
+    {
+    // Find out which client can handle this request
+    const DBase* client = FindNonStandardRequestClient(aPacket.iRequestType & KUsbRequestType_DestMask,aPacket);
+        
+    // If client is valide
+    if (client != NULL)
+        {
+        // Try to relay aPacket to the real recipient
+        TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks);
+        TUsbcRequestCallback* p;
+        
+        // Find out the request callback with match the client 
+        // returned from last FindNonStandardRequestClient().
+        while ((p = iter++) != NULL)
+            {
+            if (p->Owner() == client)
+                {
+                __ASSERT_DEBUG((p->iEndpointNum == 0), Kern::Fault(KUsbPILPanicCat, __LINE__));
+                __ASSERT_DEBUG((p->iTransferDir == UsbShai::EControllerRead), Kern::Fault(KUsbPILPanicCat, __LINE__));
+                __KTRACE_OPT(KUSB, Kern::Printf("  Found Ep0 read request"));
+                if (aPacket.iLength != 0)
+                    {
+                    if ((aPacket.iRequestType & KUsbRequestType_DirMask) == KUsbRequestType_DirToDev)
+                        {
+                        // Data transfer & direction OUT => there'll be a DATA_OUT stage
+                        __KTRACE_OPT(KUSB, Kern::Printf("  Next is DATA_OUT: setting up DataOutVars"));
+                        SetEp0DataOutVars(client);
+                        }
+                    else if ((aPacket.iRequestType & KUsbRequestType_DirMask) == KUsbRequestType_DirToHost)
+                        {
+                        // For possible later use (ZLP).
+                        iEp0_TxNonStdCount = aPacket.iLength;
+                        }
+                    }
+                    
+                // Found the request callback, jump out now
+                break;                
+                }
+            }
+            
+        // if a request callback matching the client is found,
+        // complete the request
+        if( p != NULL)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  Ep0 read request completed to client"));
+            memcpy(p->iBufferStart, iEp0_RxBuf, aCount);
+            p->iError = KErrNone;
+            *(p->iPacketSize) = aCount;
+            p->iRxPackets = 1;
+            *(p->iPacketIndex) = 0;
+            ProcessDataTransferDone(*p);            
+            }
+        else
+            {            
+            __KTRACE_OPT(KUSB, Kern::Printf("  Ep0 read request not found: setting RxExtra vars (Setup)"));
+            iEp0_RxExtraCount = aCount;
+            //iEp0_RxExtraData = ETrue;
+            //iEp0_RxExtraError = aErrCode;
+            iSetupPacketPending = ETrue;
+            
+            // For setup packet,a zero bytes status is always needed
+            iLastError = KErrNotFound;           
+            }
+        }
+    else // if (client == NULL)
+        {
+        // Pil don't know how to deal with non-standard request, stall endpoint
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Ep0 request error: Stalling Ep0"));
+        iConTransferMgr->StallEndpoint(KEp0_In);
+        iLastError = KErrGeneral;
+        }
+    }
+    
+const DBase* DUsbClientController::FindNonStandardRequestClient(TUint8 aPacketTypeDestination,const TUsbcSetup& aPacket)
+    {
+    const DBase* client = NULL;
+    
+    switch (aPacketTypeDestination)
+        { // Recipient
+        case KUsbRequestType_DestDevice:
+            {
+            client = iEp0DeviceControl;
+            }
+            break;
+            
+        case KUsbRequestType_DestIfc:
+            {
+            //Add this mutex to protect the interface set data structure
+            if (NKern::CurrentContext() == EThread)
+                {
+                NKern::FMWait(&iMutex);
+                }
+                
+            if ( iDeviceState < UsbShai::EUsbPeripheralStateConfigured)
+                {
+                __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
+                }
+            else
+                {
+                const TUsbcInterfaceSet* const ifcset_ptr =
+                    InterfaceNumber2InterfacePointer(aPacket.iIndex);
+                    
+                //In some rare case, ifcset_ptr is not NULL but the ifcset_ptr->iInterfaces.Count() is 0,
+                //so panic will happen when excute the following line. so I add the conditon
+                //0 != ifcset_ptr->iInterfaces.Count() here.
+                if (ifcset_ptr && 0 != ifcset_ptr->iInterfaces.Count())
+                    {
+                    if (ifcset_ptr->CurrentInterface()->iNoEp0Requests)
+                        {
+                        __KTRACE_OPT(KUSB, Kern::Printf("  Recipient says: NoEp0RequestsPlease"));
+                        }
+                    else
+                        {
+                        client = ifcset_ptr->iClientId;
+                        }
+                    }
+                else
+                    {
+                    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface 0x%02x does not exist",
+                                                      aPacket.iIndex));
+                    }
+                }
+                
+            if (NKern::CurrentContext() == EThread)
+                {
+                NKern::FMSignal(&iMutex);
+                }
+            }
+            break;
+                        
+        case KUsbRequestType_DestEp:
+            {
+            //Add this mutex to protect the interface set data structure
+            if (NKern::CurrentContext() == EThread)
+                {
+                NKern::FMWait(&iMutex);
+                }
+            if ( iDeviceState < UsbShai::EUsbPeripheralStateConfigured)
+                {
+                __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
+                }
+            else if (EndpointExists(aPacket.iIndex) == EFalse)
+                {
+                __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Endpoint 0x%02x does not exist",
+                                                  aPacket.iIndex));
+                }
+            else
+                {
+                const TInt idx = EpAddr2Idx(aPacket.iIndex);
+                const TUsbcInterfaceSet* const ifcset_ptr =
+                    iRealEndpoints[idx].iLEndpoint->iInterface->iInterfaceSet;
+                if (ifcset_ptr->CurrentInterface()->iNoEp0Requests)
+                    {
+                    __KTRACE_OPT(KUSB, Kern::Printf("  Recipient says: NoEp0RequestsPlease"));
+                    }
+                else
+                    {
+                    client = ifcset_ptr->iClientId;
+                    }
+                }
+            if (NKern::CurrentContext() == EThread)
+                {
+                NKern::FMSignal(&iMutex);
+                }
+            }
+            break;
+            
+        default:
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Other or Unknown recipient"));
+            break;
+            }
+        }
+        
+    return client;
+    }
+
+TInt DUsbClientController::ProcessSetupEndpointZeroRead()
+    {
+    __KTRACE_OPT(KPANIC, Kern::Printf("DUsbClientController:: Read EP0 Issued"));
+    return iController.SetupEndpointZeroRead();
+    }
+    
+TInt DUsbClientController::ProcessSetupEndpointZeroWrite(const TUint8* aBuffer, TInt aLength, TBool aZlpReqd)
+    {
+    __KTRACE_OPT(KPANIC, Kern::Printf("DUsbClientController:: Write EP0 Issued"));
+    return iController.SetupEndpointZeroWrite(aBuffer,aLength,aZlpReqd);
+    }
+    
+TInt DUsbClientController::ProcessSendEp0ZeroByteStatusPacket()
+    {
+    __KTRACE_OPT(KPANIC, Kern::Printf("DUsbClientController:: Zero Status to EP0 Issued"));
+    return iController.SendEp0ZeroByteStatusPacket();
+    }
+    
+TInt DUsbClientController::ProcessStallEndpoint(TInt aRealEndpoint)
+    {
+    __KTRACE_OPT(KPANIC, Kern::Printf("DUsbClientController:: EP0(%d) Stall Issued",aRealEndpoint));
+    return iController.StallEndpoint(aRealEndpoint);
+    }
+
+void DUsbClientController::ProcessEp0SetupPacketProceed()
+    {
+    __KTRACE_OPT(KPANIC, Kern::Printf("DUsbClientController:: Missed setup packet procced"));
+    iController.Ep0ReadSetupPktProceed();
+    }
+    
+void DUsbClientController::ProcessEp0DataPacketProceed()
+    {
+    __KTRACE_OPT(KPANIC, Kern::Printf("DUsbClientController:: Missed data packet procced"));
+    iController.Ep0ReadDataPktProceed();
+    }
+    
+// -eof-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/pdd/pil/src/controltransfersm.cpp	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,604 @@
+/*
+  Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). 
+  All rights reserved.
+
+  This program and the accompanying materials are made available 
+  under the terms of the Eclipse Public License v1.0 which accompanies 
+  this distribution, and is available at 
+  http://www.eclipse.org/legal/epl-v10.html
+
+  Initial Contributors:
+  Nokia Corporation - initial contribution.
+
+  Contributors:
+*/
+
+#include "controltransfersm.h"
+
+// Bitmap of setup packet
+/*
+Offset 0, bmRequestType, 1 bytes
+    1 Bit-Map
+        D7 Data Phase Transfer Direction
+        0 = Host to Device
+        1 = Device to Host
+    
+        D6..5 Type
+        0 = Standard
+        1 = Class
+        2 = Vendor
+        3 = Reserved
+    
+        D4..0 Recipient
+        0 = Device
+        1 = Interface
+        2 = Endpoint
+        3 = Other
+        4..31 = Reserved
+
+Offset 1, bRequest
+
+Offset 6, Count, 2 bytes
+        Number of bytes to transfer if there is a data phase
+*/
+
+#if defined(_DEBUG)
+
+#define CTSM_ID "ControlTransferSM "
+
+char* DebugName[] = 
+    {
+    "Setup",
+    "Data Out",
+    "Status In",
+    "Data In",
+    "Status Out"
+    };
+    
+#endif
+
+// Static data instance
+TUsbcSetup TSetupPkgParser::iSetupPkt;
+
+TSetupPkgParser::TSetupPkgParser()
+    {
+    iSetupPkt.iRequestType = 0;
+    iSetupPkt.iRequest = 0;
+    
+    iSetupPkt.iValue  = 0;
+    iSetupPkt.iIndex  = 0;
+    iSetupPkt.iLength = 0;
+    }
+
+// Code for TSetupPkgParser
+// we do a bitwise copy here.
+void TSetupPkgParser::Set(const TUint8* aSetupBuf)
+    {
+    // TUint8 index
+    iSetupPkt.iRequestType = static_cast<const TUint8*>(aSetupBuf)[0];
+    iSetupPkt.iRequest = static_cast<const TUint8*>(aSetupBuf)[1];
+    // TUint16 index from here!
+    iSetupPkt.iValue = SWAP_BYTES_16((reinterpret_cast<const TUint16*>(aSetupBuf))[1]);
+    iSetupPkt.iIndex = SWAP_BYTES_16((reinterpret_cast<const TUint16*>(aSetupBuf))[2]);
+    iSetupPkt.iLength = SWAP_BYTES_16((reinterpret_cast<const TUint16*>(aSetupBuf))[3]);
+    
+    __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID "TSetupPkgParser::Set"));
+    }
+
+// return the next stage by decoding the setup packet 
+// the possible stage followed by a setup packet are:
+//      StatusIn (no data stage)
+//      DataOut  (host sent to peripheral)
+//      DataIn   (peripheral to host)
+UsbShai::TControlStage TSetupPkgParser::NextStage()
+    {
+    UsbShai::TControlStage ret = UsbShai::EControlTransferStageMax;
+    
+    // Take the data length out, 0 length means no data stage
+    if (iSetupPkt.iLength == 0)
+        {
+        ret = UsbShai::EControlTransferStageStatusIn;
+        }
+    else if ((iSetupPkt.iRequestType & KUsbRequestType_DirMask) == KUsbRequestType_DirToDev)
+        {
+        // Dir to device means host will send data out
+        ret = UsbShai::EControlTransferStageDataOut;
+        }
+    else
+        {
+        // Otherwise, there must be a datain stage follows
+        ret = UsbShai::EControlTransferStageDataIn;
+        } 
+    
+    __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID "TSetupPkgParser::NextStage %d", ret));
+    
+    return ret;
+    }
+
+// Base class of stage sm
+TControlStageSm::TControlStageSm(DControlTransferManager& aTransferMgr):
+    iTransferMgr(aTransferMgr)
+    {    
+    }
+
+void TControlStageSm::ChangeToStage(UsbShai::TControlStage aToStage)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID "<> TControlStageSm::ChangeToStage: %s",DebugName[aToStage]));
+    iTransferMgr.iCurrentStage = aToStage;
+    }
+
+void TControlStageSm::ClearPendingRead()
+    {
+    iTransferMgr.iReadPending = EFalse;
+    }
+    
+// Code for DControlTransferManager
+// 
+
+DControlTransferManager::DControlTransferManager(MControlTransferIf& aCtrTransIf):
+    iCtrTransferIf(aCtrTransIf)
+    {    
+    for(int i=0; i<UsbShai::EControlTransferStageMax; i++)
+        {
+        iState[i] = NULL;
+        }
+    
+    Reset();
+    }
+
+TInt DControlTransferManager::SetupEndpointZeroRead()
+    {
+    if(iState[iCurrentStage]->IsRequstAllowed(TControlTransferRequestRead))
+        {
+        if(!iReadPending)
+            {
+            iReadPending = ETrue;
+            return CtrTransferIf().ProcessSetupEndpointZeroRead();
+            }
+        else
+            {
+            // A read operation already on going, ignore this request
+            return KErrNone;
+            }
+        }
+    else
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID " !! SetupEndpointZeroRead discard"));
+        return KErrNotReady;
+        }
+    }
+    
+TInt DControlTransferManager::SetupEndpointZeroWrite(const TUint8* aBuffer, TInt aLength, TBool aZlpReqd)
+    {
+    if(iState[iCurrentStage]->IsRequstAllowed(TControlTransferRequestWrite))
+        {
+        return CtrTransferIf().ProcessSetupEndpointZeroWrite(aBuffer,aLength,aZlpReqd);
+        }
+    else
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID " !! SetupEndpointZeroWrite discard"));
+        return KErrNotReady;
+        }    
+    }
+    
+TInt DControlTransferManager::SendEp0ZeroByteStatusPacket()
+    {
+     if(iState[iCurrentStage]->IsRequstAllowed(TControlTransferRequestSendStatus))
+        {
+        iCurrentStage = UsbShai::EControlTransferStageSetup;
+        return CtrTransferIf().ProcessSendEp0ZeroByteStatusPacket();
+        }
+    else
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID " !! SendEp0ZeroByteStatusPacket discard"));
+        return KErrNotReady;
+        }
+    }
+    
+TInt DControlTransferManager::StallEndpoint(TInt aRealEndpoint)
+    {
+    // Endpoint is stalled, we need to reset our state machine.
+    Reset();
+    return CtrTransferIf().ProcessStallEndpoint(aRealEndpoint);
+    }
+
+void DControlTransferManager::Ep0SetupPacketProceed()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID " !! Missed setup packet processed"));
+    CtrTransferIf().ProcessEp0SetupPacketProceed();
+    }
+        
+void DControlTransferManager::Ep0DataPacketProceed()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID " !! Missed data packet processed")); 
+    CtrTransferIf().ProcessEp0DataPacketProceed();
+    }
+    
+void DControlTransferManager::Reset()
+    {
+    iCurrentStage = UsbShai::EControlTransferStageSetup;
+    iReadPending = EFalse;
+    }
+    
+void DControlTransferManager::Ep0RequestComplete(TUint8* aBuf, 
+                                             TInt aCount, 
+                                             TInt aError, 
+                                             UsbShai::TControlPacketType aPktType)
+    {   
+    __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID "> DControlTransferManager::Ep0RequestComplete, packet type: %s", DebugName[aPktType])); 
+    // If a setup packet comes, update our local setup packet buffer first
+    if(aPktType == UsbShai::EControlPacketTypeSetup)
+        {
+        iPacketParser.Set(aBuf);
+        // This is the only place this variable to be reset.
+        iDataTransfered = 0;
+        }
+    
+    // RequestComplete will return ETrue if it can not handle a packet
+    // And it knows that some other sm can handle it.
+    // It will update the state to the one which can hanlde that packet first.        
+    TBool furtherProcessNeeded = ETrue;
+    while(furtherProcessNeeded)
+        {        
+        __KTRACE_OPT(KUSB, Kern::Printf("   We're at Stage:         %s", DebugName[iCurrentStage]));
+        furtherProcessNeeded = iState[iCurrentStage]->RequestComplete(aCount,aError,aPktType);
+        __KTRACE_OPT(KUSB, Kern::Printf("   We're moved to stage:   %s", DebugName[iCurrentStage]));
+        }    
+    
+    __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID "< DControlTransferManager::Ep0RequestComplete")); 
+    }
+
+// setup the state machine for a state
+void DControlTransferManager::AddState(UsbShai::TControlStage aStage,TControlStageSm& aStageSm)
+    {
+    if( (aStage >= UsbShai::EControlTransferStageSetup) && (aStage < UsbShai::EControlTransferStageMax))
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID " AddState(), Stage: %s", DebugName[aStage]));
+        iState[aStage] = &aStageSm;
+        }
+    }
+        
+// *************** Code for SETUP state machines **************************************
+//
+DSetupStageSm::DSetupStageSm(DControlTransferManager& aTransferMgr):
+    TControlStageSm(aTransferMgr)
+    {
+    }
+
+// WE are waiting a SETUP packet
+TBool DSetupStageSm::RequestComplete(TInt aPktSize, TInt aError, UsbShai::TControlPacketType aPktType)
+    {
+    TBool ret = EFalse;
+    
+    __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID "DSetupStageSm::RequestComplete"));
+    
+    if(aPktType != UsbShai::EControlPacketTypeSetup)
+        {
+        // we just discard any non-setup packet
+        __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID "ALERT: DSetupStageSm - Non-Setup recieved"));
+        return ret;
+        }
+    
+    // change state to whatever returned from this call.
+    ChangeToStage(iTransferMgr.PktParser().NextStage());
+    
+    // We're going to complete User's read request, consume the previous
+    // read operation
+    ClearPendingRead();
+    
+    // Setup packet are always need to be processed
+    iTransferMgr.CtrTransferIf().ProcessSetupPacket(aPktSize,aError);
+    
+    return EFalse;
+    }
+
+TBool DSetupStageSm::IsRequstAllowed(TControlTransferRequest aRequest)
+    {
+    // Allow user to read, No other operation is allowed
+    TBool ret = (aRequest == TControlTransferRequestRead)?ETrue:EFalse;
+    
+    if( ! ret)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID "Warning: request %d was blocked at DSetupStageSm",aRequest));
+        }
+        
+    return ret;
+    }
+
+    
+// *************** Code for DATA IN state machines **************************************
+
+DDataInStageSm::DDataInStageSm(DControlTransferManager& aTransferMgr):
+    TControlStageSm(aTransferMgr)
+    {
+    }
+
+// We are waiting for a competion of DATA IN packet
+TBool DDataInStageSm::RequestComplete(TInt aPktSize, TInt aError, UsbShai::TControlPacketType aPktType)
+    {
+    TInt completionCode = aError;
+    TBool furtherRequest = EFalse;
+    
+    switch(aPktType)
+        {
+        case UsbShai::EControlPacketTypeSetup:
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID "ALERT: DDataInStageSm - Setup recieved"));
+            // Something goes wrong, host is abandoning the unfinished control transfer
+            completionCode = KErrGeneral;
+            
+            // Force SM restart at setup stage
+            ChangeToStage(UsbShai::EControlTransferStageSetup);
+            
+            // this packet is partially processed here
+            // need another SM to continue
+            furtherRequest = ETrue;
+            }
+            break;
+            
+        case UsbShai::EControlPacketTypeDataIn:
+            {
+            // PSL notifing us that the data had been sent to host
+            // next step is to wait for the status from Host
+            ChangeToStage(UsbShai::EControlTransferStageStatusOut);
+             
+            // In USB spec, a compete control transfer must inclue a status stage
+            // which is not case in reality,some PSL/Hardware will swallow the
+            // Status out report, so, we just complete client normally.
+            }
+            break;
+            
+        default:
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID "ALERT: DDataInStageSm -  %s recieved",DebugName[aPktType]));
+            
+            // Unexpected packet will be discard, and lead us reset state machine
+            // so that we can wait for next SETUP packet.
+            // Of course error will be report to any client if any there.
+            ChangeToStage(UsbShai::EControlTransferStageSetup);
+            completionCode = KErrGeneral;
+            }
+            break;
+        }
+    
+    iTransferMgr.CtrTransferIf().ProcessDataInPacket(aPktSize,completionCode);
+
+    return furtherRequest;
+    }
+
+TBool DDataInStageSm::IsRequstAllowed(TControlTransferRequest aRequest)
+    {
+    // Only write is possible because host is waiting for data from us
+    TBool ret = (aRequest == TControlTransferRequestWrite)?ETrue:EFalse;
+    
+    if( ! ret)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID "Warning: request %d was blocked at DDataInStageSm",aRequest));
+        }
+        
+    return ret;
+    };
+    
+// *************** Code for STATUS OUT state machines **************************************
+DStatusOutStageSm::DStatusOutStageSm(DControlTransferManager& aTransferMgr):
+    TControlStageSm(aTransferMgr)
+    {
+    }
+
+// We are waiting for a competion of STATUS OUT or a SETUP packet if PSL or hardware don't
+// complete a status in packet
+TBool DStatusOutStageSm::RequestComplete(TInt aPktSize, TInt aError, UsbShai::TControlPacketType aPktType)
+    {
+    TBool furtherRequest = EFalse;
+    TInt completionCode = aError;
+    
+    switch(aPktType)
+        {
+        case UsbShai::EControlPacketTypeSetup:
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID "ALERT: DStatusOutStageSm - Setup recieved"));
+            // hw or PSL may not send back the status packet for a DATA OUT
+            // and we're ok for this, just back to EControlTransferStageSetup stage           
+            
+            // Force SM restart at setup stage
+            ChangeToStage(UsbShai::EControlTransferStageSetup);
+            
+            // this packet is partially processed here
+            // need another SM to continue
+            furtherRequest = ETrue;
+            }
+            break;
+
+        case UsbShai::EControlPacketTypeStatusOut:
+            {
+            // Force SM restart at setup stage
+            ChangeToStage(UsbShai::EControlTransferStageSetup);
+            }
+            break;
+        
+        default:
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID "ALERT: DStatusOutStageSm -  %s recieved",DebugName[aPktType]));
+
+            // Unexpected packet will be discard, and lead us reset state machine
+            // so that we can wait for next SETUP packet.
+            // Of course error will be report to any client if any there.            
+            ChangeToStage(UsbShai::EControlTransferStageSetup);
+            completionCode = KErrGeneral;
+            }
+            break;
+        }
+
+    iTransferMgr.CtrTransferIf().ProcessStatusOutPacket(completionCode);
+        
+    return furtherRequest;
+    
+    }
+
+TBool DStatusOutStageSm::IsRequstAllowed(TControlTransferRequest aRequest)
+    {
+    // Read is ok since client don't care the status out stage.
+    // and this lead no hurt to anybody.
+    TBool ret = (aRequest == TControlTransferRequestRead)?ETrue:EFalse;
+    
+    if( ! ret)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID "Warning: request %d was blocked at DStatusOutStageSm",aRequest));
+        }
+        
+    return ret;
+    };
+
+// *************** Code for DATA OUT state machines **************************************
+//
+DDataOutStageSm::DDataOutStageSm(DControlTransferManager& aTransferMgr):
+    TControlStageSm(aTransferMgr)
+    {
+    }
+
+TBool DDataOutStageSm::RequestComplete(TInt aPktSize, TInt aError, UsbShai::TControlPacketType aPktType)
+    {
+    TBool furtherRequest = EFalse;
+    TInt completionCode = aError;
+    
+    switch(aPktType)
+        {
+        case UsbShai::EControlPacketTypeSetup:
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID "ALERT: DDataOutStageSm - Setup recieved"));
+            // Host is abandon the previous Transfer 
+            completionCode = KErrGeneral;
+            
+            // Force SM restart at setup stage
+            ChangeToStage(UsbShai::EControlTransferStageSetup);
+
+            // this packet is partially processed here
+            // need another SM to continue
+            furtherRequest = ETrue;
+            }
+            break;
+            
+        case UsbShai::EControlPacketTypeDataOut:
+            {
+            iTransferMgr.DataReceived(aPktSize);
+            
+            if(!iTransferMgr.IsMoreBytesNeeded())
+                {
+                // We had recieved enough bytes as indicated by the setup
+                // packet, Data stage is finished. enter STATUS IN state
+                ChangeToStage(UsbShai::EControlTransferStageStatusIn);       
+                }            
+            }
+            break;
+        
+        case UsbShai::EControlPacketTypeStatusIn:
+            {
+            // Status in had been sent to host
+            // return and waiting for new SETUP
+            ChangeToStage(UsbShai::EControlTransferStageSetup);
+            }
+            break;
+            
+        default:
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID "ALERT: DDataOutStageSm -  %s recieved",DebugName[aPktType]));
+            
+            // Unexpected packet will be discard, and lead us reset state machine
+            // so that we can wait for next SETUP packet.
+            // Of course error will be report to any client if any there.
+            ChangeToStage(UsbShai::EControlTransferStageSetup);
+            completionCode = KErrGeneral;
+            }
+            break;
+        }
+    
+    ClearPendingRead();
+    iTransferMgr.CtrTransferIf().ProcessDataOutPacket(aPktSize,completionCode);
+    
+    return furtherRequest;
+    }
+
+TBool DDataOutStageSm::IsRequstAllowed(TControlTransferRequest aRequest)
+    {
+    // only read operation is allowed in data out stage.
+    TBool ret = (aRequest == TControlTransferRequestRead)?ETrue:EFalse;
+    
+    if( ! ret)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID "Warning: request %d was blocked at DDataOutStageSm",aRequest));
+        }
+        
+    return ret;
+    };
+
+// *************** Code for DATA OUT state machines **************************************
+//
+DStatusInStageSm::DStatusInStageSm(DControlTransferManager& aTransferMgr):
+    TControlStageSm(aTransferMgr)
+    {
+    }
+
+TBool DStatusInStageSm::RequestComplete(TInt aPktSize, TInt aError, UsbShai::TControlPacketType aPktType)
+    {
+    TBool furtherRequest = EFalse;
+    TInt completionCode = KErrNone;
+    
+    switch(aPktType)
+        {
+        case UsbShai::EControlPacketTypeSetup:
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID "ALERT: DStatusInStageSm - Setup recieved"));
+            // Status in is an optional for PSL
+            // If we received a setup packet here, we assume the previous
+            // status in packet had been successfully sent to host.
+            
+            // Force SM restart at setup stage
+            ChangeToStage(UsbShai::EControlTransferStageSetup);
+            
+            // this packet is partially processed here
+            // need another SM to continue
+            furtherRequest = ETrue;
+            }
+            break;
+            
+        case UsbShai::EControlPacketTypeStatusIn:
+            {
+            // Status in had been recieved, monitor setup packet then.
+            ChangeToStage(UsbShai::EControlTransferStageSetup);
+            }
+            break;
+            
+        default:
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID "ALERT: DStatusInStageSm -  %s recieved",DebugName[aPktType]));
+
+            // Unexpected packet will be discard, and lead us reset state machine
+            // so that we can wait for next SETUP packet.
+            // Of course error will be report to any client if any there.
+            ChangeToStage(UsbShai::EControlTransferStageSetup);
+            completionCode = KErrGeneral;
+            }
+            break;
+        }
+    
+    iTransferMgr.CtrTransferIf().ProcessStatusInPacket(completionCode);
+    
+    return furtherRequest;
+    }
+
+TBool DStatusInStageSm::IsRequstAllowed(TControlTransferRequest aRequest)
+    {
+    // Read is ok even we are wait for the client to send a zero status packet
+    TBool ret = ((aRequest == TControlTransferRequestSendStatus) || 
+                (aRequest == TControlTransferRequestRead))?ETrue:EFalse;
+    
+    if( ! ret)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf(CTSM_ID "Warning: request %d was blocked at DStatusInStageSm",aRequest));
+        }
+        
+    return ret;
+    }
+    
+// End of file
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/pdd/pil/src/descriptors.cpp	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,2362 @@
+// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32/drivers/usbcc/descriptors.cpp
+// Platform independent layer (PIL) of the USB Device controller driver:
+// USB descriptor handling and management.
+// 
+//
+
+/**
+ @file descriptors.cpp
+ @internalTechnology
+*/
+
+#include <kernel/kern_priv.h>
+// #include <drivers/usbc.h>
+#include <usb/usbc.h>
+
+
+// Debug Support
+static const char KUsbPanicCat[] = "USB PIL";
+
+
+// --- TUsbcDescriptorBase
+
+TUsbcDescriptorBase::TUsbcDescriptorBase()
+    :
+#ifdef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST
+    iIndex(0),
+#endif
+    iBufPtr(NULL, 0)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorBase::TUsbcDescriptorBase()"));
+    }
+
+
+TUsbcDescriptorBase::~TUsbcDescriptorBase()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorBase::~TUsbcDescriptorBase()"));
+    }
+
+
+void TUsbcDescriptorBase::SetByte(TInt aPosition, TUint8 aValue)
+    {
+    iBufPtr[aPosition] = aValue;
+    }
+
+
+void TUsbcDescriptorBase::SetWord(TInt aPosition, TUint16 aValue)
+    {
+    *reinterpret_cast<TUint16*>(&iBufPtr[aPosition]) = SWAP_BYTES_16(aValue);
+    }
+
+
+TUint8 TUsbcDescriptorBase::Byte(TInt aPosition) const
+    {
+    return iBufPtr[aPosition];
+    }
+
+
+TUint16 TUsbcDescriptorBase::Word(TInt aPosition) const
+    {
+    return SWAP_BYTES_16(*reinterpret_cast<const TUint16*>(&iBufPtr[aPosition]));
+    }
+
+
+void TUsbcDescriptorBase::GetDescriptorData(TDes8& aBuffer) const
+    {
+    aBuffer = iBufPtr;
+    }
+
+
+TInt TUsbcDescriptorBase::GetDescriptorData(TUint8* aBuffer) const
+    {
+    memcpy(aBuffer, iBufPtr.Ptr(), Size());
+    return Size();
+    }
+
+
+TInt TUsbcDescriptorBase::GetDescriptorData(TUint8* aBuffer, TUint aMaxSize) const
+    {
+    if (aMaxSize < Size())
+        {
+        // No use to copy only half a descriptor
+        return 0;
+        }
+    return GetDescriptorData(aBuffer);
+    }
+
+
+const TDes8& TUsbcDescriptorBase::DescriptorData() const
+    {
+    return iBufPtr;
+    }
+
+
+TDes8& TUsbcDescriptorBase::DescriptorData()
+    {
+    return iBufPtr;
+    }
+
+
+TUint TUsbcDescriptorBase::Size() const
+    {
+    return iBufPtr.Size();
+    }
+
+
+TUint8 TUsbcDescriptorBase::Type() const
+    {
+    return iBufPtr[1];
+    }
+
+
+void TUsbcDescriptorBase::UpdateFs()
+    {
+    // virtual function can be overridden in derived classes.
+    return;
+    }
+
+
+void TUsbcDescriptorBase::UpdateHs()
+    {
+    // virtual function can be overridden in derived classes.
+    return;
+    }
+
+
+void TUsbcDescriptorBase::SetBufferPointer(const TDesC8& aDes)
+    {
+    iBufPtr.Set(const_cast<TUint8*>(aDes.Ptr()), aDes.Size(), aDes.Size());
+    }
+
+
+// --- TUsbcDeviceDescriptor
+
+TUsbcDeviceDescriptor::TUsbcDeviceDescriptor()
+    : iBuf()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDeviceDescriptor::TUsbcDeviceDescriptor()"));
+    }
+
+
+TUsbcDeviceDescriptor* TUsbcDeviceDescriptor::New(TUint8 aDeviceClass, TUint8 aDeviceSubClass,
+                                                  TUint8 aDeviceProtocol, TUint8 aMaxPacketSize0,
+                                                  TUint16 aVendorId, TUint16 aProductId,
+                                                  TUint16 aDeviceRelease, TUint8 aNumConfigurations)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDeviceDescriptor::New()"));
+    TUsbcDeviceDescriptor* self = new TUsbcDeviceDescriptor();
+    if (self)
+        {
+        if (self->Construct(aDeviceClass, aDeviceSubClass, aDeviceProtocol, aMaxPacketSize0, aVendorId,
+                            aProductId, aDeviceRelease, aNumConfigurations) != KErrNone)
+            {
+            delete self;
+            return NULL;
+            }
+        }
+    return self;
+    }
+
+
+TInt TUsbcDeviceDescriptor::Construct(TUint8 aDeviceClass, TUint8 aDeviceSubClass, TUint8 aDeviceProtocol,
+                                      TUint8 aMaxPacketSize0, TUint16 aVendorId, TUint16 aProductId,
+                                      TUint16 aDeviceRelease, TUint8 aNumConfigurations)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDeviceDescriptor::Construct()"));
+    iBuf.SetMax();
+    SetBufferPointer(iBuf);
+    iBuf[0] = iBuf.Size();                                    // bLength
+    iBuf[1] = KUsbDescType_Device;                            // bDescriptorType
+    SetWord(2, KUsbcUsbVersion);                            // bcdUSB
+    iBuf[4] = aDeviceClass;                                    // bDeviceClass
+    iBuf[5] = aDeviceSubClass;                                // bDeviceSubClass
+    iBuf[6] = aDeviceProtocol;                                // bDeviceProtocol
+    iBuf[7] = aMaxPacketSize0;                                // bMaxPacketSize0
+    SetWord(8, aVendorId);                                    // idVendor
+    SetWord(10, aProductId);                                // idProduct
+    SetWord(12, aDeviceRelease);                            // bcdDevice
+    iBuf[14] = 0;                                            // iManufacturer
+    iBuf[15] = 0;                                            // iProduct
+    iBuf[16] = 0;                                            // iSerialNumber
+    iBuf[17] = aNumConfigurations;                            // bNumConfigurations
+    iEp0Size_Fs = aMaxPacketSize0;
+    return KErrNone;
+    }
+
+
+void TUsbcDeviceDescriptor::UpdateFs()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDeviceDescriptor::UpdateFs()"));
+    SetByte(7, iEp0Size_Fs);                                // bMaxPacketSize0
+    }
+
+
+void TUsbcDeviceDescriptor::UpdateHs()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDeviceDescriptor::UpdateHs()"));
+    SetByte(7, 64);                                            // bMaxPacketSize0
+    }
+
+
+// --- TUsbcDeviceQualifierDescriptor
+
+TUsbcDeviceQualifierDescriptor::TUsbcDeviceQualifierDescriptor()
+    : iBuf()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDeviceDescriptor::TUsbcDeviceQualifierDescriptor()"));
+    }
+
+
+TUsbcDeviceQualifierDescriptor* TUsbcDeviceQualifierDescriptor::New(TUint8 aDeviceClass,
+                                                                    TUint8 aDeviceSubClass,
+                                                                    TUint8 aDeviceProtocol,
+                                                                    TUint8 aMaxPacketSize0,
+                                                                    TUint8 aNumConfigurations,
+                                                                    TUint8 aReserved)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDeviceQualifierDescriptor::New()"));
+    TUsbcDeviceQualifierDescriptor* self = new TUsbcDeviceQualifierDescriptor();
+    if (self)
+        {
+        if (self->Construct(aDeviceClass, aDeviceSubClass, aDeviceProtocol, aMaxPacketSize0,
+                            aNumConfigurations, aReserved) != KErrNone)
+            {
+            delete self;
+            return NULL;
+            }
+        }
+    return self;
+    }
+
+
+TInt TUsbcDeviceQualifierDescriptor::Construct(TUint8 aDeviceClass, TUint8 aDeviceSubClass,
+                                               TUint8 aDeviceProtocol, TUint8 aMaxPacketSize0,
+                                               TUint8 aNumConfigurations, TUint8 aReserved)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDeviceQualifierDescriptor::Construct()"));
+    iBuf.SetMax();
+    SetBufferPointer(iBuf);
+    iBuf[0] = iBuf.Size();                                    // bLength
+    iBuf[1] = KUsbDescType_DeviceQualifier;                    // bDescriptorType
+    SetWord(2, KUsbcUsbVersion);                            // bcdUSB
+    iBuf[4] = aDeviceClass;                                    // bDeviceClass
+    iBuf[5] = aDeviceSubClass;                                // bDeviceSubClass
+    iBuf[6] = aDeviceProtocol;                                // bDeviceProtocol
+    iBuf[7] = aMaxPacketSize0;                                // bMaxPacketSize0
+    iBuf[8] = aNumConfigurations;                            // bNumConfigurations
+    if (aReserved) aReserved = 0;
+    iBuf[9] = aReserved;                                    // Reserved for future use, must be zero
+    iEp0Size_Fs = aMaxPacketSize0;
+    return KErrNone;
+    }
+
+
+void TUsbcDeviceQualifierDescriptor::UpdateFs()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDeviceQualifierDescriptor::UpdateFs()"));
+    // Here we do exactly the opposite of what's done in the Device descriptor (as this one's
+    // documenting the 'other than the current speed').
+    SetByte(7, 64);                                            // bMaxPacketSize0
+    }
+
+
+void TUsbcDeviceQualifierDescriptor::UpdateHs()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDeviceQualifierDescriptor::UpdateHs()"));
+    // Here we do exactly the opposite of what's done in the Device descriptor (as this one's
+    // documenting the 'other than the current speed').
+    SetByte(7, iEp0Size_Fs);                                // bMaxPacketSize0
+    }
+
+
+// --- TUsbcConfigDescriptor
+
+TUsbcConfigDescriptor::TUsbcConfigDescriptor()
+    : iBuf()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcConfigDescriptor::TUsbcConfigDescriptor()"));
+    }
+
+
+TUsbcConfigDescriptor* TUsbcConfigDescriptor::New(TUint8 aConfigurationValue, TBool aSelfPowered,
+                                                  TBool aRemoteWakeup, TUint16 aMaxPower)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcConfigDescriptor::New()"));
+    TUsbcConfigDescriptor* self = new TUsbcConfigDescriptor();
+    if (self)
+        {
+        if (self->Construct(aConfigurationValue, aSelfPowered, aRemoteWakeup, aMaxPower) != KErrNone)
+            {
+            delete self;
+            return NULL;
+            }
+        }
+    return self;
+    }
+
+
+TInt TUsbcConfigDescriptor::Construct(TUint8 aConfigurationValue, TBool aSelfPowered,
+                                       TBool aRemoteWakeup, TUint16 aMaxPower)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcConfigDescriptor::Construct()"));
+    iBuf.SetMax();
+    SetBufferPointer(iBuf);
+    iBuf[0] = iBuf.Size();                                    // bLength
+    iBuf[1] = KUsbDescType_Config;                            // bDescriptorType
+    SetWord(2, KUsbDescSize_Config);                        // wTotalLength
+    iBuf[4] = 0;                                            // bNumInterfaces
+    iBuf[5] = aConfigurationValue;                            // bConfigurationValue
+    iBuf[6] = 0;                                            // iConfiguration
+    iBuf[7] = 0x80 |
+        (aSelfPowered ? KUsbDevAttr_SelfPowered : 0) |
+        (aRemoteWakeup ? KUsbDevAttr_RemoteWakeup : 0);        // bmAttributes (bit 7 always 1)
+    if (aMaxPower > 510)
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid value for bMaxPower: %d", aMaxPower));
+    iBuf[8] = aMaxPower / 2;                                // bMaxPower (2mA units!)
+    return KErrNone;
+    }
+
+
+// --- TUsbcInterfaceDescriptor
+
+TUsbcInterfaceDescriptor::TUsbcInterfaceDescriptor()
+    : iBuf()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcInterfaceDescriptor::TUsbcInterfaceDescriptor()"));
+    }
+
+
+TUsbcInterfaceDescriptor* TUsbcInterfaceDescriptor::New(TUint8 aInterfaceNumber, TUint8 aAlternateSetting,
+                                                        TInt aNumEndpoints, const TUsbcClassInfo& aClassInfo)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcInterfaceDescriptor::New()"));
+    TUsbcInterfaceDescriptor* self = new TUsbcInterfaceDescriptor();
+    if (self)
+        {
+        if (self->Construct(aInterfaceNumber, aAlternateSetting, aNumEndpoints, aClassInfo) != KErrNone)
+            {
+            delete self;
+            return NULL;
+            }
+        }
+    return self;
+    }
+
+
+TInt TUsbcInterfaceDescriptor::Construct(TUint8 aInterfaceNumber, TUint8 aAlternateSetting,
+                                         TInt aNumEndpoints, const TUsbcClassInfo& aClassInfo)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcInterfaceDescriptor::Construct()"));
+    iBuf.SetMax();
+    SetBufferPointer(iBuf);
+    iBuf[0] = iBuf.Size();                                    // bLength
+    iBuf[1] = KUsbDescType_Interface;                        // bDescriptorType
+    iBuf[2] = aInterfaceNumber;                                // bInterfaceNumber
+    iBuf[3] = aAlternateSetting;                            // bAlternateSetting
+    iBuf[4] = aNumEndpoints;                                // bNumEndpoints
+    iBuf[5] = aClassInfo.iClassNum;                            // bInterfaceClass
+    iBuf[6] = aClassInfo.iSubClassNum;                        // bInterfaceSubClass
+    iBuf[7] = aClassInfo.iProtocolNum;                        // bInterfaceProtocol
+    iBuf[8] = 0;                                            // iInterface
+    return KErrNone;
+    }
+
+
+// --- TUsbcEndpointDescriptorBase
+
+TUsbcEndpointDescriptorBase::TUsbcEndpointDescriptorBase()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpointDescriptorBase::TUsbcEndpointDescriptorBase()"));
+    }
+
+
+TInt TUsbcEndpointDescriptorBase::Construct(const TUsbcEndpointInfo& aEpInfo)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpointDescriptorBase::Construct()"));
+    //  Adjust FS/HS endpoint sizes
+    if (aEpInfo.AdjustEpSizes(iEpSize_Fs, iEpSize_Hs) != KErrNone)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Unknown endpoint type: %d", aEpInfo.iType));
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("  Now set: iEpSize_Fs=%d iEpSize_Hs=%d (aEpInfo.iSize=%d)",
+                                    iEpSize_Fs, iEpSize_Hs, aEpInfo.iSize));
+
+    //  Adjust HS endpoint size for additional transactions
+    if ((aEpInfo.iType == UsbShai::KUsbEpTypeIsochronous) || (aEpInfo.iType == UsbShai::KUsbEpTypeInterrupt))
+        {
+        if ((aEpInfo.iTransactions > 0) && (aEpInfo.iTransactions < 3))
+            {
+            // Bits 12..11 specify the number of additional transactions per microframe
+            iEpSize_Hs |= (aEpInfo.iTransactions << 12);
+            __KTRACE_OPT(KUSB, Kern::Printf("  Adjusted for add. transact.: iEpSize_Hs=0x%02x "
+                                            "(aEpInfo.iTransactions=%d)",
+                                            iEpSize_Hs, aEpInfo.iTransactions));
+            }
+        else if (aEpInfo.iTransactions != 0)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Invalid iTransactions value: %d (ignored)",
+                                              aEpInfo.iTransactions));
+            }
+        }
+
+    //  Adjust HS polling interval
+    TUsbcEndpointInfo info(aEpInfo);                        // create local writeable copy
+    if (info.AdjustPollInterval() != KErrNone)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Unknown ep type (%d) or invalid interval value (%d)",
+                                          info.iType, info.iInterval));
+        }
+    iInterval_Fs = info.iInterval;
+    iInterval_Hs = info.iInterval_Hs;
+    __KTRACE_OPT(KUSB, Kern::Printf("  Now set: iInterval_Fs=%d iInterval_Hs=%d",
+                                    iInterval_Fs, iInterval_Hs));
+    return KErrNone;
+    }
+
+
+void TUsbcEndpointDescriptorBase::UpdateFs()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpointDescriptorBase::UpdateFs()"));
+    // (TUsbcEndpointDescriptorBase's FS/HS endpoint sizes and interval values got
+    //  adjusted in its Construct() method.)
+    SetWord(4, iEpSize_Fs);                                    // wMaxPacketSize
+    SetByte(6, iInterval_Fs);                                // bInterval
+    }
+
+
+void TUsbcEndpointDescriptorBase::UpdateHs()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpointDescriptorBase::UpdateHs()"));
+    // (TUsbcEndpointDescriptorBase's FS/HS endpoint sizes and interval values get
+    //  adjusted in its Construct() method.)
+    SetWord(4, iEpSize_Hs);                                    // wMaxPacketSize
+    SetByte(6, iInterval_Hs);                                // bInterval
+    }
+
+
+// --- TUsbcEndpointDescriptor
+
+TUsbcEndpointDescriptor::TUsbcEndpointDescriptor()
+    : iBuf()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpointDescriptor::TUsbcEndpointDescriptor()"));
+    }
+
+
+TUsbcEndpointDescriptor* TUsbcEndpointDescriptor::New(TUint8 aEndpointAddress,
+                                                      const TUsbcEndpointInfo& aEpInfo)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpointDescriptor::New()"));
+    TUsbcEndpointDescriptor* self = new TUsbcEndpointDescriptor();
+    if (self)
+        {
+        if (self->Construct(aEndpointAddress, aEpInfo) != KErrNone)
+            {
+            delete self;
+            return NULL;
+            }
+        }
+    return self;
+    }
+
+
+TInt TUsbcEndpointDescriptor::Construct(TUint8 aEndpointAddress, const TUsbcEndpointInfo& aEpInfo)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpointDescriptor::Construct()"));
+    (void) TUsbcEndpointDescriptorBase::Construct(aEpInfo);    // Init Base class
+    iBuf.SetMax();
+    SetBufferPointer(iBuf);
+    iBuf[0] = iBuf.Size();                                    // bLength
+    iBuf[1] = KUsbDescType_Endpoint;                        // bDescriptorType
+    iBuf[2] = aEndpointAddress;                                // bEndpointAddress
+    iBuf[3] = EpTypeMask2Value(aEpInfo.iType);                // bmAttributes
+    SetWord(4, iEpSize_Fs);                                    // wMaxPacketSize (default is FS)
+    iBuf[6] = iInterval_Fs;                                    // bInterval (default is FS)
+    return KErrNone;
+    }
+
+
+// --- TUsbcAudioEndpointDescriptor
+
+TUsbcAudioEndpointDescriptor::TUsbcAudioEndpointDescriptor()
+    : iBuf()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcAudioEndpointDescriptor::TUsbcAudioEndpointDescriptor()"));
+    }
+
+
+TUsbcAudioEndpointDescriptor* TUsbcAudioEndpointDescriptor::New(TUint8 aEndpointAddress,
+                                                                const TUsbcEndpointInfo& aEpInfo)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcAudioEndpointDescriptor::New()"));
+    TUsbcAudioEndpointDescriptor* self = new TUsbcAudioEndpointDescriptor();
+    if (self)
+        {
+        if (self->Construct(aEndpointAddress, aEpInfo) != KErrNone)
+            {
+            delete self;
+            return NULL;
+            }
+        }
+    return self;
+    }
+
+
+TInt TUsbcAudioEndpointDescriptor::Construct(TUint8 aEndpointAddress, const TUsbcEndpointInfo& aEpInfo)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcAudioEndpointDescriptor::Construct()"));
+    (void) TUsbcEndpointDescriptorBase::Construct(aEpInfo);    // Init Base class
+    iBuf.SetMax();
+    SetBufferPointer(iBuf);
+    iBuf[0] = iBuf.Size();                                    // bLength
+    iBuf[1] = KUsbDescType_Endpoint;                        // bDescriptorType
+    iBuf[2] = aEndpointAddress;                                // bEndpointAddress
+    iBuf[3] = EpTypeMask2Value(aEpInfo.iType);                // bmAttributes
+    SetWord(4, iEpSize_Fs);                                    // wMaxPacketSize (default is FS)
+    iBuf[6] = iInterval_Fs;                                    // bInterval (default is FS)
+    iBuf[7] = 0;
+    iBuf[8] = 0;
+    return KErrNone;
+    }
+
+
+// --- TUsbcOtgDescriptor
+
+TUsbcOtgDescriptor* TUsbcOtgDescriptor::New(TBool aHnpSupport, TBool aSrpSupport)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcOtgDescriptor::New()"));
+    TUsbcOtgDescriptor* self = new TUsbcOtgDescriptor();
+    if (self && (self->Construct(aHnpSupport, aSrpSupport) != KErrNone))
+        {
+        delete self;
+        return NULL;
+        }
+    return self;
+    }
+
+
+TUsbcOtgDescriptor::TUsbcOtgDescriptor()
+    : iBuf()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcOtgDescriptor::TUsbcOtgDescriptor()"));
+    }
+
+
+TInt TUsbcOtgDescriptor::Construct(TBool aHnpSupport, TBool aSrpSupport)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcOtgDescriptor::Construct()"));
+    iBuf.SetMax();
+    SetBufferPointer(iBuf);
+    iBuf[0] = iBuf.Size();                                    // bLength
+    iBuf[1] = KUsbDescType_Otg;                                // bDescriptorType
+    iBuf[2] = (aHnpSupport ? KUsbOtgAttr_HnpSupp : 0) |
+        (aSrpSupport ? KUsbOtgAttr_SrpSupp : 0);            // bmAttributes
+    return KErrNone;
+    }
+
+
+// --- TUsbcClassSpecificDescriptor
+
+TUsbcClassSpecificDescriptor::TUsbcClassSpecificDescriptor()
+    : iBuf(NULL)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcClassSpecificDescriptor::TUsbcClassSpecificDescriptor()"));
+    }
+
+
+TUsbcClassSpecificDescriptor::~TUsbcClassSpecificDescriptor()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcClassSpecificDescriptor::~TUsbcClassSpecificDescriptor()"));
+    delete iBuf;
+    }
+
+
+TUsbcClassSpecificDescriptor* TUsbcClassSpecificDescriptor::New(TUint8 aType, TInt aSize)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcClassSpecificDescriptor::New()"));
+    TUsbcClassSpecificDescriptor* self = new TUsbcClassSpecificDescriptor();
+    if (self)
+        {
+        if (self->Construct(aType, aSize) != KErrNone)
+            {
+            delete self;
+            return NULL;
+            }
+        }
+    return self;
+    }
+
+
+TInt TUsbcClassSpecificDescriptor::Construct(TUint8 aType, TInt aSize)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcClassSpecificDescriptor::Construct()"));
+    iBuf = HBuf8::New(aSize);
+    if (!iBuf)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Allocation of CS desc buffer failed"));
+        return KErrNoMemory;
+        }
+    iBuf->SetMax();
+    SetBufferPointer(*iBuf);
+    SetByte(1, aType);                                        // bDescriptorType
+    return KErrNone;
+    }
+
+
+// --- TUsbcStringDescriptorBase
+
+TUsbcStringDescriptorBase::TUsbcStringDescriptorBase()
+    : /*iIndex(0),*/ iSBuf(0), iBufPtr(NULL, 0)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcStringDescriptorBase::TUsbcStringDescriptorBase()"));
+    }
+
+
+TUsbcStringDescriptorBase::~TUsbcStringDescriptorBase()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcStringDescriptorBase::~TUsbcStringDescriptorBase()"));
+    }
+
+
+TUint16 TUsbcStringDescriptorBase::Word(TInt aPosition) const
+    {
+    if (aPosition <= 1)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Word(%d) in string descriptor "
+                                          "(TUsbcStringDescriptorBase::Word)", aPosition));
+        return 0;
+        }
+    else
+        {
+        // since iBufPtr[0] is actually string descriptor byte index 2,
+        // we have to subtract 2 from the absolute position.
+        return SWAP_BYTES_16(*reinterpret_cast<const TUint16*>(&iBufPtr[aPosition - 2]));
+        }
+    }
+
+
+void TUsbcStringDescriptorBase::SetWord(TInt aPosition, TUint16 aValue)
+    {
+    if (aPosition <= 1)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: SetWord(%d) in string descriptor "
+                                          "(TUsbcStringDescriptorBase::SetWord)", aPosition));
+        return;
+        }
+    else
+        {
+        // since iBufPtr[0] is actually string descriptor byte index 2,
+        // we have to subtract 2 from the absolute position.
+        *reinterpret_cast<TUint16*>(&iBufPtr[aPosition - 2]) = SWAP_BYTES_16(aValue);
+        }
+    }
+
+
+TInt TUsbcStringDescriptorBase::GetDescriptorData(TUint8* aBuffer) const
+    {
+    aBuffer[0] = iSBuf[0];
+    aBuffer[1] = iSBuf[1];
+    memcpy(&aBuffer[2], iBufPtr.Ptr(), iBufPtr.Size());
+    return Size();
+    }
+
+
+TInt TUsbcStringDescriptorBase::GetDescriptorData(TUint8* aBuffer, TUint aMaxSize) const
+    {
+    if (aMaxSize < Size())
+        {
+        // No use to copy only half a string
+        return 0;
+        }
+    return GetDescriptorData(aBuffer);
+    }
+
+
+const TDes8& TUsbcStringDescriptorBase::StringData() const
+    {
+    return iBufPtr;
+    }
+
+
+TDes8& TUsbcStringDescriptorBase::StringData()
+    {
+    return iBufPtr;
+    }
+
+
+TUint TUsbcStringDescriptorBase::Size() const
+    {
+    return iSBuf[0];
+    }
+
+
+void TUsbcStringDescriptorBase::SetBufferPointer(const TDesC8& aDes)
+    {
+    iBufPtr.Set(const_cast<TUint8*>(aDes.Ptr()), aDes.Size(), aDes.Size());
+    }
+
+
+// --- TUsbcStringDescriptor
+
+TUsbcStringDescriptor::TUsbcStringDescriptor()
+    : iBuf(NULL)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcStringDescriptor::TUsbcStringDescriptor()"));
+    }
+
+
+TUsbcStringDescriptor::~TUsbcStringDescriptor()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcStringDescriptor::~TUsbcStringDescriptor()"));
+    delete iBuf;
+    }
+
+
+TUsbcStringDescriptor* TUsbcStringDescriptor::New(const TDesC8& aString)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcStringDescriptor::New"));
+    TUsbcStringDescriptor* self = new TUsbcStringDescriptor();
+    if (self)
+        {
+        if (self->Construct(aString) != KErrNone)
+            {
+            delete self;
+            return NULL;
+            }
+        }
+    return self;
+    }
+
+
+TInt TUsbcStringDescriptor::Construct(const TDesC8& aString)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcStringDescriptor::Construct"));
+    iBuf = HBuf8::New(aString.Size());                        // bytes, not UNICODE chars
+    if (!iBuf)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Allocation of string buffer failed"));
+        return KErrNoMemory;
+        }
+    iBuf->SetMax();
+    SetBufferPointer(*iBuf);
+    iBufPtr.Copy(aString);
+    iSBuf.SetMax();
+    iSBuf[0] = iBuf->Size() + 2;                            // Bytes
+    iSBuf[1] = KUsbDescType_String;
+    return KErrNone;
+    }
+
+
+// --- TUsbcLangIdDescriptor
+
+TUsbcLangIdDescriptor::TUsbcLangIdDescriptor()
+    : iBuf(NULL)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcLangIdDescriptor::TUsbcLangIdDescriptor()"));
+    }
+
+
+TUsbcLangIdDescriptor::~TUsbcLangIdDescriptor()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcLangIdDescriptor::~TUsbcLangIdDescriptor()"));
+    }
+
+
+TUsbcLangIdDescriptor* TUsbcLangIdDescriptor::New(TUint16 aLangId)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcLangIdDescriptor::New"));
+    TUsbcLangIdDescriptor* self = new TUsbcLangIdDescriptor();
+    if (self)
+        {
+        if (self->Construct(aLangId) != KErrNone)
+            {
+            delete self;
+            return NULL;
+            }
+        }
+    return self;
+    }
+
+
+TInt TUsbcLangIdDescriptor::Construct(TUint16 aLangId)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcLangIdDescriptor::Construct"));
+    iBuf.SetMax();
+    SetBufferPointer(iBuf);
+    iBufPtr[0] = LowByte(SWAP_BYTES_16(aLangId));            // Language ID value
+    iBufPtr[1] = HighByte(SWAP_BYTES_16(aLangId));
+    iSBuf.SetMax();
+    iSBuf[0] = iBuf.Size() + 2;                                // Bytes
+    iSBuf[1] = KUsbDescType_String;
+    return KErrNone;
+    }
+
+
+// --- TUsbcDescriptorPool
+
+TUsbcDescriptorPool::TUsbcDescriptorPool(TUint8* aEp0_TxBuf)
+//
+//    The constructor for this class.
+//
+    : iDescriptors(), iStrings(), iIfcIdx(0), iEp0_TxBuf(aEp0_TxBuf), iHighSpeed(EFalse)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::TUsbcDescriptorPool()"));
+    }
+
+
+TUsbcDescriptorPool::~TUsbcDescriptorPool()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::~TUsbcDescriptorPool()"));
+    // The destructor of each <class T> object is called before the objects themselves are destroyed.
+    __KTRACE_OPT(KUSB, Kern::Printf("  iDescriptors.Count(): %d", iDescriptors.Count()));
+    iDescriptors.ResetAndDestroy();
+    __KTRACE_OPT(KUSB, Kern::Printf("  iStrings.Count(): %d", iStrings.Count()));
+    iStrings.ResetAndDestroy();
+    }
+
+
+TInt TUsbcDescriptorPool::Init(TUsbcDeviceDescriptor* aDeviceDesc, TUsbcConfigDescriptor* aConfigDesc,
+                               TUsbcLangIdDescriptor* aLangId, TUsbcStringDescriptor* aManufacturer,
+                               TUsbcStringDescriptor* aProduct, TUsbcStringDescriptor* aSerialNum,
+                               TUsbcStringDescriptor* aConfig, TUsbcOtgDescriptor* aOtgDesc)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::Init()"));
+    if (!aDeviceDesc || !aConfigDesc)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: No Device or Config descriptor specified"));
+        return KErrArgument;
+        }
+    for (TInt n = 0; n < KDescPosition_FirstAvailable; n++)
+        {
+        iDescriptors.Append(NULL);
+        }
+    __ASSERT_DEBUG((iDescriptors.Count() == KDescPosition_FirstAvailable),
+                   Kern::Printf("  Error: iDescriptors.Count() (%d) != KDescPosition_FirstAvailable (%d)",
+                                iDescriptors.Count(), KDescPosition_FirstAvailable));
+    iDescriptors[KDescPosition_Device] = aDeviceDesc;
+    iDescriptors[KDescPosition_Config] = aConfigDesc;
+    if (aOtgDesc)
+        {
+        iDescriptors[KDescPosition_Otg] = aOtgDesc;
+        // Update the config descriptor's wTotalLength field
+        UpdateConfigDescriptorLength(KUsbDescSize_Otg);
+        }
+    if (!aLangId)
+        {
+        // USB spec 9.6.7 says: "String index zero for all languages returns a string descriptor
+        // that contains an array of two-byte LANGID codes supported by the device. ...
+        // USB devices that omit all string descriptors must not return an array of LANGID codes."
+        // So if we have at least one string descriptor, we must also have a LANGID descriptor.
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: No LANGID string descriptor specified"));
+        return KErrArgument;
+        }
+    iStrings.Insert(aLangId, KStringPosition_Langid);
+    iStrings.Insert(aManufacturer, KStringPosition_Manufact);
+    iStrings.Insert(aProduct, KStringPosition_Product);
+    iStrings.Insert(aSerialNum, KStringPosition_Serial);
+    iStrings.Insert(aConfig, KStringPosition_Config);
+    __ASSERT_DEBUG((iStrings.Count() == 5),
+                   Kern::Printf("  Error: iStrings.Count() != 5 (%d)", iStrings.Count()));
+#ifdef _DEBUG
+    for (TInt i = KStringPosition_Langid; i <= KStringPosition_Config; i++)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool.iStrings[%d] = 0x%x", i, iStrings[i]));
+        }
+#endif
+    // Set string indices
+    if (aManufacturer)
+        iDescriptors[KDescPosition_Device]->SetByte(KUsbDescStringIndex_Manufact,
+                                                    KStringPosition_Manufact);
+    if (aProduct)
+        iDescriptors[KDescPosition_Device]->SetByte(KUsbDescStringIndex_Product,
+                                                    KStringPosition_Product);
+    if (aSerialNum)
+        iDescriptors[KDescPosition_Device]->SetByte(KUsbDescStringIndex_Serial,
+                                                    KStringPosition_Serial);
+    if (aConfig)
+        iDescriptors[KDescPosition_Config]->SetByte(KUsbDescStringIndex_Config,
+                                                    KStringPosition_Config);
+    return KErrNone;
+    }
+
+
+TInt TUsbcDescriptorPool::InitHs()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::InitHs()"));
+    __ASSERT_DEBUG((iDescriptors.Count() >= KDescPosition_FirstAvailable),
+                   Kern::Printf("  Error: Call Init() first)"));
+
+    TUsbcDeviceQualifierDescriptor* const dq_desc = TUsbcDeviceQualifierDescriptor::New(
+        iDescriptors[KDescPosition_Device]->Byte(4),        // aDeviceClass
+        iDescriptors[KDescPosition_Device]->Byte(5),        // aDeviceSubClass
+        iDescriptors[KDescPosition_Device]->Byte(6),        // aDeviceProtocol
+        iDescriptors[KDescPosition_Device]->Byte(7),        // aMaxPacketSize0
+        iDescriptors[KDescPosition_Device]->Byte(17));        // aNumConfigurations
+    if (!dq_desc)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for dev qualif desc failed."));
+        return KErrGeneral;
+        }
+    iDescriptors[KDescPosition_DeviceQualifier] = dq_desc;
+
+    TUsbcOtherSpeedConfigDescriptor* const osc_desc = TUsbcOtherSpeedConfigDescriptor::New(
+        iDescriptors[KDescPosition_Config]->Byte(5),        // aConfigurationValue
+        iDescriptors[KDescPosition_Config]->Byte(7) & KUsbDevAttr_SelfPowered, // aSelfPowered
+        iDescriptors[KDescPosition_Config]->Byte(7) & KUsbDevAttr_RemoteWakeup,    // aRemoteWakeup
+        iDescriptors[KDescPosition_Config]->Byte(8) * 2);    // aMaxPower (mA)
+    if (!osc_desc)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for other speed conf desc failed."));
+        return KErrGeneral;
+        }
+
+    // We need to set the bDescriptorType field manually, as that's the only one
+    // that differs from a Configuration descriptor.
+    osc_desc->SetByte(1, KUsbDescType_OtherSpeedConfig);
+
+    // Also, initially we set the iConfiguration string index to the same value as
+    // in the Configuration descriptor.
+    osc_desc->SetByte(KUsbDescStringIndex_Config,
+                      iDescriptors[KDescPosition_Config]->Byte(KUsbDescStringIndex_Config));
+
+    iDescriptors[KDescPosition_OtherSpeedConfig] = osc_desc;
+
+    return KErrNone;
+    }
+
+
+TInt TUsbcDescriptorPool::UpdateDescriptorsFs()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::UpdateDescriptorsFs()"));
+    const TInt count = iDescriptors.Count();
+    for (TInt i = KDescPosition_FirstAvailable; i < count; i++)
+        {
+        TUsbcDescriptorBase* const ptr = iDescriptors[i];
+        ptr->UpdateFs();
+        }
+    iHighSpeed = EFalse;
+    return KErrNone;
+    }
+
+
+TInt TUsbcDescriptorPool::UpdateDescriptorsHs()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::UpdateDescriptorsHs()"));
+    const TInt count = iDescriptors.Count();
+    for (TInt i = KDescPosition_FirstAvailable; i < count; i++)
+        {
+        TUsbcDescriptorBase* const ptr = iDescriptors[i];
+        ptr->UpdateHs();
+        }
+    iHighSpeed = ETrue;
+    return KErrNone;
+    }
+
+
+//
+// An error can be indicated by either a return value != KErrNone or by a descriptor size == 0.
+//
+TInt TUsbcDescriptorPool::FindDescriptor(TUint8 aType, TUint8 aIndex, TUint16 aLangid, TInt& aSize) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::FindDescriptor()"));
+    TInt result = KErrGeneral;
+    switch (aType)
+        {
+    case KUsbDescType_Device:
+        if (aLangid != 0)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: bad langid: 0x%04x", aLangid));
+            }
+        else if (aIndex > 0)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: bad device index: %d", aIndex));
+            }
+        else
+            {
+            aSize = GetDeviceDescriptor(KDescPosition_Device);
+            result = KErrNone;
+            }
+        break;
+    case KUsbDescType_Config:
+        if (aLangid != 0)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: bad langid: 0x%04x", aLangid));
+            }
+        else if (aIndex > 0)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: bad config index: %d", aIndex));
+            }
+        else
+            {
+            aSize = GetConfigurationDescriptor(KDescPosition_Config);
+            result = KErrNone;
+            }
+        break;
+    case KUsbDescType_DeviceQualifier:
+        if (aLangid != 0)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: bad langid: 0x%04x", aLangid));
+            }
+        else if (aIndex > 0)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: bad device index: %d", aIndex));
+            }
+        else
+            {
+            aSize = GetDeviceDescriptor(KDescPosition_DeviceQualifier);
+            result = KErrNone;
+            }
+        break;
+    case KUsbDescType_OtherSpeedConfig:
+        if (aLangid != 0)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: bad langid: 0x%04x", aLangid));
+            }
+        else if (aIndex > 0)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: bad config index: %d", aIndex));
+            }
+        else
+            {
+            aSize = GetConfigurationDescriptor(KDescPosition_OtherSpeedConfig);
+            result = KErrNone;
+            }
+        break;
+    case KUsbDescType_Otg:
+        aSize = GetOtgDescriptor();
+        result = KErrNone;
+        break;
+    case KUsbDescType_String:
+        if (aIndex == 0)                                    // 0 addresses the LangId array
+            {
+            if (AnyStringDescriptors())
+                {
+                aSize = GetStringDescriptor(aIndex);
+                result = KErrNone;
+                }
+            else
+                {
+                __KTRACE_OPT(KUSB, Kern::Printf("  No string descriptors: not returning LANGID array"));
+                }
+            }
+        else
+            {
+               if (!aLangid)
+                   {
+                   __KTRACE_OPT(KUSB,
+                              Kern::Printf("  Strange: LANGID=0 for a $ descriptor (ignoring LANGID)"));
+                // The USB spec doesn't really say what to do in this case, but as there are host apps
+                // that fail if we return an error here, we choose to ignore the issue.
+                   }
+            else if (aLangid != iStrings[KStringPosition_Langid]->Word(2))
+                {
+                // We have only one (this) language
+                __KTRACE_OPT(KUSB,
+                             Kern::Printf("  Bad LANGID: 0x%04X requested, 0x%04X supported (ignoring LANGID)",
+                                          aLangid, iStrings[KStringPosition_Langid]->Word(2)));
+                // We could return an error here, but rather choose to ignore the discrepancy
+                // (the USB spec is not very clear what to do in such a case anyway).
+                }
+            aSize = GetStringDescriptor(aIndex);
+            result = KErrNone;
+            }
+        break;
+    case KUsbDescType_CS_Interface:
+        /* fall through */
+    case KUsbDescType_CS_Endpoint:
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: finding of class specific descriptors not supported"));
+        break;
+    default:
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: unknown descriptor type requested: %d", aType));
+        break;
+        }
+    return result;
+    }
+
+
+void TUsbcDescriptorPool::InsertDescriptor(TUsbcDescriptorBase* aDesc)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::InsertDescriptor()"));
+    switch (aDesc->Type())
+        {
+    case KUsbDescType_Interface:
+        InsertIfcDesc(aDesc);
+        break;
+    case KUsbDescType_Endpoint:
+        InsertEpDesc(aDesc);
+        break;
+    default:
+        __KTRACE_OPT(KUSB, Kern::Printf("  Error: unsupported descriptor type"));
+        }
+    }
+
+
+void TUsbcDescriptorPool::SetIfcStringDescriptor(TUsbcStringDescriptor* aDesc, TInt aNumber, TInt aSetting)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::SetIfcDescriptor(%d, %d)", aNumber, aSetting));
+    const TInt i = FindIfcDescriptor(aNumber, aSetting);
+    if (i < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Ifc descriptor not found (%d, %d)",
+                                          aNumber, aSetting));
+        return;
+        }
+    // Try to find available NULL postition
+    TInt str_idx = FindAvailableStringPos();
+    if (str_idx >= 0)
+        {
+        // Insert string descriptor for specified interface
+        ExchangeStringDescriptor(str_idx, aDesc);
+        }
+    else
+        {
+        // No NULL found - expand array
+        str_idx = iStrings.Count();
+        if (str_idx > 0xff)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: $ descriptor array full (idx=%d)", str_idx));
+            return;
+            }
+        while (str_idx < KStringPosition_FirstAvailable)
+            {
+            iStrings.Append(NULL);
+            str_idx = iStrings.Count();
+            }
+        // Append string descriptor for specified interface
+        iStrings.Append(aDesc);
+        }
+    // Update this ifc descriptor's string index field
+    iDescriptors[i]->SetByte(8, str_idx);
+    __KTRACE_OPT(KUSB, Kern::Printf("  String for ifc %d/%d (@ pos %d): \"%S\"", aNumber, aSetting, str_idx,
+                                    &iStrings[str_idx]->StringData()));
+    }
+
+
+void TUsbcDescriptorPool::DeleteIfcDescriptor(TInt aNumber, TInt aSetting)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::DeleteIfcDescriptor(%d, %d)", aNumber, aSetting));
+    const TInt i = FindIfcDescriptor(aNumber, aSetting);
+    if (i < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: DeleteIfcDescriptor - descriptor not found (%d, %d)",
+                                          aNumber, aSetting));
+        return;
+        }
+    // Delete (if necessary) specified interface's string descriptor
+    const TInt si = iDescriptors[i]->Byte(8);
+    if (si != 0)
+        {
+        ExchangeStringDescriptor(si, NULL);
+        }
+    // Delete specified ifc setting + all its cs descriptors + all its endpoints + all their cs descriptors:
+    // find position of the next interface descriptor: we need to delete everything in between
+    const TInt count = iDescriptors.Count();
+    TInt j = i, n = 1;
+    while (++j < count && iDescriptors[j]->Type() != KUsbDescType_Interface)
+        ++n;
+    DeleteDescriptors(i, n);
+    // Update all the following interfaces' bInterfaceNumber field if required
+    // (because those descriptors might have moved down by one position)
+    UpdateIfcNumbers(aNumber);
+    iIfcIdx = 0;                                            // ifc index no longer valid
+    }
+
+
+// The TC in many of the following functions stands for 'ThreadCopy',
+// because that's what's happening there.
+
+TInt TUsbcDescriptorPool::GetDeviceDescriptorTC(DThread* aThread, TDes8& aBuffer) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetDeviceDescriptorTC()"));
+    return Kern::ThreadDesWrite(aThread, &aBuffer, iDescriptors[KDescPosition_Device]->DescriptorData(), 0);
+    }
+
+
+TInt TUsbcDescriptorPool::SetDeviceDescriptorTC(DThread* aThread, const TDes8& aBuffer)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::SetDeviceDescriptorTC()"));
+    TBuf8<KUsbDescSize_Device> device;
+    const TInt r = Kern::ThreadDesRead(aThread, &aBuffer, device, 0);
+    if (r != KErrNone)
+        {
+        return r;
+        }
+    iDescriptors[KDescPosition_Device]->SetByte(2, device[2]); // bcdUSB
+    iDescriptors[KDescPosition_Device]->SetByte(3, device[3]); // bcdUSB (part II)
+    iDescriptors[KDescPosition_Device]->SetByte(4, device[4]); // bDeviceClass
+    iDescriptors[KDescPosition_Device]->SetByte(5, device[5]); // bDeviceSubClass
+    iDescriptors[KDescPosition_Device]->SetByte(6, device[6]); // bDeviceProtocol
+    iDescriptors[KDescPosition_Device]->SetByte(8, device[8]); // idVendor
+    iDescriptors[KDescPosition_Device]->SetByte(9, device[9]); // idVendor (part II)
+    iDescriptors[KDescPosition_Device]->SetByte(10, device[10]); // idProduct
+    iDescriptors[KDescPosition_Device]->SetByte(11, device[11]); // idProduct (part II)
+    iDescriptors[KDescPosition_Device]->SetByte(12, device[12]); // bcdDevice
+    iDescriptors[KDescPosition_Device]->SetByte(13, device[13]); // bcdDevice (part II)
+    return KErrNone;
+    }
+
+
+TInt TUsbcDescriptorPool::GetConfigurationDescriptorTC(DThread* aThread, TDes8& aBuffer) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetConfigurationDescriptorTC()"));
+    return Kern::ThreadDesWrite(aThread, &aBuffer, iDescriptors[KDescPosition_Config]->DescriptorData(), 0);
+    }
+
+
+TInt TUsbcDescriptorPool::SetConfigurationDescriptorTC(DThread* aThread, const TDes8& aBuffer)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::SetConfigurationDescriptorTC()"));
+    TBuf8<KUsbDescSize_Config> config;
+    const TInt r = Kern::ThreadDesRead(aThread, &aBuffer, config, 0);
+    if (r != KErrNone)
+        {
+        return r;
+        }
+    iDescriptors[KDescPosition_Config]->SetByte(7, config[7]); // bmAttributes
+    iDescriptors[KDescPosition_Config]->SetByte(8, config[8]); // bMaxPower
+    return KErrNone;
+    }
+
+
+TInt TUsbcDescriptorPool::GetOtgDescriptorTC(DThread* aThread, TDes8& aBuffer) const
+    {
+    return Kern::ThreadDesWrite(aThread, &aBuffer, iDescriptors[KDescPosition_Otg]->DescriptorData(), 0);
+    }
+
+
+TInt TUsbcDescriptorPool::SetOtgDescriptor(const TDesC8& aBuffer)
+    {
+    iDescriptors[KDescPosition_Otg]->SetByte(2, aBuffer[2]); // bmAttributes
+    return KErrNone;
+    }
+
+
+TInt TUsbcDescriptorPool::GetInterfaceDescriptorTC(DThread* aThread, TDes8& aBuffer,
+                                                   TInt aInterface, TInt aSetting) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetInterfaceDescriptorTC()"));
+    const TInt i = FindIfcDescriptor(aInterface, aSetting);
+    if (i < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such interface"));
+        return KErrNotFound;
+        }
+    return Kern::ThreadDesWrite(aThread, &aBuffer, iDescriptors[i]->DescriptorData(), 0);
+    }
+
+
+TInt TUsbcDescriptorPool::SetInterfaceDescriptor(const TDes8& aBuffer, TInt aInterface, TInt aSetting)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::SetInterfaceDescriptor()"));
+    const TInt i = FindIfcDescriptor(aInterface, aSetting);
+    if (i < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such interface"));
+        return KErrNotFound;
+        }
+    iDescriptors[i]->SetByte(2, aBuffer[2]);                // bInterfaceNumber
+    iDescriptors[i]->SetByte(5, aBuffer[5]);                // bInterfaceClass
+    iDescriptors[i]->SetByte(6, aBuffer[6]);                // bInterfaceSubClass
+    iDescriptors[i]->SetByte(7, aBuffer[7]);                // bInterfaceProtocol
+    return KErrNone;
+    }
+
+
+TInt TUsbcDescriptorPool::GetEndpointDescriptorTC(DThread* aThread, TDes8& aBuffer,
+                                                  TInt aInterface, TInt aSetting, TUint8 aEndpointAddress) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetEndpointDescriptorTC()"));
+    const TInt i = FindEpDescriptor(aInterface, aSetting, aEndpointAddress);
+    if (i < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such endpoint"));
+        return KErrNotFound;
+        }
+    return Kern::ThreadDesWrite(aThread, &aBuffer, iDescriptors[i]->DescriptorData(), 0);
+    }
+
+
+TInt TUsbcDescriptorPool::SetEndpointDescriptorTC(DThread* aThread, const TDes8& aBuffer,
+                                                  TInt aInterface, TInt aSetting, TUint8 aEndpointAddress)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::SetEndpointDescriptorTC()"));
+    const TInt i = FindEpDescriptor(aInterface, aSetting, aEndpointAddress);
+    if (i < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such endpoint"));
+        return KErrNotFound;
+        }
+    TBuf8<KUsbDescSize_AudioEndpoint> ep;                    // it could be an audio endpoint
+    const TInt r = Kern::ThreadDesRead(aThread, &aBuffer, ep, 0);
+    if (r != KErrNone)
+        {
+        return r;
+        }
+    iDescriptors[i]->SetByte(3, ep[3]);                        // bmAttributes
+    iDescriptors[i]->SetByte(6, ep[6]);                        // bInterval
+    if (iDescriptors[i]->Size() == KUsbDescSize_AudioEndpoint)
+        {
+        iDescriptors[i]->SetByte(7, ep[7]);                    // bRefresh
+        iDescriptors[i]->SetByte(8, ep[8]);                    // bSynchAddress
+        }
+    return KErrNone;
+    }
+
+
+TInt TUsbcDescriptorPool::GetEndpointDescriptorSize(TInt aInterface, TInt aSetting, TUint8 aEndpointAddress,
+                                                    TInt& aSize) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetEndpointDescriptorSize()"));
+    const TInt i = FindEpDescriptor(aInterface, aSetting, aEndpointAddress);
+    if (i < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such endpoint"));
+        return KErrNotFound;
+        }
+    aSize = iDescriptors[i]->Size();
+    return KErrNone;
+    }
+
+
+TInt TUsbcDescriptorPool::GetDeviceQualifierDescriptorTC(DThread* aThread, TDes8& aBuffer) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetDeviceQualifierDescriptorTC()"));
+    if (iDescriptors[KDescPosition_DeviceQualifier] == NULL)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Device_Qualifier descriptor not supported"));
+        return KErrNotSupported;
+        }
+    return Kern::ThreadDesWrite(aThread, &aBuffer,
+                                iDescriptors[KDescPosition_DeviceQualifier]->DescriptorData(), 0);
+    }
+
+
+TInt TUsbcDescriptorPool::SetDeviceQualifierDescriptorTC(DThread* aThread, const TDes8& aBuffer)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::SetDeviceQualifierDescriptorTC()"));
+    if (iDescriptors[KDescPosition_DeviceQualifier] == NULL)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Device_Qualifier descriptor not supported"));
+        return KErrNotSupported;
+        }
+    TBuf8<KUsbDescSize_DeviceQualifier> device;
+    const TInt r = Kern::ThreadDesRead(aThread, &aBuffer, device, 0);
+    if (r != KErrNone)
+        {
+        return r;
+        }
+    iDescriptors[KDescPosition_DeviceQualifier]->SetByte(2, device[2]); // bcdUSB
+    iDescriptors[KDescPosition_DeviceQualifier]->SetByte(3, device[3]); // bcdUSB (part II)
+    iDescriptors[KDescPosition_DeviceQualifier]->SetByte(4, device[4]); // bDeviceClass
+    iDescriptors[KDescPosition_DeviceQualifier]->SetByte(5, device[5]); // bDeviceSubClass
+    iDescriptors[KDescPosition_DeviceQualifier]->SetByte(6, device[6]); // bDeviceProtocol
+    return KErrNone;
+    }
+
+
+TInt TUsbcDescriptorPool::GetOtherSpeedConfigurationDescriptorTC(DThread* aThread, TDes8& aBuffer) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetOtherSpeedConfigurationDescriptorTC()"));
+    if (iDescriptors[KDescPosition_OtherSpeedConfig] == NULL)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Other_Speed_Configuration descriptor not supported"));
+        return KErrNotSupported;
+        }
+    return Kern::ThreadDesWrite(aThread, &aBuffer,
+                                iDescriptors[KDescPosition_OtherSpeedConfig]->DescriptorData(), 0);
+    }
+
+
+TInt TUsbcDescriptorPool::SetOtherSpeedConfigurationDescriptorTC(DThread* aThread, const TDes8& aBuffer)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::SetOtherSpeedConfigurationDescriptorTC()"));
+    if (iDescriptors[KDescPosition_OtherSpeedConfig] == NULL)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Other_Speed_Configuration descriptor not supported"));
+        return KErrNotSupported;
+        }
+    TBuf8<KUsbDescSize_OtherSpeedConfig> config;
+    const TInt r = Kern::ThreadDesRead(aThread, &aBuffer, config, 0);
+    if (r != KErrNone)
+        {
+        return r;
+        }
+    iDescriptors[KDescPosition_OtherSpeedConfig]->SetByte(7, config[7]); // bmAttributes
+    iDescriptors[KDescPosition_OtherSpeedConfig]->SetByte(8, config[8]); // bMaxPower
+    return KErrNone;
+    }
+
+
+TInt TUsbcDescriptorPool::GetCSInterfaceDescriptorTC(DThread* aThread, TDes8& aBuffer,
+                                                     TInt aInterface, TInt aSetting) const
+    {
+    // first find the interface
+    TInt i = FindIfcDescriptor(aInterface, aSetting);
+    if (i < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such interface"));
+        return KErrNotFound;
+        }
+    TInt r = KErrNotFound;
+    TInt offset = 0;
+    const TInt count = iDescriptors.Count();
+    while (++i < count && iDescriptors[i]->Type() == KUsbDescType_CS_Interface)
+        {
+        r = Kern::ThreadDesWrite(aThread, &aBuffer,
+                                 iDescriptors[i]->DescriptorData(), offset);
+        if (r != KErrNone)
+            break;
+        offset += iDescriptors[i]->Size();
+        }
+    return r;
+    }
+
+
+TInt TUsbcDescriptorPool::SetCSInterfaceDescriptorTC(DThread* aThread, const TDes8& aBuffer,
+                                                     TInt aInterface, TInt aSetting, TInt aSize)
+    {
+    // First find the interface
+    TInt i = FindIfcDescriptor(aInterface, aSetting);
+    if (i < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such interface"));
+        return KErrNotFound;
+        }
+    // Find a position where to insert the new class specific interface descriptor(s)
+    const TInt count = iDescriptors.Count();
+    while (++i < count && iDescriptors[i]->Type() == KUsbDescType_CS_Interface)
+        ;
+    // Create a new cs descriptor
+    TUsbcClassSpecificDescriptor* desc = TUsbcClassSpecificDescriptor::New(KUsbDescType_CS_Interface, aSize);
+    if (!desc)
+        {
+        return KErrNoMemory;
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("  inserting descriptor at position %d", i));
+    iDescriptors.Insert(desc, i);
+
+    // Update the config descriptor's wTotalLength field
+    UpdateConfigDescriptorLength(aSize);
+
+    // Copy contents from the user side
+    return Kern::ThreadDesRead(aThread, &aBuffer, iDescriptors[i]->DescriptorData(), 0);
+    }
+
+
+TInt TUsbcDescriptorPool::GetCSInterfaceDescriptorSize(TInt aInterface, TInt aSetting, TInt& aSize) const
+    {
+    // first find the interface
+    TInt i = FindIfcDescriptor(aInterface, aSetting);
+    if (i < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such interface"));
+        return KErrNotFound;
+        }
+    TInt r = KErrNotFound;
+    TInt size = 0;
+    const TInt count = iDescriptors.Count();
+    while (++i < count && iDescriptors[i]->Type() == KUsbDescType_CS_Interface)
+        {
+        size += iDescriptors[i]->Size();
+        r = KErrNone;
+        }
+    if (r == KErrNone)
+        aSize = size;
+    return r;
+    }
+
+
+TInt TUsbcDescriptorPool::GetCSEndpointDescriptorTC(DThread* aThread, TDes8& aBuffer, TInt aInterface,
+                                                    TInt aSetting, TUint8 aEndpointAddress) const
+    {
+    // first find the endpoint
+    TInt i = FindEpDescriptor(aInterface, aSetting, aEndpointAddress);
+    if (i < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such endpoint"));
+        return KErrNotFound;
+        }
+    TInt r = KErrNotFound;
+    TInt offset = 0;
+    const TInt count = iDescriptors.Count();
+    while (++i < count && iDescriptors[i]->Type() == KUsbDescType_CS_Endpoint)
+        {
+        r = Kern::ThreadDesWrite(aThread, &aBuffer,
+                                 iDescriptors[i]->DescriptorData(), offset);
+        if (r != KErrNone)
+            break;
+        offset += iDescriptors[i]->Size();
+        }
+    return r;
+    }
+
+
+TInt TUsbcDescriptorPool::SetCSEndpointDescriptorTC(DThread* aThread, const TDes8& aBuffer, TInt aInterface,
+                                                    TInt aSetting, TUint8 aEndpointAddress, TInt aSize)
+    {
+    // first find the endpoint
+    TInt i = FindEpDescriptor(aInterface, aSetting, aEndpointAddress);
+    if (i < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such endpoint"));
+        return KErrNotFound;
+        }
+    // find a position where to insert the new class specific endpoint descriptor(s)
+    const TInt count = iDescriptors.Count();
+    while (++i < count && iDescriptors[i]->Type() == KUsbDescType_CS_Endpoint)
+        ;
+    // create a new cs descriptor
+    TUsbcClassSpecificDescriptor* desc = TUsbcClassSpecificDescriptor::New(KUsbDescType_CS_Endpoint, aSize);
+    if (!desc)
+        {
+        return KErrNoMemory;
+        }
+    iDescriptors.Insert(desc, i);
+    // update the config descriptor's wTotalLength field
+    UpdateConfigDescriptorLength(aSize);
+    // copy contents from user side
+    return Kern::ThreadDesRead(aThread, &aBuffer, iDescriptors[i]->DescriptorData(), 0);
+    }
+
+
+TInt TUsbcDescriptorPool::GetCSEndpointDescriptorSize(TInt aInterface, TInt aSetting,
+                                                      TUint8 aEndpointAddress, TInt& aSize) const
+    {
+    // first find the endpoint
+    TInt i = FindEpDescriptor(aInterface, aSetting, aEndpointAddress);
+    if (i < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such endpoint"));
+        return KErrNotFound;
+        }
+    TInt r = KErrNotFound;
+    TInt size = 0;
+    const TInt count = iDescriptors.Count();
+    while (++i < count && iDescriptors[i]->Type() == KUsbDescType_CS_Endpoint)
+        {
+        size += iDescriptors[i]->Size();
+        r = KErrNone;
+        }
+    if (r == KErrNone)
+        aSize = size;
+    return r;
+    }
+
+
+TInt TUsbcDescriptorPool::GetStringDescriptorLangIdTC(DThread* aThread, TDes8& aLangId) const
+    {
+    const TUint16 id = iStrings[KStringPosition_Langid]->Word(2);
+    const TPtrC8 id_des(reinterpret_cast<const TUint8*>(&id), sizeof(id));
+    return Kern::ThreadDesWrite(aThread, &aLangId, id_des, 0);
+    }
+
+
+TInt TUsbcDescriptorPool::SetStringDescriptorLangId(TUint16 aLangId)
+    {
+    iStrings[KStringPosition_Langid]->SetWord(2, aLangId);
+    return KErrNone;
+    }
+
+
+TInt TUsbcDescriptorPool::GetManufacturerStringDescriptorTC(DThread* aThread, TDes8& aString) const
+    {
+    return GetDeviceStringDescriptorTC(aThread, aString, KUsbDescStringIndex_Manufact,
+                                       KStringPosition_Manufact);
+    }
+
+
+TInt TUsbcDescriptorPool::SetManufacturerStringDescriptorTC(DThread* aThread, const TDes8& aString)
+    {
+    return SetDeviceStringDescriptorTC(aThread, aString, KUsbDescStringIndex_Manufact,
+                                       KStringPosition_Manufact);
+    }
+
+
+TInt TUsbcDescriptorPool::RemoveManufacturerStringDescriptor()
+    {
+    return RemoveDeviceStringDescriptor(KUsbDescStringIndex_Manufact, KStringPosition_Manufact);
+    }
+
+
+TInt TUsbcDescriptorPool::GetProductStringDescriptorTC(DThread* aThread, TDes8& aString) const
+    {
+    return GetDeviceStringDescriptorTC(aThread, aString, KUsbDescStringIndex_Product,
+                                       KStringPosition_Product);
+    }
+
+
+TInt TUsbcDescriptorPool::SetProductStringDescriptorTC(DThread* aThread, const TDes8& aString)
+    {
+    return SetDeviceStringDescriptorTC(aThread, aString, KUsbDescStringIndex_Product,
+                                       KStringPosition_Product);
+    }
+
+
+TInt TUsbcDescriptorPool::RemoveProductStringDescriptor()
+    {
+    return RemoveDeviceStringDescriptor(KUsbDescStringIndex_Product, KStringPosition_Product);
+    }
+
+
+TInt TUsbcDescriptorPool::GetSerialNumberStringDescriptorTC(DThread* aThread, TDes8& aString) const
+    {
+    return GetDeviceStringDescriptorTC(aThread, aString, KUsbDescStringIndex_Serial,
+                                       KStringPosition_Serial);
+    }
+
+
+TInt TUsbcDescriptorPool::SetSerialNumberStringDescriptorTC(DThread* aThread, const TDes8& aString)
+    {
+    return SetDeviceStringDescriptorTC(aThread, aString, KUsbDescStringIndex_Serial,
+                                       KStringPosition_Serial);
+    }
+
+
+TInt TUsbcDescriptorPool::RemoveSerialNumberStringDescriptor()
+    {
+    return RemoveDeviceStringDescriptor(KUsbDescStringIndex_Serial, KStringPosition_Serial);
+    }
+
+
+TInt TUsbcDescriptorPool::GetConfigurationStringDescriptorTC(DThread* aThread, TDes8& aString) const
+    {
+    const TInt str_idx = iDescriptors[KDescPosition_Config]->Byte(KUsbDescStringIndex_Config);
+    if (str_idx)
+        {
+        __ASSERT_ALWAYS((str_idx == KStringPosition_Config), Kern::Fault(KUsbPanicCat, __LINE__));
+        __KTRACE_OPT(KUSB, Kern::Printf("  String @ pos %d (conf $): \"%S\"",
+                                        str_idx, &iStrings[str_idx]->StringData()));
+        return Kern::ThreadDesWrite(aThread, &aString,
+                                    iStrings[str_idx]->StringData(), 0);
+        }
+    else
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  No config string descriptor @ pos %d", str_idx));
+        return KErrNotFound;
+        }
+    }
+
+
+TInt TUsbcDescriptorPool::SetConfigurationStringDescriptorTC(DThread* aThread, const TDes8& aString)
+    {
+    // we don't know the length of the string, so we have to allocate memory dynamically
+    TUint strlen = Kern::ThreadGetDesLength(aThread, &aString);
+    if (strlen > KUsbStringDescStringMaxSize)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: config $ descriptor too long - will be truncated"));
+        strlen = KUsbStringDescStringMaxSize;
+        }
+    HBuf8* const strbuf = HBuf8::New(strlen);
+    if (!strbuf)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for config $ desc string failed (1)"));
+        return KErrNoMemory;
+        }
+    strbuf->SetMax();
+    // the aString points to data that lives in user memory, so we have to copy it:
+    const TInt r = Kern::ThreadDesRead(aThread, &aString, *strbuf, 0);
+    if (r != KErrNone)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Thread read error"));
+        delete strbuf;
+        return r;
+        }
+    TUsbcStringDescriptor* sd = TUsbcStringDescriptor::New(*strbuf);
+    if (!sd)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for config $ desc failed (2)"));
+        delete strbuf;
+        return KErrNoMemory;
+        }
+    // Delete old string, put in new one
+    ExchangeStringDescriptor(KStringPosition_Config, sd);
+    // Update Config descriptor string index field
+    iDescriptors[KDescPosition_Config]->SetByte(KUsbDescStringIndex_Config, KStringPosition_Config);
+    // Update Other_Speed_Config descriptor string index field as well, if applicable
+    if (iDescriptors[KDescPosition_OtherSpeedConfig])
+        iDescriptors[KDescPosition_OtherSpeedConfig]->SetByte(KUsbDescStringIndex_Config,
+                                                              KStringPosition_Config);
+    delete strbuf;
+    return KErrNone;
+    }
+
+
+TInt TUsbcDescriptorPool::RemoveConfigurationStringDescriptor()
+    {
+    if (iDescriptors[KDescPosition_Config]->Byte(KUsbDescStringIndex_Config) == 0)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  RemoveConfigurationStringDescriptor: no $ desc @ index %d",
+                                        KUsbDescStringIndex_Config));
+        return KErrNotFound;
+        }
+    // Delete old string, put in NULL pointer
+    ExchangeStringDescriptor(KStringPosition_Config, NULL);
+    // Update Config descriptor string index field
+    iDescriptors[KDescPosition_Config]->SetByte(KUsbDescStringIndex_Config, 0);
+    // Update Other_Speed_Config descriptor string index field as well, if applicable
+    if (iDescriptors[KDescPosition_OtherSpeedConfig])
+        iDescriptors[KDescPosition_OtherSpeedConfig]->SetByte(KUsbDescStringIndex_Config, 0);
+    return KErrNone;
+    }
+
+
+TInt TUsbcDescriptorPool::GetStringDescriptorTC(DThread* aThread, TInt aIndex, TDes8& aString) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetStringDescriptorTC()"));
+    if (!StringDescriptorExists(aIndex))
+        {
+        return KErrNotFound;
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("  String @ pos %d: \"%S\"",
+                                    aIndex, &iStrings[aIndex]->StringData()));
+    return Kern::ThreadDesWrite(aThread, &aString, iStrings[aIndex]->StringData(), 0);
+    }
+
+
+TInt TUsbcDescriptorPool::SetStringDescriptorTC(DThread* aThread, TInt aIndex, const TDes8& aString)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::SetStringDescriptorTC()"));
+    // we don't know the length of the string, so we have to allocate memory dynamically
+    TUint strlen = Kern::ThreadGetDesLength(aThread, &aString);
+    if (strlen > KUsbStringDescStringMaxSize)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: $ descriptor too long - will be truncated"));
+        strlen = KUsbStringDescStringMaxSize;
+        }
+    HBuf8* strbuf = HBuf8::New(strlen);
+    if (!strbuf)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Mem alloc for $ desc string failed (1)"));
+        return KErrNoMemory;
+        }
+    strbuf->SetMax();
+    // the aString points to data that lives in user memory, so we have to copy it over:
+    const TInt r = Kern::ThreadDesRead(aThread, &aString, *strbuf, 0);
+    if (r != KErrNone)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Thread read error"));
+        delete strbuf;
+        return r;
+        }
+    TUsbcStringDescriptor* const sd = TUsbcStringDescriptor::New(*strbuf);
+    if (!sd)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Mem alloc for $ desc failed (2)"));
+        delete strbuf;
+        return KErrNoMemory;
+        }
+    if (aIndex < iStrings.Count())
+        {
+        ExchangeStringDescriptor(aIndex, sd);
+        }
+    else // if (aIndex >= iStrings.Count())
+        {
+        while (aIndex > iStrings.Count())
+            {
+            iStrings.Append(NULL);
+            }
+        iStrings.Append(sd);
+        }
+    delete strbuf;
+    return KErrNone;
+    }
+
+
+TInt TUsbcDescriptorPool::RemoveStringDescriptor(TInt aIndex)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::RemoveStringDescriptor()"));
+    if (!StringDescriptorExists(aIndex))
+        {
+        return KErrNotFound;
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("  Removing string @ pos %d: \"%S\"",
+                                    aIndex, &iStrings[aIndex]->StringData()));
+    ExchangeStringDescriptor(aIndex, NULL);
+
+    // Make sure there's no $ after aIndex.
+    const TInt n = iStrings.Count();
+    for (TInt i = aIndex; i < n; i++)
+        {
+        if (iStrings[i] != NULL)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  Found $ @ idx %d - not compressing", i));
+            return KErrNone;
+            }
+        }
+
+    __KTRACE_OPT(KUSB, Kern::Printf("  No $ found after idx %d - compressing array", aIndex));
+    // Move aIndex back just before the first !NULL element.
+    while (iStrings[--aIndex] == NULL)
+        ;
+    // Let aIndex point to first NULL.
+    aIndex++;
+    __KTRACE_OPT(KUSB, Kern::Printf("  Starting at index %d", aIndex));
+    // Now remove NULL pointers until (Count() == aIndex).
+    __KTRACE_OPT(KUSB, Kern::Printf("  iStrings.Count() before: %d", iStrings.Count()));
+    do
+        {
+        iStrings.Remove(aIndex);
+        __KTRACE_OPT(KUSB, Kern::Printf("  Removing $"));
+        }
+    while (iStrings.Count() > aIndex);
+    __KTRACE_OPT(KUSB, Kern::Printf("  iStrings.Count() after: %d", iStrings.Count()));
+
+    // Regain some memory.
+    iStrings.Compress();
+
+    return KErrNone;
+    }
+
+
+// ===================================================================
+// --- private ---
+// ===================================================================
+
+//
+// Insert an Interface descriptor into the descriptor array at the appropriate index.
+//
+void TUsbcDescriptorPool::InsertIfcDesc(TUsbcDescriptorBase* aDesc)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::InsertIfcDesc()"));
+
+    const TInt count = iDescriptors.Count();
+    TBool ifc_exists = EFalse;                                // set to 'true' if we're adding an alternate
+                                                            // setting to an already existing interface
+    TInt i = KDescPosition_FirstAvailable;
+    while (i < count)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  already descriptors there (%d)...", count));
+        if (iDescriptors[i]->Type() == KUsbDescType_Interface)
+            {
+            if (iDescriptors[i]->Byte(2) > aDesc->Byte(2))
+                {
+                // our interface number is less than the one's just found => insert before it (= here)
+                break;
+                }
+            else if (iDescriptors[i]->Byte(2) == aDesc->Byte(2))
+                {
+                ifc_exists = ETrue;
+                // same interface number => look at settings number
+                if (iDescriptors[i]->Byte(3) > aDesc->Byte(3))
+                    {
+                    // our setting number is less than the one's found => insert before (= here)
+                    break;
+                    }
+                else if (iDescriptors[i]->Byte(3) == aDesc->Byte(3))
+                    {
+                    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: first delete old desc "
+                                                      "(TUsbcDescriptorPool::InsertIfcDesc)"));
+                    return;
+                    }
+                }
+            }
+        ++i;
+        }
+    // In any case: put the new descriptor at position i.
+    __KTRACE_OPT(KUSB, Kern::Printf("  inserting descriptor at position %d", i));
+    iDescriptors.Insert(aDesc, i);
+
+    // Update the config descriptor's wTotalLength field.
+    UpdateConfigDescriptorLength(KUsbDescSize_Interface);
+
+    if (!ifc_exists)
+        {
+        // If this is the first setting for the interface, increment bNumInterfaces.
+        UpdateConfigDescriptorNumIfcs(1);
+        }
+
+    iIfcIdx = i;
+    }
+
+
+//
+// Insert an Endpoint descriptor into the descriptor array at the appropriate index.
+//
+void TUsbcDescriptorPool::InsertEpDesc(TUsbcDescriptorBase* aDesc)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::InsertEpDesc()"));
+    if (iIfcIdx == 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: only after interface "
+                                          "(TUsbcDescriptorPool::InsertEpDesc)"));
+        return;
+        }
+    const TInt count = iDescriptors.Count();
+    TInt i = iIfcIdx + 1;
+    while (i < count)
+        {
+        if (iDescriptors[i]->Type() != KUsbDescType_Endpoint)
+            break;
+        ++i;
+        }
+    // put the new descriptor at position i
+    iDescriptors.Insert(aDesc, i);
+    // update the config descriptor's wTotalLength field
+    UpdateConfigDescriptorLength(aDesc->Size());
+    }
+
+
+//
+// Find the index of the Interface descriptor for a given interface setting.
+//
+TInt TUsbcDescriptorPool::FindIfcDescriptor(TInt aIfcNumber, TInt aIfcSetting) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::FindIfcDescriptor(%d, %d)",
+                                    aIfcNumber, aIfcSetting));
+    const TInt count = iDescriptors.Count();
+    for (TInt i = KDescPosition_FirstAvailable; i < count; i++)
+        {
+        if ((iDescriptors[i]->Type() == KUsbDescType_Interface) &&
+            (iDescriptors[i]->Byte(2) == aIfcNumber) &&
+            (iDescriptors[i]->Byte(3) == aIfcSetting))
+            {
+            return i;
+            }
+        }
+    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such interface"));
+    return -1;
+    }
+
+
+//
+// Find the index of the Endpoint descriptor for a given endpoint on a given interface setting.
+//
+TInt TUsbcDescriptorPool::FindEpDescriptor(TInt aIfcNumber, TInt aIfcSetting, TUint8 aEpAddress) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::FindEpDescriptor(%d, %d, 0x%02x)",
+                                    aIfcNumber, aIfcSetting, aEpAddress));
+    // first find the interface
+    const TInt ifc = FindIfcDescriptor(aIfcNumber, aIfcSetting);
+    if (ifc < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such interface"));
+        return ifc;
+        }
+    const TInt count = iDescriptors.Count();
+    // then, before the next interface, try to locate the endpoint
+    for (TInt i = ifc + 1; i < count; i++)
+        {
+        if (iDescriptors[i]->Type() == KUsbDescType_Interface)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such endpoint before next interface"));
+            return -1;
+            }
+        else if ((iDescriptors[i]->Type() == KUsbDescType_Endpoint) &&
+                 (iDescriptors[i]->Byte(2) == aEpAddress))
+            {
+            // found
+            return i;
+            }
+        }
+    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such endpoint"));
+    return -1;
+    }
+
+
+//
+// Delete n descriptors starting from aIndex and remove their pointers from the array.
+//
+void TUsbcDescriptorPool::DeleteDescriptors(TInt aIndex, TInt aCount)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::DeleteDescriptors()"));
+    if (aIndex < KDescPosition_FirstAvailable)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: aIndex < KDescPosition_FirstAvailable"));
+        return;
+        }
+    if (aCount <= 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: aCount <= 0"));
+        return;
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("  Removing descriptors at index %d:", aIndex));
+    // Try to update wTotalLength field in Config descriptor
+    while (aCount--)
+        {
+        // In this loop we don't decrement aIndex, because after deleting an element
+        // aIndex is already indexing the next one.
+        TUsbcDescriptorBase* const ptr = iDescriptors[aIndex];
+        switch (ptr->Type())
+            {
+        case KUsbDescType_Interface:
+            __KTRACE_OPT(KUSB, Kern::Printf("  - an interface descriptor"));
+            UpdateConfigDescriptorLength(-KUsbDescSize_Interface);
+            break;
+        case KUsbDescType_Endpoint:
+            __KTRACE_OPT(KUSB, Kern::Printf("  - an endpoint descriptor"));
+            UpdateConfigDescriptorLength(-ptr->Size());
+            break;
+        case KUsbDescType_CS_Interface:
+            /* fall through */
+        case KUsbDescType_CS_Endpoint:
+            __KTRACE_OPT(KUSB, Kern::Printf("  - a class specific descriptor"));
+            UpdateConfigDescriptorLength(-ptr->Size());
+            break;
+        default:
+            __KTRACE_OPT(KUSB, Kern::Printf("  - an unknown descriptor"));
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: unknown descriptor type"));
+            }
+        iDescriptors.Remove(aIndex);
+        delete ptr;
+        }
+    }
+
+
+//
+// Update the wTotalLength field in the Configuration descriptor (aLength can be negative).
+//
+void TUsbcDescriptorPool::UpdateConfigDescriptorLength(TInt aLength)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::UpdateConfigDescriptorLength(%d)", aLength));
+    TUsbcDescriptorBase* const cnf = iDescriptors[KDescPosition_Config];
+    __KTRACE_OPT(KUSB, Kern::Printf("  wTotalLength old: %d", cnf->Word(2)));
+    // Update Config descriptor
+    cnf->SetWord(2, cnf->Word(2) + aLength);
+    __KTRACE_OPT(KUSB, Kern::Printf("  wTotalLength new: %d", cnf->Word(2)));
+    // Update Other_Speed_Config descriptor as well, if applicable
+    if (iDescriptors[KDescPosition_OtherSpeedConfig])
+        iDescriptors[KDescPosition_OtherSpeedConfig]->SetWord(2, cnf->Word(2));
+    }
+
+
+//
+// Update the bNumInterfaces field in the Configuration descriptor (aNumber can be negative).
+//
+void TUsbcDescriptorPool::UpdateConfigDescriptorNumIfcs(TInt aNumber)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::UpdateConfigDescriptorNumIfcs(%d)", aNumber));
+    TUsbcDescriptorBase* const cnf = iDescriptors[KDescPosition_Config];
+    __KTRACE_OPT(KUSB, Kern::Printf("  bNumInterfaces old: %d", cnf->Byte(4)));
+    const TInt n = cnf->Byte(4) + aNumber;
+    if (n < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: bNumInterfaces + aNumber < 0"));
+        return;
+        }
+    // Update Config descriptor
+    cnf->SetByte(4, n);
+    __KTRACE_OPT(KUSB, Kern::Printf("  bNumInterfaces new: %d", cnf->Byte(4)));
+    // Update Other_Speed_Config descriptor as well, if applicable
+    if (iDescriptors[KDescPosition_OtherSpeedConfig])
+        iDescriptors[KDescPosition_OtherSpeedConfig]->SetByte(4, n);
+    }
+
+
+//
+// Update the bNumInterfaces field in the Configuration descriptor if necessary.
+//
+void TUsbcDescriptorPool::UpdateIfcNumbers(TInt aNumber)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::UpdateIfcNumbers(%d)", aNumber));
+    const TInt count = iDescriptors.Count();
+    for (TInt i = KDescPosition_FirstAvailable; i < count; i++)
+        {
+        if ((iDescriptors[i]->Type() == KUsbDescType_Interface) &&
+            (iDescriptors[i]->Byte(2) == aNumber))
+            {
+            // there's still an interface with 'number' so we don't need to update anything
+            return;
+            }
+        }
+    // if we haven't returned yet, we decrement bNumInterfaces
+    UpdateConfigDescriptorNumIfcs(-1);
+    }
+
+
+//
+// Put the current Device or Device_Qualifier descriptor in the Ep0 Tx buffer.
+// Only used for Ep0 standard requests, so target buffer can be hard-wired.
+//
+TInt TUsbcDescriptorPool::GetDeviceDescriptor(TInt aIndex) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetDeviceDescriptor()"));
+    __ASSERT_DEBUG((aIndex == KDescPosition_Device) || (aIndex == KDescPosition_DeviceQualifier),
+                   Kern::Printf("  Error: invalid descriptor index: %d", aIndex));
+    if (iDescriptors[aIndex] == NULL)
+        {
+        // This doesn't have to be an error - we might get asked here for the Device_Qualifier descriptor
+        // on a FS-only device.
+        __KTRACE_OPT(KUSB, Kern::Printf("  Descriptor #%d requested but not available", aIndex));
+        return 0;
+        }
+    return iDescriptors[aIndex]->GetDescriptorData(iEp0_TxBuf, KUsbcBufSz_Ep0Tx);
+    }
+
+
+//
+// Put the current Configuration or Other_Speed_Configuration descriptor + all the following
+// descriptors in the Ep0 Tx buffer.
+// Only used for Ep0 standard requests, so target buffer can be hard-wired.
+//
+TInt TUsbcDescriptorPool::GetConfigurationDescriptor(TInt aIndex) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetConfigDescriptor(%d)", aIndex));
+    __ASSERT_DEBUG((aIndex == KDescPosition_Config) || (aIndex == KDescPosition_OtherSpeedConfig),
+                   Kern::Printf("  Error: invalid descriptor index: %d", aIndex));
+    if (iDescriptors[aIndex] == NULL)
+        {
+        // This is always an error: We should always have a Configuration descriptor and we should never
+        // get asked for the Other_Speed_Configuration descriptor if we don't have one (9.6.2).
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Descriptor %d requested but not available", aIndex));
+        return 0;
+        }
+    const TInt count = iDescriptors.Count();
+    TInt copied = 0;
+    TUint8* buf = iEp0_TxBuf;
+    for (TInt i = aIndex; i < count; i++)
+        {
+        TUsbcDescriptorBase* const ptr = iDescriptors[i];
+        if ((aIndex == KDescPosition_OtherSpeedConfig) && (i == KDescPosition_Config))
+            {
+            // Skip Config descriptor when returning Other_Speed_Config
+            continue;
+            }
+        if ((i == KDescPosition_Otg) && (iDescriptors[i] == NULL))
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  no OTG descriptor -> next"));
+            continue;
+            }
+        // We need to edit endpoint descriptors on the fly because we have only one copy
+        // of each and that copy has to contain different information, depending on the
+        // current speed and the type of descriptor requested.
+        if (ptr->Type() == KUsbDescType_Endpoint)
+            {
+            if ((iHighSpeed && (aIndex == KDescPosition_Config)) ||
+                (!iHighSpeed && (aIndex == KDescPosition_OtherSpeedConfig)))
+                {
+                ptr->UpdateHs();
+                }
+            else
+                {
+                ptr->UpdateFs();
+                }
+            }
+        __KTRACE_OPT(KUSB, Kern::Printf("  desc[%02d]: type = 0x%02x size = %d ",
+                                        i, ptr->Type(), ptr->Size()));
+        const TInt size = ptr->GetDescriptorData(buf, KUsbcBufSz_Ep0Tx - copied);
+        if (size == 0)
+            {
+            __KTRACE_OPT(KPANIC,
+                         Kern::Printf("  Error: No Tx buffer space to copy this descriptor -> exiting"));
+            break;
+            }
+        copied += size;
+        if (copied >= KUsbcBufSz_Ep0Tx)
+            {
+            __KTRACE_OPT(KPANIC,
+                         Kern::Printf("  Error: No Tx buffer space left -> stopping here"));
+            break;
+            }
+        buf += size;
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("  copied %d bytes", copied));
+    return copied;
+    }
+
+
+//
+// Put the current OTG descriptor in the Ep0 Tx buffer.
+// Only used for Ep0 standard requests, so target buffer can be hard-wired.
+//
+TInt TUsbcDescriptorPool::GetOtgDescriptor() const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetOtgDescriptor()"));
+    if (iDescriptors[KDescPosition_Otg] == NULL)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  OTG Descriptor not set"));
+        return 0;
+        }
+    return iDescriptors[KDescPosition_Otg]->GetDescriptorData(iEp0_TxBuf, KUsbcBufSz_Ep0Tx);
+    }
+
+
+//
+// Put a specific String descriptor in the Ep0 Tx buffer.
+// Only used for Ep0 standard requests, so target buffer can be hard-wired.
+//
+TInt TUsbcDescriptorPool::GetStringDescriptor(TInt aIndex) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetStringDescriptor(%d)", aIndex));
+    // I really would have liked to display the descriptor contents here, but without trailing zero
+    // we got a problem: how can we tell printf where the string ends? We would have to
+    // dynamically allocate memory (since we don't know the size in advance), copy the descriptor
+    // contents there, append a zero, and give this to printf. That's a bit too much effort...
+    if (!StringDescriptorExists(aIndex))
+        {
+        return 0;
+        }
+    return iStrings[aIndex]->GetDescriptorData(iEp0_TxBuf, KUsbcBufSz_Ep0Tx);
+    }
+
+
+//
+// Write a String descriptor pointed to by the Device descriptor to the user side
+// (one of Manufacturer, Product, SerialNumber).
+//
+TInt TUsbcDescriptorPool::GetDeviceStringDescriptorTC(DThread* aThread, TDes8& aString,
+                                                      TInt aIndex, TInt aPosition) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetDeviceStringDescriptorTC()"));
+    const TInt str_idx = iDescriptors[KDescPosition_Device]->Byte(aIndex);
+    if (str_idx)
+        {
+        __ASSERT_ALWAYS((str_idx == aPosition), Kern::Fault(KUsbPanicCat, __LINE__));
+        __KTRACE_OPT(KUSB, Kern::Printf("  String @ pos %d (device $): \"%S\"",
+                                        str_idx, &iStrings[str_idx]->StringData()));
+        return Kern::ThreadDesWrite(aThread, &aString,
+                                    iStrings[str_idx]->StringData(), 0);
+        }
+    else
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  No string descriptor @ pos %d", aIndex));
+        return KErrNotFound;
+        }
+    }
+
+
+//
+// Read a Device String descriptor from the user side and put in the descriptor arrays
+// (one of Manufacturer, Product, SerialNumber).
+//
+TInt TUsbcDescriptorPool::SetDeviceStringDescriptorTC(DThread* aThread, const TDes8& aString,
+                                                      TInt aIndex, TInt aPosition)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::SetDeviceStringDescriptorTC()"));
+    // we don't know the length of the string, so we have to allocate memory dynamically
+    TUint strlen = Kern::ThreadGetDesLength(aThread, &aString);
+    if (strlen > KUsbStringDescStringMaxSize)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: $ descriptor too long - will be truncated"));
+        strlen = KUsbStringDescStringMaxSize;
+        }
+    HBuf8* const strbuf = HBuf8::New(strlen);
+    if (!strbuf)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for dev $ desc string failed (1)"));
+        return KErrNoMemory;
+        }
+    strbuf->SetMax();
+    // the aString points to data that lives in user memory, so we have to copy it:
+    const TInt r = Kern::ThreadDesRead(aThread, &aString, *strbuf, 0);
+    if (r != KErrNone)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Thread read error"));
+        delete strbuf;
+        return r;
+        }
+    TUsbcStringDescriptor* const sd = TUsbcStringDescriptor::New(*strbuf);
+    if (!sd)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for dev $ desc failed (2)"));
+        delete strbuf;
+        return KErrNoMemory;
+        }
+    ExchangeStringDescriptor(aPosition, sd);
+    iDescriptors[KDescPosition_Device]->SetByte(aIndex, aPosition);
+    delete strbuf;
+    return r;
+    }
+
+
+//
+// Remove a Device String descriptor from the descriptor arrays
+// (one of Manufacturer, Product, SerialNumber).
+//
+TInt TUsbcDescriptorPool::RemoveDeviceStringDescriptor(TInt aIndex, TInt aPosition)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::RemoveDeviceStringDescriptor()"));
+    if (iDescriptors[KDescPosition_Device]->Byte(aIndex) == 0)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  RemoveDeviceStringDescriptor: no $ desc @ index %d", aIndex));
+        return KErrNotFound;
+        }
+    ExchangeStringDescriptor(aPosition, NULL);
+    iDescriptors[KDescPosition_Device]->SetByte(aIndex, 0);
+    return KErrNone;
+    }
+
+
+//
+// Puts aDesc at postion aIndex in the string descriptor array, after deleting what was (possibly) there.
+//
+void TUsbcDescriptorPool::ExchangeStringDescriptor(TInt aIndex, const TUsbcStringDescriptor* aDesc)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::ExchangeStringDescriptor()"));
+    TUsbcStringDescriptorBase* const ptr = iStrings[aIndex];
+    __KTRACE_OPT(KUSB, Kern::Printf("  Deleting string descriptor at index %d: 0x%x", aIndex, ptr));
+    iStrings.Remove(aIndex);
+    delete ptr;
+    __KTRACE_OPT(KUSB, Kern::Printf("  Inserting string descriptor at index %d: 0x%x", aIndex, aDesc));
+    iStrings.Insert(aDesc, aIndex);
+    }
+
+
+//
+// Checks whether there are any string descriptors in the array (apart from LangID).
+//
+TBool TUsbcDescriptorPool::AnyStringDescriptors() const
+    {
+    const TInt n = iStrings.Count();
+    for (TInt i = 1; i < n; i++)
+        {
+        if (iStrings[i] != NULL)
+            return ETrue;
+        }
+    return EFalse;
+    }
+
+
+//
+// Returns true if aIndex exists and what is at that positition is not a NULL pointer.
+//
+TBool TUsbcDescriptorPool::StringDescriptorExists(TInt aIndex) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::StringDescriptorExists()"));
+    if (aIndex >= iStrings.Count())
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Bad string index: %d", aIndex));
+        return EFalse;
+        }
+    else if (iStrings[aIndex] == NULL)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: No $ descriptor @ pos %d", aIndex));
+        return EFalse;
+        }
+    return ETrue;
+    }
+
+
+//
+//
+//
+TInt TUsbcDescriptorPool::FindAvailableStringPos() const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::FindAvailableStringPos()"));
+    const TInt n = iStrings.Count();
+    // We don't start from 0 because the first few locations are 'reserved'.
+    for (TInt i = KStringPosition_FirstAvailable; i < n; i++)
+        {
+        if (iStrings[i] == NULL)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf(" Found available NULL position: %d", i));
+            return i;
+            }
+        }
+    return -1;
+    }
+
+
+// -eof-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/pdd/pil/src/misc.cpp	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,413 @@
+// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32/drivers/usbcc/misc.cpp
+// Platform independent layer (PIL) of the USB Device controller driver:
+// Implementations of misc. classes defined in usbc.h.
+// 
+//
+
+/**
+ @file misc.cpp
+ @internalTechnology
+*/
+// #include <drivers/usbc.h>
+#include <usb/usbc.h>
+
+
+/** Helper function for logical endpoints and endpoint descriptors:
+    Split single Ep size into separate FS/HS sizes.
+    This function modifies its arguments.
+ */
+TInt TUsbcEndpointInfo::AdjustEpSizes(TInt& aEpSize_Fs, TInt& aEpSize_Hs) const
+    {
+    if (iType == UsbShai::KUsbEpTypeBulk)
+        {
+        // FS: [8|16|32|64] HS: 512
+        if (iSize < 64)
+            {
+            aEpSize_Fs = iSize;
+            }
+        else
+            {
+            aEpSize_Fs = 64;
+            }
+        aEpSize_Hs = 512;
+        }
+    else if (iType == UsbShai::KUsbEpTypeInterrupt)
+        {
+        // FS: [0..64] HS: [0..1024]
+        if (iSize < 64)
+            {
+            aEpSize_Fs = iSize;
+            }
+        else
+            {
+            aEpSize_Fs = 64;
+            }
+        aEpSize_Hs = iSize;
+        }
+    else if (iType == UsbShai::KUsbEpTypeIsochronous)
+        {
+        // FS: [0..1023] HS: [0..1024]
+        if (iSize < 1023)
+            {
+            aEpSize_Fs = iSize;
+            }
+        else
+            {
+            aEpSize_Fs = 1023;
+            }
+        aEpSize_Hs = iSize;
+        }
+    else if (iType == UsbShai::KUsbEpTypeControl)
+        {
+        // FS: [8|16|32|64] HS: 64
+        if (iSize < 64)
+            {
+            aEpSize_Fs = iSize;
+            }
+        else
+            {
+            aEpSize_Fs = 64;
+            }
+        aEpSize_Hs = 64;
+        }
+    else
+        {
+        aEpSize_Fs = aEpSize_Hs = 0;
+        return KErrGeneral;
+        }
+
+    // For the reason of the following checks see Table 9-14. "Allowed wMaxPacketSize
+    // Values for Different Numbers of Transactions per Microframe".
+    if ((iType == UsbShai::KUsbEpTypeInterrupt) || (iType == UsbShai::KUsbEpTypeIsochronous))
+        {
+        if (iTransactions == 1)
+            {
+            if (aEpSize_Hs < 513)
+                {
+                __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Ep size too small: %d < 513. Correcting...",
+                                                  aEpSize_Hs));
+                aEpSize_Hs = 513;
+                }
+            }
+        else if (iTransactions == 2)
+            {
+            if (aEpSize_Hs < 683)
+                {
+                __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Ep size too small: %d < 683. Correcting...",
+                                                  aEpSize_Hs));
+                aEpSize_Hs = 683;
+                }
+            }
+        }
+    return KErrNone;
+    }
+
+
+/** Helper function for logical endpoints and endpoint descriptors:
+    If not set, assign a valid and meaningful value to iInterval_Hs, deriving from iInterval.
+    This function modifies the objects's data member(s).
+ */
+TInt TUsbcEndpointInfo::AdjustPollInterval()
+    {
+    if (iInterval_Hs != -1)
+        {
+        // Already done.
+        return KErrNone;
+        }
+    if ((iType == UsbShai::KUsbEpTypeBulk) || (iType == UsbShai::KUsbEpTypeControl))
+        {
+        // Valid range: 0..255 (maximum NAK rate).
+        // (The host controller will probably ignore this value though -
+        //  see the last sentence of section 9.6.6 for details.)
+        iInterval_Hs = 255;
+        }
+    else if (iType == UsbShai::KUsbEpTypeInterrupt)
+        {
+        // HS interval = 2^(iInterval_Hs-1) with a valid iInterval_Hs range of 1..16.
+        // The following table shows the mapping of HS values to actual intervals (and
+        // thus FS values) for the range of possible FS values (1..255).
+        // There is not always a 1:1 mapping possible, but we want at least to make sure
+        // that the HS polling interval is never longer than the FS one (except for 255).
+        //
+        // 1 = 1
+        // 2 = 2
+        // 3 = 4
+        // 4 = 8
+        // 5 = 16
+        // 6 = 32
+        // 7 = 64
+        // 8 = 128
+        // 9 = 256
+        if (iInterval == 255)
+            iInterval_Hs = 9;
+        else if (iInterval >= 128)
+            iInterval_Hs = 8;
+        else if (iInterval >= 64)
+            iInterval_Hs = 7;
+        else if (iInterval >= 32)
+            iInterval_Hs = 6;
+        else if (iInterval >= 16)
+            iInterval_Hs = 5;
+        else if (iInterval >= 8)
+            iInterval_Hs = 4;
+        else if (iInterval >= 4)
+            iInterval_Hs = 3;
+        else if (iInterval >= 2)
+            iInterval_Hs = 2;
+        else if (iInterval == 1)
+            iInterval_Hs = 1;
+        else
+            {
+            // iInterval wasn't set properly by the user
+            iInterval_Hs = 1;
+            return KErrGeneral;
+            }
+        }
+    else if (iType == UsbShai::KUsbEpTypeIsochronous)
+        {
+        // Interpretation is the same for FS and HS.
+        iInterval_Hs = iInterval;
+        }
+    else
+        {
+        // '1' is a valid value for all endpoint types...
+        iInterval_Hs = 1;
+        return KErrGeneral;
+        }
+    return KErrNone;
+    }
+
+
+TUsbcPhysicalEndpoint::TUsbcPhysicalEndpoint()
+    : iEndpointAddr(0), iIfcNumber(NULL), iLEndpoint(NULL), iSettingReserve(EFalse), iHalt(EFalse)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcPhysicalEndpoint::TUsbcPhysicalEndpoint"));
+    }
+
+
+TInt TUsbcPhysicalEndpoint::TypeAvailable(TUint aType) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcPhysicalEndpoint::TypeAvailable"));
+    switch (aType)
+        {
+    case UsbShai::KUsbEpTypeControl:
+        return (iCaps.iTypesAndDir & UsbShai::KUsbEpTypeControl);
+    case UsbShai::KUsbEpTypeIsochronous:
+        return (iCaps.iTypesAndDir & UsbShai::KUsbEpTypeIsochronous);
+    case UsbShai::KUsbEpTypeBulk:
+        return (iCaps.iTypesAndDir & UsbShai::KUsbEpTypeBulk);
+    case UsbShai::KUsbEpTypeInterrupt:
+        return (iCaps.iTypesAndDir & UsbShai::KUsbEpTypeInterrupt);
+    default:
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: invalid EP type: %d", aType));
+        return 0;
+        }
+    }
+
+
+TInt TUsbcPhysicalEndpoint::DirAvailable(TUint aDir) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcPhysicalEndpoint::DirAvailable"));
+    switch (aDir)
+        {
+    case UsbShai::KUsbEpDirIn:
+        return (iCaps.iTypesAndDir & UsbShai::KUsbEpDirIn);
+    case UsbShai::KUsbEpDirOut:
+        return (iCaps.iTypesAndDir & UsbShai::KUsbEpDirOut);
+    default:
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: invalid EP direction: %d", aDir));
+        return 0;
+        }
+    }
+
+
+TInt TUsbcPhysicalEndpoint::EndpointSuitable(const TUsbcEndpointInfo* aEpInfo, TInt aIfcNumber) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcPhysicalEndpoint::EndpointSuitable"));
+    __KTRACE_OPT(KUSB, Kern::Printf("  looking for EP: type=0x%x dir=0x%x size=%d (ifc_num=%d)",
+                                    aEpInfo->iType, aEpInfo->iDir, aEpInfo->iSize, aIfcNumber));
+    if (iSettingReserve)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  -> setting conflict"));
+        return 0;
+        }
+    // (aIfcNumber == -1) means the ep is for a new default interface setting
+    else if (iIfcNumber && (*iIfcNumber != aIfcNumber))
+        {
+        // If this endpoint has already been claimed (iIfcNumber != NULL),
+        // but by a different interface(-set) than the currently looking one
+        // (*iIfcNumber != aIfcNumber), then it's not available.
+        // This works because we can assign the same physical endpoint
+        // to different alternate settings of the *same* interface, and
+        // because we check for available endpoints for every alternate setting
+        // as a whole.
+        __KTRACE_OPT(KUSB, Kern::Printf("  -> ifc conflict"));
+        return 0;
+        }
+    else if (!TypeAvailable(aEpInfo->iType))
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  -> type conflict"));
+        return 0;
+        }
+    else if (!DirAvailable(aEpInfo->iDir))
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  -> direction conflict"));
+        return 0;
+        }
+    else if (!(iCaps.iSizes & PacketSize2Mask(aEpInfo->iSize)) && !(iCaps.iSizes & UsbShai::KUsbEpSizeCont))
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  -> size conflict"));
+        return 0;
+        }
+    else
+        return 1;
+    }
+
+
+TUsbcPhysicalEndpoint::~TUsbcPhysicalEndpoint()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcPhysicalEndpoint::~TUsbcPhysicalEndpoint()"));
+    iLEndpoint = NULL;
+    }
+
+
+TUsbcLogicalEndpoint::TUsbcLogicalEndpoint(DUsbClientController* aController, TUint aEndpointNum,
+                                           const TUsbcEndpointInfo& aEpInfo, TUsbcInterface* aInterface,
+                                           TUsbcPhysicalEndpoint* aPEndpoint)
+    : iController(aController), iLEndpointNum(aEndpointNum), iInfo(aEpInfo), iInterface(aInterface),
+      iPEndpoint(aPEndpoint)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcLogicalEndpoint::TUsbcLogicalEndpoint()"));
+    //  Adjust FS/HS endpoint sizes
+    if (iInfo.AdjustEpSizes(iEpSize_Fs, iEpSize_Hs) != KErrNone)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Unknown endpoint type: %d", iInfo.iType));
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("  Now set: iEpSize_Fs=%d iEpSize_Hs=%d (iInfo.iSize=%d)",
+                                    iEpSize_Fs, iEpSize_Hs, iInfo.iSize));
+    //  Adjust HS polling interval
+    if (iInfo.AdjustPollInterval() != KErrNone)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Unknown ep type (%d) or invalid interval value (%d)",
+                                          iInfo.iType, iInfo.iInterval));
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("  Now set: iInfo.iInterval=%d iInfo.iInterval_Hs=%d",
+                                    iInfo.iInterval, iInfo.iInterval_Hs));
+    // Additional transactions requested on a non High Bandwidth ep?
+    if ((iInfo.iTransactions > 0) && !aPEndpoint->iCaps.iHighBandwidth)
+        {
+        __KTRACE_OPT(KPANIC,
+                     Kern::Printf("  Warning: Additional transactions requested but not a High Bandwidth ep"));
+        }
+    }
+
+
+TUsbcLogicalEndpoint::~TUsbcLogicalEndpoint()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcLogicalEndpoint::~TUsbcLogicalEndpoint: #%d", iLEndpointNum));
+    // If the real endpoint this endpoint points to is also used by
+    // any other logical endpoint in any other setting of this interface
+    // then we leave the real endpoint marked as used. Otherwise we mark
+    // it as available (set its ifc number pointer to NULL).
+    const TInt n = iInterface->iInterfaceSet->iInterfaces.Count();
+    for (TInt i = 0; i < n; ++i)
+        {
+        const TUsbcInterface* const ifc = iInterface->iInterfaceSet->iInterfaces[i];
+        const TInt m = ifc->iEndpoints.Count();
+        for (TInt j = 0; j < m; ++j)
+            {
+            const TUsbcLogicalEndpoint* const ep = ifc->iEndpoints[j];
+            if ((ep->iPEndpoint == iPEndpoint) && (ep != this))
+                {
+                __KTRACE_OPT(KUSB, Kern::Printf("  Physical endpoint still in use -> we leave it as is"));
+                return;
+                }
+            }
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("  Closing DMA channel"));
+    const TInt idx = iController->EpAddr2Idx(iPEndpoint->iEndpointAddr);
+    // If the endpoint doesn't support DMA (now or ever) the next operation will be a no-op.
+    // iController->CloseDmaChannel(idx);
+    __KTRACE_OPT(KUSB, Kern::Printf("  Setting physical ep 0x%02x ifc number to NULL (was %d)",
+                                    iPEndpoint->iEndpointAddr, *iPEndpoint->iIfcNumber));
+    iPEndpoint->iIfcNumber = NULL;
+    }
+
+
+TUsbcInterface::TUsbcInterface(TUsbcInterfaceSet* aIfcSet, TUint8 aSetting, TBool aNoEp0Requests)
+    : iEndpoints(2), iInterfaceSet(aIfcSet), iSettingCode(aSetting), iNoEp0Requests(aNoEp0Requests)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcInterface::TUsbcInterface()"));
+    }
+
+
+TUsbcInterface::~TUsbcInterface()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcInterface::~TUsbcInterface()"));
+    iEndpoints.ResetAndDestroy();
+    }
+
+
+TUsbcInterfaceSet::TUsbcInterfaceSet(const DBase* aClientId, TUint8 aIfcNum)
+    : iInterfaces(2), iClientId(aClientId), iInterfaceNumber(aIfcNum), iCurrentInterface(0)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcInterfaceSet::TUsbcInterfaceSet()"));
+    }
+
+
+TUsbcInterfaceSet::~TUsbcInterfaceSet()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcInterfaceSet::~TUsbcInterfaceSet()"));
+    iInterfaces.ResetAndDestroy();
+    }
+
+
+TUsbcConfiguration::TUsbcConfiguration(TUint8 aConfigVal)
+    : iInterfaceSets(1), iConfigValue(aConfigVal)            // iInterfaceSets(1): granularity
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcConfiguration::TUsbcConfiguration()"));
+    }
+
+
+TUsbcConfiguration::~TUsbcConfiguration()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcConfiguration::~TUsbcConfiguration()"));
+    iInterfaceSets.ResetAndDestroy();
+    }
+
+
+_LIT(KDriverName, "Usbcc");
+
+DUsbcPowerHandler::DUsbcPowerHandler(DUsbClientController* aController)
+    : DPowerHandler(KDriverName), iController(aController)
+    {}
+
+
+void DUsbcPowerHandler::PowerUp()
+    {
+    if (iController)
+        iController->iPowerUpDfc.Enque();
+    }
+
+
+void DUsbcPowerHandler::PowerDown(TPowerState)
+    {
+    if (iController)
+        iController->iPowerDownDfc.Enque();
+    }
+
+
+// -eof-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/pdd/pil/src/ps_usbc.cpp	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,4832 @@
+// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32/drivers/usbcc/ps_usbc.cpp
+// Platform independent layer (PIL) of the USB Device controller driver (PDD).
+// Interface to the USB LDD.
+// 
+//
+
+/**
+ @file ps_usbc.cpp
+ @internalTechnology
+*/
+//#include <drivers/usbc.h>
+#include <usb/usbc.h>
+
+#include "controltransfersm.h"
+/**
+    TUsbcInterfaceSet and TUsbcInterface
+    ====================================
+
+    TUsbcInterfaceSet represents a 'USB Interface' and TUsbcInterface
+    represents an 'Alternate Setting of a USB Interface'.
+
+    Since every LDD governs exactly one interface, the above distinction is
+    made only within the USB implementation. At the LDD API, there is/are
+    simply one or more settings for this single interface, numbered from '0'
+    (the default) to 'n', and specified by the parameter 'TInt aInterfaceNum'.
+
+    Within the PDD implementation, for a TUsbcInterfaceSet number the parameter
+    'TInt aIfcSet' is used (local variable ifcset); for a TUsbcInterface number
+    the parameter 'TInt aIfc' is used (local variable ifc).
+
+
+    iConfigs[0] and CurrentConfig()
+    ===============================
+
+    One problem with this file is that it always uses iConfigs[0] and not
+    CurrentConfig(). This is mainly because the API to the LDD doesn't know
+    about the concept of multiple configurations, and thus always assumes one
+    single configuration (which is also always active: a further problem).
+
+    In the file chapter9.cpp this issue doesn't exist, since there we always
+    have to obey the USB protocol, and in this way will use the configuration
+    which is selected by the host (which will then again currently always be
+    iConfigs[0].)
+
+    iEp0ClientId
+    ==================================
+
+    The purpose of these two members of class DUsbClientController is the
+    following.
+
+    They are used only during Ep0 control transactions which have an OUT (Rx)
+    data stage. We cannot deduce from the received data itself to whom
+    it is addressed (that's because of the shared nature of Ep0).
+
+    In order to be able to tell whether received Ep0 data is to be processed by
+    the PIL or a LDD, we use iEp0ClientId. iEp0ClientId is usually NULL, which
+    means it is our data. However it is set to the client ID of an LDD in case
+    2) above. That way we can subsequently hand over received data to the
+    correct client LDD.
+
+    iEp0DataReceived tracks the amount of data already received - it is used to
+    determine the end of the DATA_OUT phase, irrespective of the owner of the
+    data. The total amount that is to be received can be obtained via
+    iConTransferMgr->PktParser().Length(). (iConTransferMgr->PktParser() holds in 
+    that case the Setup packet of the current Control transfer.)
+
+    iEp0ClientDataTransmitting is only set to TRUE if a client sets up an Ep0
+    write. After that transmission has completed we use this value to decide
+    whether we have to report the completion to a client or not. (If this
+    variable is FALSE, we did set up the write and thus no client notification
+    is necessary.)
+
+*/
+
+//
+// === Global and Local Variables ==================================================================
+//
+
+// Currently we support at most 2 peripheral stack
+GLDEF_D DUsbClientController* DUsbClientController::UsbClientController[] = {NULL, NULL};
+
+static const TInt KUsbReconnectDelay   = 500;                // milliseconds
+
+// Charger detector is the guy(PSL) who can detect the charger type and report 
+// it via a charger type observer
+static UsbShai::MChargerDetectorIf* gChargerDetector = NULL;
+
+// Charger observer is the guy who want to monitor the chager type event.
+static UsbShai::MChargerDetectorObserverIf* gChargerObsever = NULL;
+
+
+// Those const variables are used to construct the default 
+// Usb descriptors, Upper layer can change them later.
+/** Default vendor ID to set in device descriptor */
+static const TUint16 KUsbVendorId   = KUsbVendorId_Symbian;
+/** Default product ID to set in device descriptor */
+static const TUint16 KUsbProductId  = 0x1111;
+/** Default language ID (US English) to set in device descriptor */
+static const TUint16 KUsbLangId     = 0x0409;
+static const TUint8 KUsbNumberOfConfiguration = 0x01;
+/** Default manufacturer string */
+static const wchar_t KStringManufacturer[] = L"Nokia Corporation";
+/** Default product name string */
+static const wchar_t KStringProduct[]      = L"Nokia USB Driver";
+/** Default configuration name string */
+static const wchar_t KStringConfig[]       = L"Bulk transfer method configuration";
+/** Default configuration name string */
+static const wchar_t KStringSerial[]       = L"Serial Not defined";
+
+
+//
+// === USB Controller member function implementations - LDD API (public) ===========================
+//
+
+DECLARE_STANDARD_EXTENSION()//lint !e1717 !e960 defined by symbian
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> Peripheral PIL Extension entry"));
+    // Don't need to do anything here, using extension just to make sure
+    // we're loaded when peripheral PSL trying to register itself to us.
+    __KTRACE_OPT(KUSB, Kern::Printf("< Peripheral PIL Extension exit"));
+    return KErrNone;
+    }
+    
+/** The class destructor.
+
+    This rarely gets called, except, for example when something goes
+    wrong during construction.
+
+    It's not exported because it is virtual.
+*/
+DUsbClientController::~DUsbClientController()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::~DUsbClientController()"));
+    if (iPowerHandler)
+        {
+        iPowerHandler->Remove();
+        delete iPowerHandler;
+        }
+
+    // ResetAndDestroy() will call for every array element the destructor of the pointed-to object,
+    // before deleting the element itself, and closing the array.
+    iConfigs.ResetAndDestroy();
+    __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::~DUsbClientController(): Done."));
+    }
+
+EXPORT_C DUsbClientController* DUsbClientController::Create(UsbShai::MPeripheralControllerIf&               aPeripheralControllerIf, 
+                                                            const UsbShai::TPeripheralControllerProperties& aProperties,
+                                                            TBool                                  aIsOtgPort)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::Create"));
+        // Attempt to create the object
+    DUsbClientController* usbcc = new DUsbClientController(aPeripheralControllerIf, 
+                                                           aProperties,
+                                                           aIsOtgPort);
+    
+    __ASSERT_DEBUG( (usbcc != NULL), Kern::Fault( "  USB PSL Out of memory, DUsbClientController", __LINE__ ) );
+    
+    if (usbcc != NULL)
+        {
+        // Second phase constructor
+        TInt err = usbcc->Construct();
+        __ASSERT_DEBUG( (err == KErrNone), Kern::Fault( "DUsbClientController::Construct failed", err) );
+        
+        if (err != KErrNone)
+            {
+            delete usbcc;
+            usbcc = NULL;
+            }
+        }
+    
+    __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::Create instance = %d",usbcc));
+    
+    return usbcc;
+    }
+
+/**
+ * FIXME: This function used to be called by the dummy DCD to disable
+ * the peripheral stack. It has been deprecated and we currently use
+ * DisablePeripheralStack() to achieve the same effect.
+ */
+EXPORT_C void DUsbClientController::DisableClientStack()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("CALL TO OBSOLETE FUNCTION: DUsbClientController::DisableClientStack()"));
+    }
+
+
+/**
+ * FIXME: This function used to be called by the dummy DCD to enable
+ * the peripheral stack. It has been deprecated and we currently use
+ * EnablePeripheralStack() to achieve the same effect.
+ */
+EXPORT_C void DUsbClientController::EnableClientStack()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("CALL TO OBSOLETE FUNCTION: DUsbClientController::EnableClientStack()"));
+    }
+
+
+/** Called by LDD to see if controller is usable.
+
+    @return ETrue if controller is in normal state, EFalse if it is disabled.
+*/
+EXPORT_C TBool DUsbClientController::IsActive()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::IsActive = %d",iStackIsActive));
+    return iStackIsActive;
+    }
+
+
+/** Called by LDD to register client callbacks.
+
+    @return KErrNone if successful, KErrAlreadyExists callback exists.
+*/
+EXPORT_C TInt DUsbClientController::RegisterClientCallback(TUsbcClientCallback& aCallback)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::RegisterClientCallback()"));
+    if (iClientCallbacks.Elements() == KUsbcMaxListLength)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Maximum list length reached: %d",
+                                          KUsbcMaxListLength));
+        return KErrGeneral;
+        }
+    TSglQueIter<TUsbcClientCallback> iter(iClientCallbacks);
+    TUsbcClientCallback* p;
+    while ((p = iter++) != NULL)
+        if (p == &aCallback)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("     Error: ClientCallback @ 0x%x already registered", &aCallback));
+            return KErrAlreadyExists;
+            }
+    iClientCallbacks.AddLast(aCallback);
+    __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::RegisterClientCallback()"));
+    return KErrNone;
+    }
+
+
+/** Returns a pointer to the USB client controller object.
+
+    This function is static.
+
+    @param aUdc The number of the UDC (0..n) for which the pointer is to be returned.
+
+    @return A pointer to the USB client controller object.
+*/
+EXPORT_C DUsbClientController* DUsbClientController::UsbcControllerPointer(TInt aUdc)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::UsbcControllerPointer()"));
+    
+    if (aUdc < 0 || aUdc > 1)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: aUdc out of range (%d)", aUdc));
+        return NULL;
+        }
+        
+    __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::UsbcControllerPointer()"));
+    
+    return UsbClientController[aUdc];
+    }
+
+
+/** Fills the buffer passed in as an argument with endpoint capability information.
+
+     @see DUsbClientController::DeviceCaps()
+    @see TUsbcEndpointData
+    @see TUsbDeviceCaps
+
+    @param aClientId A pointer to the LDD making the enquiry.
+    @param aCapsBuf A reference to a descriptor buffer, which, on return, contains an array of
+    TUsbcEndpointData elements; there are TUsbDeviceCaps::iTotalEndpoints elements in the array;
+    call DeviceCaps() to get the number of elements required.
+*/
+EXPORT_C void DUsbClientController::EndpointCaps(const DBase* aClientId, TDes8& aCapsBuf) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::EndpointCaps()"));
+    // Here we do not simply call DUsbClientController::DeviceEndpointCaps(),
+    // because that function fills an array which comprises of _all_ endpoints,
+    // whereas this function omits ep0 and all unusable endpoints.
+    // Apart from that, we have to fill an array of TUsbcEndpointData, not TUsbcEndpointCaps.
+    TUsbcEndpointData data[KUsbcMaxEndpoints];
+    const TInt ifcset_num = ClientId2InterfaceNumber(aClientId);
+    for (TInt i = 2, j = 0; i < iDeviceTotalEndpoints; ++i)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  DUsbClientController::Caps: RealEndpoint #%d", i));
+        if (iRealEndpoints[i].iCaps.iTypesAndDir != UsbShai::KUsbEpNotAvailable)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  DUsbClientController::Caps: --> UsableEndpoint #%d", j));
+
+            data[j].iCaps.iSizes = iRealEndpoints[i].iCaps.iSizes;
+            data[j].iCaps.iTypesAndDir = iRealEndpoints[i].iCaps.iTypesAndDir;
+            data[j].iCaps.iHighBandwidth = iRealEndpoints[i].iCaps.iHighBandwidth;
+            data[j].iCaps.iReserved[0] = iRealEndpoints[i].iCaps.iReserved[0];
+            data[j].iCaps.iReserved[1] = iRealEndpoints[i].iCaps.iReserved[1];
+            
+            if (ifcset_num < 0)
+                {
+                // If this LDD doesn't own an interface, but the Ep points to one,
+                // then that must be the interface of a different LDD. Hence the Ep
+                // is not available for this LDD.
+                data[j].iInUse = (iRealEndpoints[i].iIfcNumber != NULL);
+                }
+            else
+                {
+                // If this LDD does already own an interface, and the Ep also points to one,
+                // then the Ep is not available for this LDD only if that interface is owned
+                // by a different LDD (i.e. if the interface number is different).
+                // Reason: Even though the endpoint might already be part of an interface setting,
+                // it is still available for a different alternate setting of the same interface.
+                data[j].iInUse = ((iRealEndpoints[i].iIfcNumber != NULL) &&
+                                  (*(iRealEndpoints[i].iIfcNumber) != ifcset_num));
+                }
+
+            j++;
+            }
+        }
+    // aCapsBuf resides in userland
+    TPtrC8 des((TUint8*)data, sizeof(data));
+    const TInt r = Kern::ThreadDesWrite((reinterpret_cast<const DLddUsbcChannel*>(aClientId))->Client(),
+                                        &aCapsBuf, des, 0, KChunkShiftBy0, NULL);
+    if (r != KErrNone)
+        {
+        Kern::ThreadKill((reinterpret_cast<const DLddUsbcChannel*>(aClientId))->Client(),
+                         EExitPanic, r, KUsbPILKillCat);
+        }
+        
+    __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::EndpointCaps()"));
+    }
+
+
+/** Fills the buffer passed in as an argument with device capability information.
+
+    @see TUsbDeviceCaps
+    @see TUsbDeviceCapsV01
+
+    @param aClientId A pointer to the LDD making the enquiry.
+    @param aCapsBuf A reference to a descriptor buffer which, on return, contains
+    a TUsbDeviceCaps structure.
+*/
+EXPORT_C void DUsbClientController::DeviceCaps(const DBase* aClientId, TDes8& aCapsBuf) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::DeviceCaps()"));
+    TUsbDeviceCaps caps;
+    caps().iTotalEndpoints = iDeviceUsableEndpoints;        // not DeviceTotalEndpoints()!
+    
+    caps().iSelfPowered = iSelfPowered;
+    caps().iRemoteWakeup = iRemoteWakeup;
+    caps().iHighSpeed = (iControllerProperties.iControllerCaps & UsbShai::KDevCapHighSpeed)?ETrue:EFalse;
+    
+    // PIL always assume controller support this caps, see explaination in peripheral shai header
+    caps().iFeatureWord1 = caps().iFeatureWord1 | KUsbDevCapsFeatureWord1_CableDetectWithoutPower;
+    
+    caps().iFeatureWord1 = caps().iFeatureWord1 | KUsbDevCapsFeatureWord1_EndpointResourceAllocV2;
+    caps().iReserved = 0;
+
+    // aCapsBuf resides in userland
+    const TInt r = Kern::ThreadDesWrite((reinterpret_cast<const DLddUsbcChannel*>(aClientId))->Client(),
+                                        &aCapsBuf, caps, 0, KChunkShiftBy0, NULL);
+    if (r != KErrNone)
+        {
+        Kern::ThreadKill((reinterpret_cast<const DLddUsbcChannel*>(aClientId))->Client(),
+                         EExitPanic, r, KUsbPILKillCat);
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::DeviceCaps()"));
+    }
+
+
+TUsbcEndpointInfoArray::TUsbcEndpointInfoArray(const TUsbcEndpointInfo* aData, TInt aDataSize)
+    {
+    iType = EUsbcEndpointInfo;
+    iData = (TUint8*) aData;
+    if (aDataSize > 0)
+        iDataSize = aDataSize;
+    else
+        iDataSize = sizeof(TUsbcEndpointInfo);
+    }
+
+
+inline TUsbcEndpointInfo& TUsbcEndpointInfoArray::operator[](TInt aIndex) const
+    {
+    return *(TUsbcEndpointInfo*) &iData[aIndex * iDataSize];
+    }
+
+
+EXPORT_C TInt DUsbClientController::SetInterface(const DBase* aClientId, DThread* aThread,
+                                                 TInt aInterfaceNum, TUsbcClassInfo& aClass,
+                                                 TDesC8* aString, TInt aTotalEndpointsUsed,
+                                                 const TUsbcEndpointInfo aEndpointData[],
+                                                 TInt (*aRealEpNumbers)[6], TUint32 aFeatureWord)
+    {
+    TUsbcEndpointInfoArray endpointData = TUsbcEndpointInfoArray(aEndpointData);
+    return SetInterface(aClientId, aThread, aInterfaceNum, aClass, aString, aTotalEndpointsUsed,
+                        endpointData, (TInt*) aRealEpNumbers, aFeatureWord);
+    }
+
+
+/** Creates a new USB interface (one setting), complete with endpoints, descriptors, etc.,
+    and chains it into the internal device configuration tree.
+
+    @param aClientId A pointer to the LDD owning the new interface.
+    @param aThread A pointer to the thread the owning LDD is running in.
+    @param aInterfaceNum The interface setting number of the new interface setting. This must be 0
+    if it is the first setting of the interface that gets created, or 1 more than the last setting
+    that was created for this interface.
+    @param aClass Contains information about the device class this interface might belong to.
+    @param aString A pointer to a string that is used for the string descriptor of this interface.
+    @param aTotalEndpointsUsed The number of endpoints used by this interface (and also the number of
+    elements of the following array).
+    @param aEndpointData An array with aTotalEndpointsUsed elements, containing information about the
+    endpoints of this interface.
+
+    @return KErrNotSupported if Control endpoints are requested by the LDD but aren't supported by the PIL,
+    KErrInUse if at least one requested endpoint is - temporarily or permanently - not available for use,
+    KErrNoMemory if (endpoint, interface, string) descriptor allocation fails, KErrGeneral if something else
+    goes wrong during endpoint or interface or descriptor creation, KErrNone if interface successfully set up.
+*/
+EXPORT_C TInt DUsbClientController::SetInterface(const DBase* aClientId, DThread* aThread,
+                                                 TInt aInterfaceNum, TUsbcClassInfo& aClass,
+                                                 TDesC8* aString, TInt aTotalEndpointsUsed,
+                                                 const TUsbcEndpointInfoArray aEndpointData,
+                                                 TInt aRealEpNumbers[], TUint32 aFeatureWord)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::SetInterface()"));
+    if (aInterfaceNum != 0)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  alternate interface setting request: #%d", aInterfaceNum));
+        }
+
+#ifndef USB_SUPPORTS_CONTROLENDPOINTS
+    for (TInt i = 0; i < aTotalEndpointsUsed; ++i)
+        {
+        if (aEndpointData[i].iType == UsbShai::KUsbEpTypeControl)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: control endpoints not supported"));
+            return KErrNotSupported;
+            }
+        }
+#endif
+
+    // Check for endpoint availability & check those endpoint's capabilities
+    const TInt ifcset_num = ClientId2InterfaceNumber(aClientId);
+    
+    // The passed-in ifcset_num may be -1 now, but that's intended.
+    if (!CheckEpAvailability(aTotalEndpointsUsed, aEndpointData, ifcset_num))
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: endpoints not (all) available"));
+        return KErrInUse;
+        }
+    
+    // Create & setup new interface
+    TUsbcInterface* ifc = CreateInterface(aClientId, aInterfaceNum, aFeatureWord);
+    if (ifc == NULL)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: ifc == NULL"));
+        return KErrGeneral;
+        }
+    
+    // Create logical endpoints
+    TInt r = CreateEndpoints(ifc, aTotalEndpointsUsed, aEndpointData, aRealEpNumbers);
+    if (r != KErrNone)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: CreateEndpoints() err = %d ",r));
+        DeleteInterface(ifc->iInterfaceSet->iInterfaceNumber, aInterfaceNum);
+        return r;
+        }
+    
+    // Create & setup interface, string, and endpoint descriptors
+    r = SetupIfcDescriptor(ifc, aClass, aThread, aString, aEndpointData);
+    if (r != KErrNone)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: SetupIfcDescriptor() err = %d",r));
+        return r;
+        }
+    
+    __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::SetInterface()"));
+    return KErrNone;
+    }
+
+
+/** Releases an existing USB interface (one setting), complete with endpoints, descriptors, etc.,
+    and removes it from the internal device configuration tree.
+
+    @param aClientId A pointer to the LDD owning the interface.
+    @param aInterfaceNum The setting number of the interface setting to be deleted. This must be
+    the highest numbered (or 'last') setting for this interface.
+
+    @return KErrNotFound if interface (not setting) for some reason cannot be found, KErrArgument if an
+    invalid interface setting number is specified (not existing or existing but too small), KErrNone if
+    interface successfully released or if this client doesn't own any interface.
+*/
+EXPORT_C TInt DUsbClientController::ReleaseInterface(const DBase* aClientId, TInt aInterfaceNum)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::ReleaseInterface(..., %d)", aInterfaceNum));
+    const TInt ifcset = ClientId2InterfaceNumber(aClientId);
+    if (ifcset < 0)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  interface not found")); // no error
+        return KErrNone;
+        }
+    TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(ifcset);
+    if (!ifcset_ptr)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Error: interface number %d doesn't exist", ifcset));
+        return KErrNotFound;
+        }
+    const TInt setting_count = ifcset_ptr->iInterfaces.Count();
+    if ((setting_count - 1) != aInterfaceNum)
+        {
+        __KTRACE_OPT(KUSB,
+                     Kern::Printf("  Error: interface settings must be released in descending order:\n\r"
+                                  "   %d setting(s) exist, #%d was requested to be released.\n\r"
+                                  "   (#%d has to be released first)",
+                                  setting_count, aInterfaceNum, setting_count - 1));
+        return KErrArgument;
+        }
+    // Tear down current setting (invalidate configured state)
+    __KTRACE_OPT(KUSB, Kern::Printf("  tearing down InterfaceSet %d", ifcset));
+    // Cancel all transfers on the current setting of this interface and deconfigure all its endpoints.
+    InterfaceSetTeardown(ifcset_ptr);
+    // 'Setting 0' means: delete all existing settings.
+    if (aInterfaceNum == 0)
+        {
+        TInt m = ifcset_ptr->iInterfaces.Count();
+        while (m > 0)
+            {
+            m--;
+            // Ground the physical endpoints' logical_endpoint_pointers
+            const TInt n = ifcset_ptr->iInterfaces[m]->iEndpoints.Count();
+            for (TInt i = 0; i < n; ++i)
+                {
+                TUsbcPhysicalEndpoint* ptr = const_cast<TUsbcPhysicalEndpoint*>
+                    (ifcset_ptr->iInterfaces[m]->iEndpoints[i]->iPEndpoint);
+                ptr->iLEndpoint = NULL;
+                }
+            // Delete the setting itself + its ifc & ep descriptors
+            DeleteInterface(ifcset, m);
+            iDescriptors.DeleteIfcDescriptor(ifcset, m);
+            }
+        }
+    else
+        {
+        // Ground the physical endpoints' logical_endpoint_pointers
+        const TInt n = ifcset_ptr->iInterfaces[aInterfaceNum]->iEndpoints.Count();
+        for (TInt i = 0; i < n; ++i)
+            {
+            TUsbcPhysicalEndpoint* ptr = const_cast<TUsbcPhysicalEndpoint*>
+                (ifcset_ptr->iInterfaces[aInterfaceNum]->iEndpoints[i]->iPEndpoint);
+            ptr->iLEndpoint = NULL;
+            }
+        // Delete the setting itself + its ifc & ep descriptors
+        DeleteInterface(ifcset, aInterfaceNum);
+        iDescriptors.DeleteIfcDescriptor(ifcset, aInterfaceNum);
+        }
+    // Delete the whole interface if all settings are gone
+    if (ifcset_ptr->iInterfaces.Count() == 0)
+        {
+        DeleteInterfaceSet(ifcset);
+        }
+    // We now no longer have a valid current configuration
+    iCurrentConfig = 0;
+    if (iDeviceState == UsbShai::EUsbPeripheralStateConfigured)
+        {
+        NextDeviceState(UsbShai::EUsbPeripheralStateAddress);
+        }
+    // If it was the last interface(set)...
+    if (iConfigs[0]->iInterfaceSets.Count() == 0)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  No ifc left -> turning off UDC"));
+        // First disconnect the device from the bus
+        UsbDisconnect();
+        DeActivateHardwareController();
+        // (this also disables endpoint zero; we cannot have a USB device w/o interface, see 9.6.3)
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::ReleaseInterface"));
+    return KErrNone;
+    }
+
+
+/** Enforces a USB re-enumeration by disconnecting the UDC from the bus (if it is currently connected) and
+    re-connecting it.
+
+    This only works if the PSL supports it, i.e. if SoftConnectCaps() returns ETrue.
+*/
+EXPORT_C TInt DUsbClientController::ReEnumerate()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::ReEnumerate()"));
+    
+    // ReEnumerate is possible only when stack is enabled
+    if (!iStackIsActive)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Client stack disabled -> returning here"));
+        return KErrNotReady;
+        }
+    
+    // If no interfaces setup, there is no point to reenumerate
+    if (iConfigs[0]->iInterfaceSets.Count() == 0)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  > No interface registered -> no need to re-enumerate"));
+        return KErrNone;;
+        }
+    
+    if (!iHardwareActivated)
+        {
+        // If the UDC is still off, we switch it on here.
+        const TInt r = ActivateHardwareController();
+        if (r != KErrNone)
+                {
+                __KTRACE_OPT(KPANIC, Kern::Printf("  Error: ActivateHardwareController() failed: %d", r));
+                return r;
+                }
+        
+        // Finally connect the device to the bus
+        UsbConnect();
+        }
+    else
+        {
+        UsbDisconnect();
+        
+        // Now we have to wait a certain amount of time, in order to give the host the opportunity
+        // to come to terms with the new situation.
+        // (The ETrue parameter makes the callback get called in DFC instead of in ISR context.)
+        iReconnectTimer.OneShot(KUsbReconnectDelay, ETrue);
+        }
+        
+    __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::ReEnumerate()"));
+    return KErrNone;;
+    }
+
+
+/** Powers up the UDC if one or more interfaces exist.
+
+    @return KErrNone if UDC successfully powered up, KErrNotReady if no
+    interfaces have been registered yet, KErrHardwareNotAvailable if UDC
+    couldn't be activated.
+*/
+EXPORT_C TInt DUsbClientController::PowerUpUdc()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::PowerUpUdc()"));
+    
+    // we need to check whether Stack is activate or not(can be done by otg sw in otg setup
+    // or by vBus risen/fallen event in a non-otg env)
+    if (!iStackIsActive)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Client stack disabled -> returning here"));
+        return KErrNotReady;
+        }
+    
+    if (iConfigs[0]->iInterfaceSets.Count() == 0)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  No interface registered -> won't power up UDC"));
+        return KErrNotReady;
+        }
+    
+    // If the UDC is still off, we switch it on here.
+    const TInt r = ActivateHardwareController();
+    if (r != KErrNone)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: ActivateHardwareController() failed: %d", r));
+        }
+    
+    __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::PowerUpUdc() returns %d",r));
+    return r;
+    }
+
+
+/** Connects the UDC to the bus.
+
+    @return KErrNone if UDC successfully connected, 
+            KErrNotSupported if KDevCapSoftConnect not supported
+            KErrGeneral if there was an error.
+            
+*/
+EXPORT_C TInt DUsbClientController::UsbConnect()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::UsbConnect()"));
+    iClientSupportReady = ETrue;
+    
+    // If a deferred reset is pending, service it now
+    const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
+    if (iUsbResetDeferred)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Resetting USB Reset 'defer' flag"));
+        iUsbResetDeferred = EFalse;
+        (void) ProcessResetEvent(EFalse);
+        }
+    __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+
+    // Indicate readiness to connect to the PSL
+    const TInt r = iController.PeripheralConnect();
+    
+    // Check whether Stack is activated by OTG controller
+    // or Vbus Risen had been detected.
+    // If either of them is true and HW is not activated yet, do it here.
+    if (iStackIsActive &&  !iHardwareActivated )
+        {
+        // PowerUpUdc only do Activating Hardware when there are at least 1
+        // Iterface registered            
+        PowerUpUdc();
+        }
+    
+    __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::UsbConnect()"));
+    return r;
+    }
+
+
+/** Disconnects the UDC from the bus.
+
+    This only works if the PSL supports it, i.e. if SoftConnectCaps() returns ETrue.
+
+    @return KErrNone if UDC successfully disconnected, KErrGeneral if there was an error.
+*/
+EXPORT_C TInt DUsbClientController::UsbDisconnect()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::UsbDisconnect()"));
+    iClientSupportReady = EFalse;
+
+    // Indicate to PSL that we are no longer ready to connect
+    const TInt r = iController.PeripheralDisconnect();
+
+    // There won't be any notification by the PSL about this,
+    // so we have to notify the LDD/user ourselves:
+    if ((r == KErrNone) && (iDeviceState != UsbShai::EUsbPeripheralStateUndefined))
+        {
+        // Not being in state UNDEFINED implies that the cable is inserted.
+        if (iHardwareActivated)
+            {
+            NextDeviceState(UsbShai::EUsbPeripheralStatePowered);
+            }
+        // (If the hardware is NOT activated at this point, we can only be in
+        //    state UsbShai::EUsbPeripheralStateAttached, so we don't have to move to it.)
+        }
+    return r;
+    }
+
+
+/** Registers a notification callback for changes of the USB device state.
+
+    In the event of a device state change, the callback's state member gets updated (using SetState) with a
+    new UsbShai::TUsbPeripheralState value, and then the callback is executed (DoCallback). 'USB device state' here refers
+    to the Visible Device States as defined in chapter 9 of the USB specification.
+
+    @param aCallback A reference to a properly filled in status callback structure.
+
+    @return KErrNone if callback successfully registered, KErrGeneral if this callback is already registered
+    (it won't be registered twice).
+*/
+EXPORT_C TInt DUsbClientController::RegisterForStatusChange(TUsbcStatusCallback& aCallback)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RegisterForStatusChange()"));
+    if (iStatusCallbacks.Elements() == KUsbcMaxListLength)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Maximum list length reached: %d",
+                                          KUsbcMaxListLength));
+        return KErrGeneral;
+        }
+    if (IsInTheStatusList(aCallback))
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Error: StatusCallback @ 0x%x already registered", &aCallback));
+        return KErrGeneral;
+        }
+    const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
+    iStatusCallbacks.AddLast(aCallback);
+    __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+    return KErrNone;
+    }
+
+
+/** De-registers (removes from the list of pending requests) a notification callback for the USB device
+    status.
+
+    @param aClientId A pointer to the LDD owning the status change callback.
+
+    @return KErrNone if callback successfully unregistered, KErrNotFound if the callback couldn't be found.
+*/
+EXPORT_C TInt DUsbClientController::DeRegisterForStatusChange(const DBase* aClientId)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForStatusChange()"));
+    __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
+    const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
+    TSglQueIter<TUsbcStatusCallback> iter(iStatusCallbacks);
+    TUsbcStatusCallback* p;
+    while ((p = iter++) != NULL)
+        {
+        if (p->Owner() == aClientId)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  removing StatusCallback @ 0x%x", p));
+            iStatusCallbacks.Remove(*p);
+            __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+            return KErrNone;
+            }
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("  client not found"));
+    __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+    return KErrNotFound;
+    }
+
+
+/** Registers a notification callback for changes of the state of endpoints.
+
+    In the event of a state change of an endpoint that is spart of an interface which is owned by the LDD
+    specified in the callback structure, the callback's state member gets updated (using SetState) with a new
+    value, and the callback is executed (DoCallback). 'Endpoint state' here refers to the state of the
+    ENDPOINT_HALT feature of an endpoint as described in chapter 9 of the USB specification. The contents of
+    the state variable reflects the state of the halt features for all endpoints of the current interface
+    setting: bit 0 represents endpoint 1, bit 1 endpoint 2, etc. A set bit means 'endpoint halted', a cleared
+    bit 'endpoint not halted'.
+
+    @param aCallback A reference to a properly filled in endpoint status callback structure.
+
+    @return KErrNone if callback successfully registered, KErrGeneral if this callback is already registered
+    (it won't be registered twice).
+*/
+EXPORT_C TInt DUsbClientController::RegisterForEndpointStatusChange(TUsbcEndpointStatusCallback& aCallback)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RegisterForEndpointStatusChange()"));
+    if (iEpStatusCallbacks.Elements() == KUsbcMaxListLength)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Maximum list length reached: %d",
+                                          KUsbcMaxListLength));
+        return KErrGeneral;
+        }
+    if (IsInTheEpStatusList(aCallback))
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Error: EpStatusCallback @ 0x%x already registered", &aCallback));
+        return KErrGeneral;
+        }
+    const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
+    iEpStatusCallbacks.AddLast(aCallback);
+    __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+    return KErrNone;
+    }
+
+
+/** De-registers (removes from the list of pending requests) a notification callback for changes of the state
+    of endpoints.
+
+    @param aClientId A pointer to the LDD owning the endpoint status change callback.
+
+    @return KErrNone if callback successfully unregistered, KErrNotFound if the callback couldn't be found.
+*/
+EXPORT_C TInt DUsbClientController::DeRegisterForEndpointStatusChange(const DBase* aClientId)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForEndpointStatusChange()"));
+    __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
+    const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
+    TSglQueIter<TUsbcEndpointStatusCallback> iter(iEpStatusCallbacks);
+    TUsbcEndpointStatusCallback* p;
+    while ((p = iter++) != NULL)
+        {
+        if (p->Owner() == aClientId)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  removing EpStatusCallback @ 0x%x", p));
+            iEpStatusCallbacks.Remove(*p);
+            __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+            return KErrNone;
+            }
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("  client not found"));
+    __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+    return KErrNotFound;
+    }
+
+
+/** Returns the number of the currently active alternate interface setting for this interface.
+
+    @param aClientId A pointer to the LDD owning the interface.
+    @param aInterfaceNum Here the interface gets written to.
+
+    @return KErrNotFound if an interface for this client couldn't be found, KErrNone if setting value was
+    successfully written.
+*/
+EXPORT_C TInt DUsbClientController::GetInterfaceNumber(const DBase* aClientId, TInt& aInterfaceNum) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetInterfaceNumber()"));
+    const TInt ifcset = ClientId2InterfaceNumber(aClientId);
+    if (ifcset < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error (ifc < 0)"));
+        return KErrNotFound;
+        }
+    const TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(ifcset);
+    if (!ifcset_ptr)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: interface number %d doesn't exist", ifcset));
+        return KErrNotFound;
+        }
+    aInterfaceNum = ifcset_ptr->iCurrentInterface;
+    return KErrNone;
+    }
+
+
+/** This is normally called once by an LDD's destructor, either after a Close() on the user side,
+    or during general cleanup.
+
+    It might also be called by the LDD when some internal unrecoverable error occurs.
+
+    This function
+    - de-registers a possibly pending device state change notification request,
+    - de-registers a possibly pending endpoint state change notification request,
+    - releases all interfaces + settings owned by this LDD,
+    - cancels all remaining (if any) read/write requests.
+
+    @param aClientId A pointer to the LDD to be unregistered.
+
+    @return KErrNone.
+*/
+EXPORT_C TInt DUsbClientController::DeRegisterClient(const DBase* aClientId)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterClient(0x%x)", aClientId));
+    // Cancel all device state notification requests
+    DeRegisterForStatusChange(aClientId);
+    // Cancel all endpoint state notification requests
+    DeRegisterForEndpointStatusChange(aClientId);
+    DeRegisterForOtgFeatureChange(aClientId);
+    DeRegisterClientCallback(aClientId);
+    // Delete the interface including all its alternate settings which might exist.
+    // (If we release the default setting (0), all alternate settings are deleted as well.)
+    const TInt r = ReleaseInterface(aClientId, 0);
+    // Cancel all remaining (if any) read/write requests
+    DeleteRequestCallbacks(aClientId);
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterClient: Done."));
+    return r;
+    }
+
+
+/** Returns the currently used Ep0 max packet size.
+
+    @return The currently used Ep0 max packet size.
+*/
+EXPORT_C TInt DUsbClientController::Ep0PacketSize() const
+    {
+    const TUsbcLogicalEndpoint* const ep = iRealEndpoints[0].iLEndpoint;
+    if (iHighSpeed)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Ep0 size = %d (HS)", ep->iEpSize_Hs));
+        return ep->iEpSize_Hs;
+        }
+    else
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Ep0 size = %d (FS)", ep->iEpSize_Fs));
+        return ep->iEpSize_Fs;
+        }
+    }
+
+
+/** Stalls Ep0.
+
+    @param aClientId A pointer to the LDD wishing to stall Ep0 (this is for PIL internal purposes only).
+
+    @return KErrNone if endpoint zero successfully stalled, KErrGeneral otherwise.
+*/
+EXPORT_C TInt DUsbClientController::Ep0Stall(const DBase* aClientId)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::Ep0Stall()"));
+    if (aClientId == iEp0ClientId)
+        {
+        ResetEp0DataOutVars();
+        }
+    const TInt err = iConTransferMgr->StallEndpoint(KEp0_Out);
+    if (err < 0)
+        {
+        return err;
+        }
+    else
+        return iConTransferMgr->StallEndpoint(KEp0_In);
+    }
+
+
+/** Sends a zero-byte status packet on Ep0.
+
+    @param aClientId A pointer to the LDD wishing to send the status packet (not used at present).
+*/
+EXPORT_C void DUsbClientController::SendEp0StatusPacket(const DBase* /* aClientId */)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SendEp0StatusPacket()"));
+    iConTransferMgr->SendEp0ZeroByteStatusPacket();
+    }
+
+
+/** Returns the current USB device state.
+
+    'USB device state' here refers to the Visible Device States as defined in chapter 9 of the USB
+    specification.
+
+    @return The current USB device state, or UsbShai::EUsbPeripheralStateUndefined
+*/
+EXPORT_C UsbShai::TUsbPeripheralState DUsbClientController::GetDeviceStatus() const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetDeviceStatus()"));
+    return iDeviceState;
+    }
+
+
+/** Returns the state of an endpoint.
+
+    'Endpoint state' here refers to the state of the ENDPOINT_HALT feature of
+    an endpoint as described in chapter 9 of the USB specification.
+
+    @param aClientId A pointer to the LDD owning the interface which contains the endpoint to be queried.
+    @param aEndpointNum The number of the endpoint to be queried.
+
+    @return The current endpoint state, or EEndpointStateUnknown if the endpoint couldn't be found.
+*/
+EXPORT_C TEndpointState DUsbClientController::GetEndpointStatus(const DBase* aClientId, TInt aEndpointNum) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::GetEndpointStatus()"));
+    
+    TEndpointState ret = (iRealEndpoints[aEndpointNum].iHalt)?EEndpointStateStalled : EEndpointStateNotStalled;
+    
+    __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::GetEndpointStatus() %d",ret));
+    
+    return  ret;
+    }
+
+
+/** Sets up a data read request for an endpoint.
+
+    @param aCallback A reference to a properly filled in data transfer request callback structure.
+
+    @return KErrNone if callback successfully registered or if this callback is already registered
+    (but it won't be registered twice), KErrNotFound if the endpoint couldn't be found, KErrArgument if
+    endpoint number invalid (PSL), KErrGeneral if something else goes wrong.
+*/
+EXPORT_C TInt DUsbClientController::SetupReadBuffer(TUsbcRequestCallback& aCallback)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetupReadBuffer()"));
+    const TInt ep = aCallback.iRealEpNum;
+    __KTRACE_OPT(KUSB, Kern::Printf("  logical ep: #%d", aCallback.iEndpointNum));
+    __KTRACE_OPT(KUSB, Kern::Printf("  real ep:    #%d", ep));
+    TInt err = KErrGeneral;
+    if (ep != 0)
+        {
+        if (iRequestCallbacks[ep])
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: RequestCallback already registered for that ep"));
+            if (iRequestCallbacks[ep] == &aCallback)
+                {
+                __KTRACE_OPT(KPANIC, Kern::Printf("  (this same RequestCallback @ 0x%x)", &aCallback));
+                }
+            else
+                {
+                __KTRACE_OPT(KPANIC, Kern::Printf("  (a different RequestCallback @ 0x%x)", &aCallback));
+                }
+            return KErrNone;
+            }
+        // This may seem awkward:
+        // First we add a callback, and then, in case of an error, we remove it again.
+        // However this is necessary because the transfer request might complete (through
+        // an ISR) _before_ the SetupEndpointRead function returns. Since we don't know the
+        // outcome, we have to provide the callback before making the setup call.
+        //
+        __KTRACE_OPT(KUSB, Kern::Printf("  adding RequestCallback[%d] @ 0x%x", ep, &aCallback));
+        iRequestCallbacks[ep] = &aCallback;
+        if ((err = iController.SetupEndpointRead(ep, aCallback)) != KErrNone)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  removing RequestCallback @ 0x%x (due to error)",
+                                              &aCallback));
+            iRequestCallbacks[ep] = NULL;
+            }
+        }
+    else                                                    // (ep == 0)
+        {
+        if (iEp0ReadRequestCallbacks.Elements() == KUsbcMaxListLength)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Maximum list length reached: %d",
+                                              KUsbcMaxListLength));
+            return KErrGeneral;
+            }
+        if (IsInTheRequestList(aCallback))
+            {       
+            __KTRACE_OPT(KUSB, Kern::Printf("  RequestCallback @ 0x%x already registered", &aCallback));
+            return KErrNone;
+            }
+        // Ep0 reads don't need to be prepared - there's always one pending
+        __KTRACE_OPT(KUSB, Kern::Printf("  adding RequestCallback @ 0x%x (ep0)", &aCallback));
+        const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
+        iEp0ReadRequestCallbacks.AddLast(aCallback);
+        __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+        err = KErrNone;
+        if (iEp0_RxExtraCount != 0)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  iEp0_RxExtraData: trying again..."));
+            
+            const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
+            
+            // Extra data is either a setup packet or a data packet
+            // They are not possible to be both
+            // And, the error code must be KErrNone, otherwise, we can not arrive here
+            if( iSetupPacketPending )
+                {
+                ProcessSetupPacket(iEp0_RxExtraCount,KErrNone);
+                }
+            else
+                {
+                ProcessDataOutPacket(iEp0_RxExtraCount,KErrNone);
+                }
+            
+            // clear it since already completed to client
+            iEp0_RxExtraCount = 0;
+            
+            err = iLastError;
+            
+            __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+            if (err == KErrNone)
+                {
+                //iEp0_RxExtraData = EFalse;
+                // Queue a new Ep0 read (because xxxProceed only re-enables the interrupt)
+                iConTransferMgr->SetupEndpointZeroRead();
+                if (iSetupPacketPending)
+                    {
+                    iConTransferMgr->Ep0SetupPacketProceed();
+                    iSetupPacketPending = EFalse;
+                    }
+                else
+                    {
+                    iConTransferMgr->Ep0DataPacketProceed();
+                    }
+                
+                __KTRACE_OPT(KUSB, Kern::Printf("  :-)"));
+                }
+            else
+                {
+                __KTRACE_OPT(KPANIC, Kern::Printf("  Error: :-("));
+                err = KErrGeneral;
+                }
+            return err;
+            }
+        }
+    return err;
+    }
+
+
+/** Sets up a data write request for an endpoint.
+
+    @param aCallback A reference to a properly filled in data transfer request callback structure.
+
+    @return KErrNone if callback successfully registered or if this callback is already registered
+    (but it won't be registered twice), KErrNotFound if the endpoint couldn't be found, KErrArgument if
+    endpoint number invalid (PSL), KErrGeneral if something else goes wrong.
+*/
+EXPORT_C TInt DUsbClientController::SetupWriteBuffer(TUsbcRequestCallback& aCallback)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetupWriteBuffer()"));
+    TInt ep = aCallback.iRealEpNum;
+    __KTRACE_OPT(KUSB, Kern::Printf("  logical ep: #%d", aCallback.iEndpointNum));
+    __KTRACE_OPT(KUSB, Kern::Printf("  real ep:       #%d", ep));
+    if (iRequestCallbacks[ep])
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: RequestCallback already registered for that ep"));
+        if (iRequestCallbacks[ep] == &aCallback)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  (this same RequestCallback @ 0x%x)", &aCallback));
+            return KErrNone;
+            }
+        else
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  (a different RequestCallback @ 0x%x - poss. error)",
+                                              &aCallback));
+            return KErrGeneral;
+            }
+        }
+    if (ep == 0)
+        {
+        if (iEp0_TxNonStdCount)
+            {
+            if (iEp0_TxNonStdCount > aCallback.iLength)
+                {
+                __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Ep0 is sending less data than requested"));
+                if ((aCallback.iLength % iEp0MaxPacketSize == 0) && !aCallback.iZlpReqd)
+                    {
+                    __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Zlp should probably be requested"));
+                    }
+                }
+            else if (iEp0_TxNonStdCount < aCallback.iLength)
+                {
+                __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Ep0 is sending more data than requested"));
+                }
+            iEp0_TxNonStdCount = 0;
+            }
+        // Ep0 IN needs to be adjusted: the LDD uses 0 for both Ep0 directions.
+        ep = KEp0_Tx;
+        }
+    // This may seem awkward:
+    // First we add a callback, and then, in case of an error, we remove it again.
+    // However this is necessary because the transfer request might complete (through
+    // an ISR) _before_ the SetupEndpointWrite function returns. Since we don't know the
+    // outcome, we have to provide the callback before making the setup call.
+    //
+    __KTRACE_OPT(KUSB, Kern::Printf("  adding RequestCallback[%d] @ 0x%x", ep, &aCallback));
+    iRequestCallbacks[ep] = &aCallback;
+    if (ep == KEp0_Tx)
+        {
+        iEp0ClientDataTransmitting = ETrue;             // this must be set before calling SetupEndpointZeroWrite
+        TInt ret = iConTransferMgr->SetupEndpointZeroWrite(aCallback.iBufferStart, aCallback.iLength, aCallback.iZlpReqd);
+        if (ret != KErrNone)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  removing RequestCallback @ 0x%x (due to error)", &aCallback));
+            iRequestCallbacks[ep] = NULL;
+            iEp0ClientDataTransmitting = EFalse;
+            return ret;
+            }
+        }
+    else if (iController.SetupEndpointWrite(ep, aCallback) != KErrNone)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  removing RequestCallback @ 0x%x (due to error)", &aCallback));
+        iRequestCallbacks[ep] = NULL;
+        }
+    return KErrNone;
+    }
+
+
+/** Cancels a data read request for an endpoint.
+
+    The request callback will be removed from the queue and the
+    callback function won't be executed.
+
+    @param aClientId A pointer to the LDD owning the interface which contains the endpoint.
+    @param aRealEndpoint The number of the endpoint for which the transfer request is to be cancelled.
+*/
+EXPORT_C void DUsbClientController::CancelReadBuffer(const DBase* aClientId, TInt aRealEndpoint)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CancelReadBuffer(%d)", aRealEndpoint));
+    if (aRealEndpoint < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: ep # < 0: %d", aRealEndpoint));
+        return;
+        }
+    // Note that we here don't cancel Ep0 read requests at the PSL level!
+    if (aRealEndpoint > 0)
+        {
+        iController.CancelEndpointRead(aRealEndpoint);
+        }
+    DeleteRequestCallback(aClientId, aRealEndpoint, UsbShai::EControllerRead);
+    }
+
+
+/** Cancels a data write request for an endpoint.
+
+    It cannot be guaranteed that the data is not sent nonetheless, as some UDCs don't permit a flushing of a
+    TX FIFO once it has been filled. The request callback will be removed from the queue in any case and the
+    callback function won't be executed.
+
+    @param aClientId A pointer to the LDD owning the interface which contains the endpoint.
+    @param aRealEndpoint The number of the endpoint for which the transfer request is to be cancelled.
+*/
+EXPORT_C void DUsbClientController::CancelWriteBuffer(const DBase* aClientId, TInt aRealEndpoint)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CancelWriteBuffer(%d)", aRealEndpoint));
+    if (aRealEndpoint < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: ep # < 0: %d", aRealEndpoint));
+        return;
+        }
+    if (aRealEndpoint == 0)
+        {
+        // Ep0 IN needs to be adjusted: the LDD uses 0 for both Ep0 directions.
+        aRealEndpoint = KEp0_Tx;
+        }
+    iController.CancelEndpointWrite(aRealEndpoint);
+    if (aRealEndpoint == KEp0_Tx)
+        {
+        // Since Ep0 is shared among clients, we don't have to care about the client id.
+        iEp0WritePending = EFalse;
+        }
+    DeleteRequestCallback(aClientId, aRealEndpoint, UsbShai::EControllerWrite);
+    }
+
+
+/** Halts (stalls) an endpoint (but not Ep0).
+
+    @param aClientId A pointer to the LDD owning the interface which contains the endpoint to be stalled.
+    @param aEndpointNum The number of the endpoint.
+
+    @return KErrNotFound if endpoint couldn't be found (includes Ep0), KErrNone if endpoint successfully
+    stalled, KErrGeneral otherwise.
+*/
+EXPORT_C TInt DUsbClientController::HaltEndpoint(const DBase* aClientId, TInt aEndpointNum)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::HaltEndpoint(%d)", aEndpointNum));
+    const TInt r = iController.StallEndpoint(aEndpointNum);
+    if (r == KErrNone)
+        {
+        iRealEndpoints[aEndpointNum].iHalt = ETrue;
+        }
+    else if (r == KErrArgument)
+        {
+        return KErrNotFound;
+        }
+    return r;
+    }
+
+
+/** Clears the halt condition of an endpoint (but not Ep0).
+
+    @param aClientId A pointer to the LDD owning the interface which contains the endpoint to be un-stalled.
+    @param aEndpointNum The number of the endpoint.
+
+    @return KErrNotFound if endpoint couldn't be found (includes Ep0), KErrNone if endpoint successfully
+    stalled, KErrGeneral otherwise.
+*/
+EXPORT_C TInt DUsbClientController::ClearHaltEndpoint(const DBase* aClientId, TInt aEndpointNum)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ClearHaltEndpoint(%d)", aEndpointNum));
+    const TInt r = iController.ClearStallEndpoint(aEndpointNum);
+    if (r == KErrNone)
+        {
+        iRealEndpoints[aEndpointNum].iHalt = EFalse;
+        }
+    else if (r == KErrArgument)
+        {
+        return KErrNotFound;
+        }
+    return r;
+    }
+
+
+/** This function requests 'device control' for an LDD.
+
+    Class or vendor specific Ep0 requests addressed to the USB device as a whole (Recipient field in
+    bmRequestType byte of a Setup packet set to zero) are delivered to the LDD that owns device control. For
+    obvious reasons only one USB LDD can have device control at any given time.
+
+    @param aClientId A pointer to the LDD requesting device control.
+
+    @return KErrNone if device control successfully claimed or if this LDD already owns it, KErrGeneral if
+    device control already owned by a different client.
+*/
+EXPORT_C TInt DUsbClientController::SetDeviceControl(const DBase* aClientId)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetDeviceControl()"));
+    if (iEp0DeviceControl)
+        {
+        if (iEp0DeviceControl == aClientId)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Device Control already owned by this client"));
+            return KErrNone;
+            }
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Device Control already claimed by a different client"));
+        return KErrGeneral;
+        }
+    iEp0DeviceControl = aClientId;
+    return KErrNone;
+    }
+
+
+/** This function releases device control for an LDD.
+
+    @see DUsbClientController::SetDeviceControl()
+
+    @param aClientId A pointer to the LDD releasing device control.
+
+    @return KErrNone if device control successfully released, KErrGeneral if device control owned by a
+    different client or by no client at all.
+*/
+EXPORT_C TInt DUsbClientController::ReleaseDeviceControl(const DBase* aClientId)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ReleaseDeviceControl()"));
+    if (iEp0DeviceControl)
+        {
+        if (iEp0DeviceControl == aClientId)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  Releasing Device Control"));
+            iEp0DeviceControl = NULL;
+            return KErrNone;
+            }
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Device Control owned by a different client"));
+        }
+    else
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Device Control not owned by any client"));
+        }
+    return KErrGeneral;
+    }
+
+
+/** Returns all available (configurable) max packet sizes for Ep0.
+
+    The information is coded as bitwise OR'ed values of KUsbEpSizeXXX constants (the bitmap format used for
+    TUsbcEndpointCaps.iSupportedSizes).
+
+    @return All available (configurable) max packet sizes for Ep0.
+*/
+EXPORT_C TUint DUsbClientController::EndpointZeroMaxPacketSizes() const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EndpointZeroMaxPacketSizes()"));
+    return iRealEndpoints[0].iCaps.iSizes;
+    }
+
+
+/** Sets (configures) the max packet size for Ep0.
+
+    For available sizes as returned by DUsbClientController::EndpointZeroMaxPacketSizes()
+
+    Note that for HS operation the Ep0 size cannot be chosen, but is fixed at 64 bytes.
+
+    @return KErrNotSupported if invalid size specified, KErrNone if new max packet size successfully set or
+    requested size was already set.
+*/
+EXPORT_C TInt DUsbClientController::SetEndpointZeroMaxPacketSize(TInt aMaxPacketSize)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetEndpointZeroMaxPacketSize(%d)",
+                                    aMaxPacketSize));
+
+    if (iControllerProperties.iControllerCaps & UsbShai::KDevCapHighSpeed)
+        {
+        // We're not going to mess with this on a HS device.
+        return KErrNone;
+        }
+
+    if (!(iRealEndpoints[0].iCaps.iSizes & PacketSize2Mask(aMaxPacketSize)))
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: invalid size"));
+        return KErrNotSupported;
+        }
+    if (iRealEndpoints[0].iLEndpoint->iEpSize_Fs == aMaxPacketSize)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  this packet size already set -> returning"));
+        return KErrNone;
+        }
+    const TUsbcLogicalEndpoint* const ep0_0 = iRealEndpoints[0].iLEndpoint;
+    const TUsbcLogicalEndpoint* const ep0_1 = iRealEndpoints[1].iLEndpoint;
+    const_cast<TUsbcLogicalEndpoint*>(ep0_0)->iEpSize_Fs = aMaxPacketSize;
+    const_cast<TUsbcLogicalEndpoint*>(ep0_1)->iEpSize_Fs = aMaxPacketSize;
+
+    // @@@ We should probably modify the device descriptor here as well...
+
+    if (iHardwareActivated)
+        {
+        // De-configure endpoint zero
+        iController.DeConfigureEndpoint(KEp0_Out);
+        iController.DeConfigureEndpoint(KEp0_In);
+        // Re-configure endpoint zero
+        const_cast<TUsbcLogicalEndpoint*>(ep0_0)->iInfo.iSize = ep0_0->iEpSize_Fs;
+        const_cast<TUsbcLogicalEndpoint*>(ep0_1)->iInfo.iSize = ep0_1->iEpSize_Fs;
+        iController.ConfigureEndpoint(0, ep0_0->iInfo);
+        iController.ConfigureEndpoint(1, ep0_1->iInfo);
+        iEp0MaxPacketSize = ep0_0->iInfo.iSize;
+        }
+    return KErrNone;
+    }
+
+
+/** Returns the current USB Device descriptor.
+
+    @param aThread A pointer to the thread the LDD requesting the descriptor is running in.
+    @param aDeviceDescriptor A reference to a buffer into which the requested descriptor should be written
+    (most likely located user-side).
+
+    @return The return value of the thread write operation, Kern::ThreadWrite(), when writing to the target
+    buffer.
+*/
+EXPORT_C TInt DUsbClientController::GetDeviceDescriptor(DThread* aThread, TDes8& aDeviceDescriptor)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetDeviceDescriptor()"));
+    return iDescriptors.GetDeviceDescriptorTC(aThread, aDeviceDescriptor);
+    }
+
+
+/** Sets a new USB Device descriptor.
+
+    @param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
+    @param aDeviceDescriptor A reference to a buffer which contains the descriptor to be set (most likely
+    located user-side).
+
+    @return The return value of the thread read operation, Kern::ThreadRead(), when reading from the source
+    buffer in case of a failure, KErrNone if the new descriptor was successfully set.
+*/
+EXPORT_C TInt DUsbClientController::SetDeviceDescriptor(DThread* aThread, const TDes8& aDeviceDescriptor)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetDeviceDescriptor()"));
+    return iDescriptors.SetDeviceDescriptorTC(aThread, aDeviceDescriptor);
+    }
+
+
+/** Returns the current USB Device descriptor size.
+
+    @param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
+    @param aSize A reference to a buffer into which the requested descriptor size should be written
+    (most likely located user-side).
+
+    @return The return value of the thread write operation, Kern::ThreadWrite(), when writing to the target
+    buffer.
+*/
+EXPORT_C TInt DUsbClientController::GetDeviceDescriptorSize(DThread* aThread, TDes8& aSize)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetDeviceDescriptorSize()"));
+    // We do not really enquire here....
+    const TPtrC8 size(reinterpret_cast<const TUint8*>(&KUsbDescSize_Device), sizeof(KUsbDescSize_Device));
+    return Kern::ThreadDesWrite(aThread, &aSize, size, 0);
+    }
+
+
+/** Returns the current USB configuration descriptor.
+
+    @param aThread A pointer to the thread the LDD requesting the descriptor is running in.
+    @param aConfigurationDescriptor A reference to a buffer into which the requested descriptor should be
+    written (most likely located user-side).
+
+    @return The return value of the thread write operation, Kern::ThreadWrite(), when writing to the target
+    buffer.
+*/
+EXPORT_C TInt DUsbClientController::GetConfigurationDescriptor(DThread* aThread, TDes8& aConfigurationDescriptor)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetConfigurationDescriptor()"));
+    return iDescriptors.GetConfigurationDescriptorTC(aThread, aConfigurationDescriptor);
+    }
+
+
+/** Sets a new USB configuration descriptor.
+
+    @param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
+    @param aConfigurationDescriptor A reference to a buffer which contains the descriptor to be set (most
+    likely located user-side).
+
+    @return The return value of the thread read operation, Kern::ThreadRead() when reading from the source
+    buffer in case of a failure, KErrNone if the new descriptor was successfully set.
+*/
+EXPORT_C TInt DUsbClientController::SetConfigurationDescriptor(DThread* aThread,
+                                                               const TDes8& aConfigurationDescriptor)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetConfigurationDescriptor()"));
+    return iDescriptors.SetConfigurationDescriptorTC(aThread, aConfigurationDescriptor);
+    }
+
+
+/** Returns the current USB configuration descriptor size.
+
+    @param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
+    @param aSize A reference to a buffer into which the requested descriptor size should be written
+    (most likely located user-side).
+
+    @return The return value of the thread write operation, Kern::ThreadWrite(), when writing to the target
+    buffer.
+*/
+EXPORT_C TInt DUsbClientController::GetConfigurationDescriptorSize(DThread* aThread, TDes8& aSize)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetConfigurationDescriptorSize()"));
+    // We do not really enquire here....
+    const TPtrC8 size(reinterpret_cast<const TUint8*>(&KUsbDescSize_Config), sizeof(KUsbDescSize_Config));
+    return Kern::ThreadDesWrite(aThread, &aSize, size, 0);
+    }
+
+
+/** Returns the current USB OTG descriptor.
+
+    @param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
+    @param aOtgDesc A reference to a buffer into which the requested descriptor should be
+    written (most likely located user-side).
+
+    @return KErrNotSupported or the return value of the thread write operation, Kern::ThreadDesWrite(),
+    when writing to the target buffer.
+*/
+EXPORT_C TInt DUsbClientController::GetOtgDescriptor(DThread* aThread, TDes8& aOtgDesc) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetOtgDescriptor()"));
+    if (!iOtgSupport)
+        {
+        return KErrNotSupported;
+        }
+    return iDescriptors.GetOtgDescriptorTC(aThread, aOtgDesc);
+    }
+
+
+/** Sets a new OTG descriptor.
+
+    @param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
+    @param aOtgDesc A reference to a buffer which contains new OTG descriptor.
+
+    @return KErrNotSupported or the return value of the thread read operation, Kern::ThreadDesRead().
+*/
+EXPORT_C TInt DUsbClientController::SetOtgDescriptor(DThread* aThread, const TDesC8& aOtgDesc)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetOtgDescriptor()"));
+    if (!iOtgSupport)
+        {
+        return KErrNotSupported;
+        }
+    TBuf8<KUsbDescSize_Otg> otg;
+    const TInt r = Kern::ThreadDesRead(aThread, &aOtgDesc, otg, 0);
+    if (r != KErrNone)
+        {
+        return r;
+        }
+    // Check descriptor validity
+    if (otg[0] != KUsbDescSize_Otg || otg[1] != KUsbDescType_Otg || otg[2] > 3)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid OTG descriptor"));
+        return KErrGeneral;
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("  iOtgFuncMap before: 0x%x", iOtgFuncMap));
+    // Update value in controller as well
+    const TUint8 hnp = otg[2] & KUsbOtgAttr_HnpSupp;
+    const TUint8 srp = otg[2] & KUsbOtgAttr_SrpSupp;
+    if (hnp && !srp)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Invalid OTG attribute combination (HNP && !SRP"));
+        }
+    if (hnp && !(iOtgFuncMap & KUsbOtgAttr_HnpSupp))
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Setting attribute KUsbOtgAttr_HnpSupp"));
+        iOtgFuncMap |= KUsbOtgAttr_HnpSupp;
+        }
+    else if (!hnp && (iOtgFuncMap & KUsbOtgAttr_HnpSupp))
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Removing attribute KUsbOtgAttr_HnpSupp"));
+        iOtgFuncMap &= ~KUsbOtgAttr_HnpSupp;
+        }
+    if (srp && !(iOtgFuncMap & KUsbOtgAttr_SrpSupp))
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Setting attribute KUsbOtgAttr_SrpSupp"));
+        iOtgFuncMap |= KUsbOtgAttr_SrpSupp;
+        }
+    else if (!srp && (iOtgFuncMap & KUsbOtgAttr_SrpSupp))
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Removing attribute KUsbOtgAttr_SrpSupp"));
+        iOtgFuncMap &= ~KUsbOtgAttr_SrpSupp;
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("  iOtgFuncMap after:  0x%x", iOtgFuncMap));
+    return iDescriptors.SetOtgDescriptor(otg);
+    }
+
+
+/** Returns current OTG features of USB device.
+
+    @param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
+    @param aFeatures A reference to a buffer into which the requested OTG features should be written.
+
+    @return KErrNotSupported or the return value of the thread write operation, Kern::ThreadDesWrite().
+*/
+EXPORT_C TInt DUsbClientController::GetOtgFeatures(DThread* aThread, TDes8& aFeatures) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetOtgFeatures()"));
+    if (!iOtgSupport)
+        {
+        return KErrNotSupported;
+        }
+    TBuf8<1> features(1);
+    features[0] = iOtgFuncMap & 0x1C;
+    return Kern::ThreadDesWrite(aThread, &aFeatures, features, 0);
+    }
+
+
+/** Returns current OTG features of USB device. This function is intended to be
+    called only from kernel side.
+
+    @param aFeatures The reference to which the current features should be set at.
+    @return KErrNone if successful, KErrNotSupported if OTG is unavailable.
+*/
+EXPORT_C TInt DUsbClientController::GetCurrentOtgFeatures(TUint8& aFeatures) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetCurrentOtgFeatures()"));
+    if (!iOtgSupport)
+        {
+        return KErrNotSupported;
+        }
+    aFeatures = iOtgFuncMap & 0x1C;
+    return KErrNone;
+    }
+
+
+/** Registers client request for OTG feature change. Client is notified when any OTG
+    feature is changed.
+
+    @see KUsbOtgAttr_B_HnpEnable, KUsbOtgAttr_A_HnpSupport, KUsbOtgAttr_A_AltHnpSupport
+
+    @param aCallback Callback function. Gets called when OTG features change
+
+    @return KErrNone if successful, KErrAlreadyExists if aCallback is already in the queue.
+*/
+EXPORT_C TInt DUsbClientController::RegisterForOtgFeatureChange(TUsbcOtgFeatureCallback& aCallback)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RegisterForOtgFeatureChange()"));
+    if (iOtgCallbacks.Elements() == KUsbcMaxListLength)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Maximum list length reached: %d",
+                                          KUsbcMaxListLength));
+        return KErrGeneral;
+        }
+    if (IsInTheOtgFeatureList(aCallback))
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Error: OtgFeatureCallback @ 0x%x already registered", &aCallback));
+        return KErrAlreadyExists;
+        }
+    const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
+    iOtgCallbacks.AddLast(aCallback);
+    __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+    return KErrNone;
+    }
+
+
+/** De-registers (removes from the list of pending requests) a notification callback for
+    OTG feature change.
+
+    @param aClientId A pointer to the LDD owning the endpoint status change callback.
+
+    @return KErrNone if callback successfully unregistered, KErrNotFound if the callback couldn't be found.
+*/
+EXPORT_C TInt DUsbClientController::DeRegisterForOtgFeatureChange(const DBase* aClientId)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForOtgFeatureChange()"));
+    __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
+    const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
+    TSglQueIter<TUsbcOtgFeatureCallback> iter(iOtgCallbacks);
+    TUsbcOtgFeatureCallback* p;
+    while ((p = iter++) != NULL)
+        {
+        if (!aClientId || p->Owner() == aClientId)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  removing OtgFeatureCallback @ 0x%x", p));
+            iOtgCallbacks.Remove(*p);
+            __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+            return KErrNone;
+            }
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("  client not found"));
+    __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+    return KErrNotFound;
+    }
+
+
+/** Returns a specific standard USB interface descriptor.
+
+    @param aThread A pointer to the thread the LDD requesting the descriptor is running in.
+    @param aClientId A pointer to the LDD requesting the descriptor.
+    @param aSettingNum The setting number of the interface for which the descriptor is requested.
+    @param aInterfaceDescriptor A reference to a buffer into which the requested descriptor should be written
+    (most likely located user-side).
+
+    @return KErrNotFound if the specified interface couldn't be found, otherwise the return value of the thread
+    write operation, Kern::ThreadWrite(), when writing to the target buffer.
+*/
+EXPORT_C TInt DUsbClientController::GetInterfaceDescriptor(DThread* aThread, const DBase* aClientId,
+                                                           TInt aSettingNum, TDes8& aInterfaceDescriptor)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetInterfaceDescriptor(x, 0x%08x, %d, y)",
+                                    aClientId, aSettingNum));
+    const TInt ifcset = ClientId2InterfaceNumber(aClientId);
+    if (ifcset < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
+        return KErrNotFound;
+        }
+    return iDescriptors.GetInterfaceDescriptorTC(aThread, aInterfaceDescriptor, ifcset, aSettingNum);
+    }
+
+
+/** Sets a new standard USB interface descriptor.
+
+    This function can also be used, by the user, and under certain conditions, to change an interface's number
+    (reported as bInterfaceNumber in the descriptor). The conditions are: 1) We cannot accept a number that is
+    already used by another interface, 2) We allow the interface number to be changed only when it's still the
+    only setting, and 3) We allow the interface number to be changed only for the default setting (0). (All
+    alternate settings created for that interface thereafter will inherit the new, changed number.)
+
+    @param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
+    @param aClientId A pointer to the LDD requesting the setting of the descriptor.
+    @param aSettingNum The setting number of the interface for which the descriptor is to be set.
+    @param aInterfaceDescriptor A reference to a buffer which contains the descriptor to be set (most
+    likely located user-side).
+
+    @return KErrNotFound if the specified interface couldn't be found, the return value of the thread read
+    operation, Kern::ThreadRead(), when reading from the source buffer in case of a failure, KErrArgument if the
+    interface  number is to be changed (via bInterfaceNumber in the descriptor) and either the requested
+    interface number is already used by another interface or the interface has more than one setting. KErrNone
+    if the new descriptor was successfully set.
+*/
+EXPORT_C TInt DUsbClientController::SetInterfaceDescriptor(DThread* aThread, const DBase* aClientId,
+                                                           TInt aSettingNum, const TDes8& aInterfaceDescriptor)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetInterfaceDescriptor(x, 0x%08x, %d, y)",
+                                    aClientId, aSettingNum));
+    const TInt ifcset = ClientId2InterfaceNumber(aClientId);
+    if (ifcset < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
+        return KErrNotFound;
+        }
+    TBuf8<KUsbDescSize_Interface> new_ifc;
+    TInt r = Kern::ThreadDesRead(aThread, &aInterfaceDescriptor, new_ifc, 0);
+    if (r != KErrNone)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Copying interface descriptor buffer failed (%d)", r));
+        return r;
+        }
+    const TInt ifcset_new = new_ifc[2];
+    const TBool ifc_num_changes = (ifcset != ifcset_new);
+    TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(ifcset);
+    if (!ifcset_ptr)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: interface number %d doesn't exist", ifcset));
+        return KErrNotFound;
+        }
+    if (ifc_num_changes)
+        {
+        // If the user wants to change the interface number, we need to do some sanity checks:
+        if (InterfaceExists(ifcset_new))
+            {
+            // Obviously we cannot accept a number that is already used by another interface.
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: interface number %d already in use", ifcset_new));
+            return KErrArgument;
+            }
+        if (ifcset_ptr->iInterfaces.Count() > 1)
+            {
+            // We allow the interface number to be changed only when it's the only setting.
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: interface has more than one alternate setting"));
+            return KErrArgument;
+            }
+        if (aSettingNum != 0)
+            {
+            // We allow the interface number to be changed only when it's the default setting.
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: interface number can only be changed for setting 0"));
+            return KErrArgument;
+            }
+        }
+    if ((r = iDescriptors.SetInterfaceDescriptor(new_ifc, ifcset, aSettingNum)) != KErrNone)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: iDescriptors.SetInterfaceDescriptorfailed"));
+        return r;
+        }
+    if (ifc_num_changes)
+        {
+        // Alright then, let's do it...
+        __KTRACE_OPT(KUSB, Kern::Printf("  about to change interface number from %d to %d",
+                                        ifcset, ifcset_new));
+        ifcset_ptr->iInterfaceNumber = ifcset_new;
+        }
+    return KErrNone;
+    }
+
+
+/** Returns the size of a specific standard USB interface descriptor.
+
+    @param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
+    @param aClientId A pointer to the LDD requesting the descriptor size.
+    @param aSettingNum The setting number of the interface for which the descriptor size is requested.
+    @param aSize A reference to a buffer into which the requested descriptor size should be written (most
+    likely located user-side).
+
+    @return KErrNotFound if the specified interface couldn't be found, otherwise the return value of the thread
+    write operation, Kern::ThreadWrite(), when writing to the target buffer.
+*/
+EXPORT_C TInt DUsbClientController::GetInterfaceDescriptorSize(DThread* aThread, const DBase* aClientId,
+                                                               TInt /*aSettingNum*/, TDes8& aSize)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetInterfaceDescriptorSize()"));
+    const TInt ifcset = ClientId2InterfaceNumber(aClientId);
+    if (ifcset < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
+        return KErrNotFound;
+        }
+    // Actually, we do not really enquire here....
+    const TPtrC8 size(reinterpret_cast<const TUint8*>(&KUsbDescSize_Interface), sizeof(KUsbDescSize_Interface));
+    Kern::ThreadDesWrite(aThread, &aSize, size, 0);
+    return KErrNone;
+    }
+
+
+/** Returns a specific standard USB endpoint descriptor.
+
+    @param aThread A pointer to the thread the LDD requesting the descriptor is running in.
+    @param aClientId A pointer to the LDD requesting the descriptor.
+    @param aSettingNum The setting number of the interface that contains the endpoint for which the
+    descriptor is requested.
+    @param aEndpointNum The endpoint for which the descriptor is requested.
+    @param aEndpointDescriptor A reference to a buffer into which the requested descriptor should be written
+    (most likely located user-side).
+
+    @return KErrNotFound if the specified interface or endpoint couldn't be found, otherwise the return value
+    of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
+*/
+EXPORT_C TInt DUsbClientController::GetEndpointDescriptor(DThread* aThread, const DBase* aClientId,
+                                                          TInt aSettingNum, TInt aEndpointNum,
+                                                          TDes8& aEndpointDescriptor)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetEndpointDescriptor(x, 0x%08x, %d, %d, y)",
+                                    aClientId, aSettingNum, aEndpointNum));
+    const TInt ifcset = ClientId2InterfaceNumber(aClientId);
+    if (ifcset < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
+        return KErrNotFound;
+        }
+    return iDescriptors.GetEndpointDescriptorTC(aThread, aEndpointDescriptor, ifcset,
+                                                aSettingNum, EpIdx2Addr(aEndpointNum));
+    }
+
+
+/** Sets a new standard USB endpoint descriptor.
+
+    @param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
+    @param aClientId A pointer to the LDD requesting the setting of the descriptor.
+    @param aSettingNum The setting number of the interface that contains the endpoint for which the
+    descriptor is to be set.
+    @param aEndpointNum The endpoint for which the descriptor is to be set.
+    @param aEndpointDescriptor A reference to a buffer which contains the descriptor to be set (most
+    likely located user-side).
+
+    @return KErrNotFound if the specified interface or endpoint couldn't be found, the return value of the
+    thread read operation, Kern::ThreadRead(), when reading from the source buffer in case of a read failure,
+    KErrNone if the new descriptor was successfully set.
+*/
+EXPORT_C TInt DUsbClientController::SetEndpointDescriptor(DThread* aThread, const DBase* aClientId,
+                                                          TInt aSettingNum, TInt aEndpointNum,
+                                                          const TDes8& aEndpointDescriptor)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetEndpointDescriptor(x, 0x%08x, %d, %d, y)",
+                                    aClientId, aSettingNum, aEndpointNum));
+    const TInt ifcset = ClientId2InterfaceNumber(aClientId);
+    if (ifcset < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
+        return KErrNotFound;
+        }
+    return iDescriptors.SetEndpointDescriptorTC(aThread, aEndpointDescriptor, ifcset,
+                                                aSettingNum, EpIdx2Addr(aEndpointNum));
+    }
+
+
+/** Returns the size of a specific standard USB endpoint descriptor.
+
+    @param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
+    @param aClientId A pointer to the LDD requesting the descriptor size.
+    @param aSettingNum The setting number of the interface that contains the endpoint for which the
+    descriptor size is requested.
+    @param aEndpointNum The endpoint for which the descriptor size is requested.
+    @param aEndpointDescriptor A reference to a buffer into which the requested descriptor size should be
+    written (most likely located user-side).
+
+    @return KErrNotFound if the specified interface or endpoint couldn't be found, otherwise the return value
+    of the thread write operation, kern::ThreadWrite(), when writing to the target buffer.
+*/
+EXPORT_C TInt DUsbClientController::GetEndpointDescriptorSize(DThread* aThread, const DBase* aClientId,
+                                                              TInt aSettingNum, TInt aEndpointNum,
+                                                              TDes8& aSize)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetEndpointDescriptorSize(x, 0x%08x, %d, %d, y)",
+                                    aClientId, aSettingNum, aEndpointNum));
+    const TInt ifcset = ClientId2InterfaceNumber(aClientId);
+    if (ifcset < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
+        return KErrNotFound;
+        }
+    TInt s;
+    TInt r = iDescriptors.GetEndpointDescriptorSize(ifcset, aSettingNum,
+                                                    EpIdx2Addr(aEndpointNum), s);
+    if (r == KErrNone)
+        {
+        TPtrC8 size(reinterpret_cast<const TUint8*>(&s), sizeof(s));
+        r = Kern::ThreadDesWrite(aThread, &aSize, size, 0);
+        }
+    else
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: endpoint descriptor not found"));
+        }
+    return r;
+    }
+
+
+/** Returns the current Device_Qualifier descriptor. On a USB device which doesn't support high-speed
+    operation this function will return an error. Note that the contents of the descriptor depend on
+    the current device speed (full-speed or high-speed).
+
+    @param aThread A pointer to the thread the LDD requesting the descriptor is running in.
+    @param aDeviceQualifierDescriptor A reference to a buffer into which the requested descriptor
+    should be written (most likely located user-side).
+
+    @return KErrNotSupported if this descriptor is not supported, otherwise the return value of the thread
+    write operation, Kern::ThreadWrite(), when writing to the target buffer.
+*/
+EXPORT_C TInt DUsbClientController::GetDeviceQualifierDescriptor(DThread* aThread,
+                                                                 TDes8& aDeviceQualifierDescriptor)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetDeviceQualifierDescriptor()"));
+    return iDescriptors.GetDeviceQualifierDescriptorTC(aThread, aDeviceQualifierDescriptor);
+    }
+
+
+/** Sets a new Device_Qualifier descriptor. On a USB device which doesn't support high-speed
+    operation this function will return an error. Note that the contents of the descriptor should take
+    into account the current device speed (full-speed or high-speed) as it is dependent on it.
+
+    @param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
+    @param aDeviceQualifierDescriptor A reference to a buffer which contains the descriptor to be set (most
+    likely located user-side).
+
+    @return KErrNotSupported if this descriptor is not supported, otherwise the return value of the thread
+    read operation, Kern::ThreadRead(), when reading from the source buffer in case of a failure, KErrNone if
+    the new descriptor was successfully set.
+*/
+EXPORT_C TInt DUsbClientController::SetDeviceQualifierDescriptor(DThread* aThread,
+                                                                 const TDes8& aDeviceQualifierDescriptor)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetDeviceQualifierDescriptor()"));
+    return iDescriptors.SetDeviceQualifierDescriptorTC(aThread, aDeviceQualifierDescriptor);
+    }
+
+
+/** Returns the current Other_Speed_Configuration descriptor. On a USB device which doesn't support high-speed
+    operation this function will return an error. Note that the contents of the descriptor depend on the
+    current device speed (full-speed or high-speed).
+
+    @param aThread A pointer to the thread the LDD requesting the descriptor is running in.
+    @param aConfigurationDescriptor A reference to a buffer into which the requested descriptor
+    should be written (most likely located user-side).
+
+    @return KErrNotSupported if this descriptor is not supported, otherwise the return value of the thread
+    write operation, Kern::ThreadWrite(), when writing to the target buffer.
+*/
+EXPORT_C TInt DUsbClientController::GetOtherSpeedConfigurationDescriptor(DThread* aThread,
+                                                                         TDes8& aConfigurationDescriptor)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetOtherSpeedConfigurationDescriptor()"));
+    return iDescriptors.GetOtherSpeedConfigurationDescriptorTC(aThread, aConfigurationDescriptor);
+    }
+
+
+/** Sets a new Other_Speed_Configuration descriptor. On a USB device which doesn't support high-speed
+    operation this function will return an error. Note that the contents of the descriptor should take
+    into account the current device speed (full-speed or high-speed) as it is dependent on it.
+
+    @param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
+    @param aConfigurationDescriptor A reference to a buffer which contains the descriptor to be set (most
+    likely located user-side).
+
+    @return KErrNotSupported if this descriptor is not supported, otherwise the return value of the thread
+    read operation, Kern::ThreadRead(), when reading from the source buffer in case of a failure, KErrNone if
+    the new descriptor was successfully set.
+*/
+EXPORT_C TInt DUsbClientController::SetOtherSpeedConfigurationDescriptor(DThread* aThread,
+                                                                         const TDes8& aConfigurationDescriptor)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetOtherSpeedConfigurationDescriptor()"));
+    return iDescriptors.SetOtherSpeedConfigurationDescriptorTC(aThread, aConfigurationDescriptor);
+    }
+
+
+/** Returns a block of all available non-standard (class-specific) interface descriptors for a specific
+    interface.
+
+    @param aThread A pointer to the thread the LDD requesting the descriptor block is running in.
+    @param aClientId A pointer to the LDD requesting the descriptor block.
+    @param aSettingNum The setting number of the interface for which the descriptor block is requested.
+    @param aInterfaceDescriptor A reference to a buffer into which the requested descriptor(s) should be
+    written (most likely located user-side).
+
+    @return KErrNotFound if the specified interface couldn't be found, otherwise the return value of the thread
+    write operation, Kern::ThreadWrite(), when writing to the target buffer.
+*/
+EXPORT_C TInt DUsbClientController::GetCSInterfaceDescriptorBlock(DThread* aThread, const DBase* aClientId,
+                                                                  TInt aSettingNum,
+                                                                  TDes8& aInterfaceDescriptor)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetCSInterfaceDescriptorBlock(x, 0x%08x, %d, y)",
+                                    aClientId, aSettingNum));
+    const TInt ifcset = ClientId2InterfaceNumber(aClientId);
+    if (ifcset < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
+        return KErrNotFound;
+        }
+    return iDescriptors.GetCSInterfaceDescriptorTC(aThread, aInterfaceDescriptor, ifcset, aSettingNum);
+    }
+
+
+/** Sets a block of (i.e. one or more) non-standard (class-specific) interface descriptors for a specific
+    interface.
+
+    @param aThread A pointer to the thread the LDD requesting the setting of the descriptor block is running
+    in.
+    @param aClientId A pointer to the LDD requesting the setting of the descriptor block.
+    @param aSettingNum The setting number of the interface for which the setting of the descriptor block is
+    requested.
+    @param aInterfaceDescriptor A reference to a buffer which contains the descriptor block to be set (most
+    likely located user-side).
+    @param aSize The size of the descriptor block to be set.
+
+    @return KErrNotFound if the specified interface couldn't be found, KErrArgument if aSize is less than 2,
+    KErrNoMemory if enough memory for the new descriptor(s) couldn't be allocated, otherwise the return value
+    of the thread read operation, Kern::ThreadRead(), when reading from the source buffer.
+*/
+EXPORT_C TInt DUsbClientController::SetCSInterfaceDescriptorBlock(DThread* aThread, const DBase* aClientId,
+                                                                  TInt aSettingNum,
+                                                                  const TDes8& aInterfaceDescriptor, TInt aSize)
+    {
+    __KTRACE_OPT(KUSB,
+                 Kern::Printf("DUsbClientController::SetCSInterfaceDescriptorBlock(x, 0x%08x, %d, y, %d)",
+                              aClientId, aSettingNum, aSize));
+    const TInt ifcset = ClientId2InterfaceNumber(aClientId);
+    if (ifcset < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
+        return KErrNotFound;
+        }
+    if (aSize < 2)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: aSize < 2 (%d)", aSize));
+        return KErrArgument;
+        }
+    return iDescriptors.SetCSInterfaceDescriptorTC(aThread, aInterfaceDescriptor, ifcset, aSettingNum, aSize);
+    }
+
+
+/** Returns the total size all non-standard (class-specific) interface descriptors for a specific interface.
+
+    @param aThread A pointer to the thread the LDD requesting the descriptor block size is running in.
+    @param aClientId A pointer to the LDD requesting the descriptor block size.
+    @param aSettingNum The setting number of the interface for which the descriptor block size is
+    requested.
+    @param aSize A reference to a buffer into which the requested descriptor block size should be written (most
+    likely located user-side).
+
+    @return KErrNotFound if the specified interface couldn't be found, otherwise the return value of the thread
+    write operation, Kern::ThreadWrite(), when writing to the target buffer.
+*/
+EXPORT_C TInt DUsbClientController::GetCSInterfaceDescriptorBlockSize(DThread* aThread, const DBase* aClientId,
+                                                                      TInt aSettingNum, TDes8& aSize)
+    {
+    __KTRACE_OPT(KUSB,
+                 Kern::Printf("DUsbClientController::GetCSInterfaceDescriptorBlockSize(x, 0x%08x, %d, y)",
+                              aClientId, aSettingNum));
+    const TInt ifcset = ClientId2InterfaceNumber(aClientId);
+    if (ifcset < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
+        return KErrNotFound;
+        }
+    TInt s;
+    const TInt r = iDescriptors.GetCSInterfaceDescriptorSize(ifcset, aSettingNum, s);
+    if (r == KErrNone)
+        {
+        const TPtrC8 size(reinterpret_cast<const TUint8*>(&s), sizeof(s));
+        Kern::ThreadDesWrite(aThread, &aSize, size, 0);
+        }
+    else
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: cs interface descriptor not found"));
+        }
+    return r;
+    }
+
+
+/** Returns a block of all available non-standard (class-specific) endpoint descriptors for a specific endpoint.
+
+    @param aThread A pointer to the thread the LDD requesting the descriptor block is running in.
+    @param aClientId A pointer to the LDD requesting the descriptor block.
+    @param aSettingNum The setting number of the interface that contains the endpoint for which the
+    descriptor block is requested.
+    @param aEndpointNum The endpoint for which the descriptor block is requested.
+    @param aEndpointDescriptor A reference to a buffer into which the requested descriptor(s) should be written
+    (most likely located user-side).
+
+    @return KErrNotFound if the specified interface or endpoint couldn't be found, otherwise the return value
+    of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
+*/
+EXPORT_C TInt DUsbClientController::GetCSEndpointDescriptorBlock(DThread* aThread, const DBase* aClientId,
+                                                                 TInt aSettingNum, TInt aEndpointNum,
+                                                                 TDes8& aEndpointDescriptor)
+    {
+    __KTRACE_OPT(KUSB,
+                 Kern::Printf("DUsbClientController::GetCSEndpointDescriptorBlock(x, 0x%08x, %d, %d, y)",
+                              aClientId, aSettingNum, aEndpointNum));
+    const TInt ifcset = ClientId2InterfaceNumber(aClientId);
+    if (ifcset < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
+        return KErrNotFound;
+        }
+    return iDescriptors.GetCSEndpointDescriptorTC(aThread, aEndpointDescriptor, ifcset,
+                                                  aSettingNum, EpIdx2Addr(aEndpointNum));
+    }
+
+
+/** Sets a block of (i.e. one or more) non-standard (class-specific) endpoint descriptors for a specific
+    endpoint.
+
+    @param aThread A pointer to the thread the LDD requesting the setting of the descriptor block is running
+    in.
+    @param aClientId A pointer to the LDD requesting the setting of the descriptor block.
+    @param aSettingNum The setting number of the interface that contains the endpoint for which the
+    descriptor block is to be set.
+    @param aEndpointNum The endpoint for which the descriptor block is to be set.
+    @param aEndpointDescriptor A reference to a buffer which contains the descriptor block to be set (most
+    likely located user-side).
+    @param aSize The size of the descriptor block to be set.
+
+    @return KErrNotFound if the specified interface or endpoint couldn't be found, KErrArgument if aSize is
+    less than 2, KErrNoMemory if enough memory for the new descriptor(s) couldn't be allocated, otherwise the
+    return value of the thread read operation, Kern::ThreadRead(), when reading from the source buffer.
+*/
+EXPORT_C TInt DUsbClientController::SetCSEndpointDescriptorBlock(DThread* aThread, const DBase* aClientId,
+                                                                 TInt aSettingNum, TInt aEndpointNum,
+                                                                 const TDes8& aEndpointDescriptor, TInt aSize)
+    {
+    __KTRACE_OPT(KUSB,
+                 Kern::Printf("DUsbClientController::SetCSEndpointDescriptorBlock(x, 0x%08x, %d, %d, y)",
+                              aClientId, aSettingNum, aEndpointNum));
+    const TInt ifcset = ClientId2InterfaceNumber(aClientId);
+    if (ifcset < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
+        return KErrNotFound;
+        }
+    if (aSize < 2)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: aSize < 2 (%d)", aSize));
+        return KErrArgument;
+        }
+    return iDescriptors.SetCSEndpointDescriptorTC(aThread, aEndpointDescriptor, ifcset,
+                                                  aSettingNum, EpIdx2Addr(aEndpointNum), aSize);
+    }
+
+
+/** Returns the total size all non-standard (class-specific) endpoint descriptors for a specific endpoint.
+
+    @param aThread A pointer to the thread the LDD requesting the descriptor block size is running in.
+    @param aClientId A pointer to the LDD requesting the descriptor block size.
+    @param aSettingNum The setting number of the interface for which the descriptor block size is
+    requested.
+    @param aEndpointNum The endpoint for which the descriptor block size is requested.
+    @param aSize A reference to a buffer into which the requested descriptor block size should be written (most
+    likely located user-side).
+
+    @return KErrNotFound if the specified interface or endpoint couldn't be found, otherwise the return value
+    of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
+*/
+EXPORT_C TInt DUsbClientController::GetCSEndpointDescriptorBlockSize(DThread* aThread, const DBase* aClientId,
+                                                                     TInt aSettingNum, TInt aEndpointNum,
+                                                                     TDes8& aSize)
+    {
+    __KTRACE_OPT(KUSB,
+                 Kern::Printf("DUsbClientController::GetCSEndpointDescriptorBlockSize(x, 0x%08x, %d, %d, y)",
+                              aClientId, aSettingNum, aEndpointNum));
+    const TInt ifcset = ClientId2InterfaceNumber(aClientId);
+    if (ifcset < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
+        return KErrNotFound;
+        }
+    TInt s;
+    const TInt r = iDescriptors.GetCSEndpointDescriptorSize(ifcset, aSettingNum,
+                                                            EpIdx2Addr(aEndpointNum), s);
+    if (r == KErrNone)
+        {
+        const TPtrC8 size(reinterpret_cast<const TUint8*>(&s), sizeof(s));
+        Kern::ThreadDesWrite(aThread, &aSize, size, 0);
+        }
+    else
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: cs endpoint descriptor not found"));
+        }
+    return r;
+    }
+
+
+/** Returns the currently set string descriptor language ID (LANGID) code.
+
+    @param aThread A pointer to the thread the LDD requesting the LANGID is running in.
+    @param aLangId A reference to a buffer into which the requested code should be written (most likely
+    located user-side).
+
+    @return The return value of the thread write operation, Kern::ThreadDesWrite(),
+    when writing to the target buffer.
+*/
+EXPORT_C TInt DUsbClientController::GetStringDescriptorLangId(DThread* aThread, TDes8& aLangId)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetStringDescriptorLangId()"));
+    return iDescriptors.GetStringDescriptorLangIdTC(aThread, aLangId);
+    }
+
+
+/** Sets the string descriptor language ID (LANGID) code.
+
+    @param aLangId The langauge ID code to be written.
+
+    @return KErrNone.
+*/
+EXPORT_C TInt DUsbClientController::SetStringDescriptorLangId(TUint16 aLangId)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetStringDescriptorLangId()"));
+    return iDescriptors.SetStringDescriptorLangId(aLangId);
+    }
+
+
+/** Returns the currently set Manufacturer string (which is referenced by the iManufacturer field in the device
+    descriptor).
+
+    (Thus, the function should actually be called either 'GetManufacturerString'
+    or 'GetManufacturerStringDescriptorString'.)
+
+    @param aThread A pointer to the thread the LDD requesting the string is running in.
+    @param aString A reference to a buffer into which the requested string should be written (most likely
+    located user-side).
+
+    @return KErrNotFound if the string descriptor couldn't be found (PIL internal error), otherwise the return
+    value of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
+*/
+EXPORT_C TInt DUsbClientController::GetManufacturerStringDescriptor(DThread* aThread, TDes8& aString)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetManufacturerStringDescriptor()"));
+    return iDescriptors.GetManufacturerStringDescriptorTC(aThread, aString);
+    }
+
+
+/** Sets a new Manufacturer string in the Manufacturer string descriptor (which is referenced by the
+    iManufacturer field in the device descriptor).
+
+    (Thus, the function should actually be called either
+    'SetManufacturerString' or 'SetManufacturerStringDescriptorString'.)
+
+    @param aThread A pointer to the thread the LDD requesting the setting of the string is running in.
+    @param aString A reference to a buffer which contains the string to be set (most likely located
+    user-side).
+
+    @return KErrNoMemory if not enough memory for the new descriptor or the string could be allocated, the
+    return value of the thread read operation, Kern::ThreadRead(), if reading from the source buffer goes wrong,
+    KErrNone if new string descriptor successfully set.
+*/
+EXPORT_C TInt DUsbClientController::SetManufacturerStringDescriptor(DThread* aThread, const TDes8& aString)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetManufacturerStringDescriptor()"));
+    return iDescriptors.SetManufacturerStringDescriptorTC(aThread, aString);
+    }
+
+
+/** Removes (deletes) the Manufacturer string descriptor (which is referenced by the
+    iManufacturer field in the device descriptor).
+
+    @return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found
+*/
+EXPORT_C TInt DUsbClientController::RemoveManufacturerStringDescriptor()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RemoveManufacturerStringDescriptor()"));
+    return iDescriptors.RemoveManufacturerStringDescriptor();
+    }
+
+
+/** Returns the currently set Product string (which is referenced by the iProduct field in the device
+    descriptor).
+
+    (Thus, the function should actually be called either 'GetProductString' or
+    'GetProductStringDescriptorString'.)
+
+    @param aThread A pointer to the thread the LDD requesting the string is running in.
+    @param aString A reference to a buffer into which the requested string should be written (most likely
+    located user-side).
+
+    @return KErrNotFound if the string descriptor couldn't be found (PIL internal error), otherwise the return
+    value of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
+*/
+EXPORT_C TInt DUsbClientController::GetProductStringDescriptor(DThread* aThread, TDes8& aString)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetProductStringDescriptor()"));
+    return iDescriptors.GetProductStringDescriptorTC(aThread, aString);
+    }
+
+
+/** Sets a new Product string in the Product string descriptor (which is referenced by the iProduct field in
+    the device descriptor).
+
+    (Thus, the function should actually be called either 'SetProductString' or
+    'SetProductStringDescriptorString'.)
+
+    @param aThread A pointer to the thread the LDD requesting the setting of the string is running in.
+    @param aString A reference to a buffer which contains the string to be set (most likely located
+    user-side).
+
+    @return KErrNoMemory if not enough memory for the new descriptor or the string could be allocated, the
+    return value of the thread read operation, Kern::ThreadRead(), if reading from the source buffer goes wrong,
+    KErrNone if new string descriptor successfully set.
+*/
+EXPORT_C TInt DUsbClientController::SetProductStringDescriptor(DThread* aThread, const TDes8& aString)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetProductStringDescriptor()"));
+    return iDescriptors.SetProductStringDescriptorTC(aThread, aString);
+    }
+
+
+/** Removes (deletes) the Product string descriptor (which is referenced by the
+    iProduct field in the device descriptor).
+
+    @return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found
+*/
+EXPORT_C TInt DUsbClientController::RemoveProductStringDescriptor()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RemoveProductStringDescriptor()"));
+    return iDescriptors.RemoveProductStringDescriptor();
+    }
+
+
+/** Returns the currently set SerialNumber string (which is referenced by the iSerialNumber field in the device
+    descriptor).
+
+    (Thus, the function should actually be called either 'GetSerialNumberString' or
+    'GetSerialNumberStringDescriptorString'.)
+
+    @param aThread A pointer to the thread the LDD requesting the string is running in.
+    @param aString A reference to a buffer into which the requested string should be written (most likely
+    located user-side).
+
+    @return KErrNotFound if the string descriptor couldn't be found (PIL internal error), otherwise the return
+    value of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
+*/
+EXPORT_C TInt DUsbClientController::GetSerialNumberStringDescriptor(DThread* aThread, TDes8& aString)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetSerialNumberStringDescriptor()"));
+    return iDescriptors.GetSerialNumberStringDescriptorTC(aThread, aString);
+    }
+
+
+/** Sets a new SerialNumber string in the SerialNumber string descriptor (which is referenced by the
+    iSerialNumber field in the device descriptor).
+
+    (Thus, the function should actually be called either
+    'SetSerialNumberString' or 'SetSerialNumberStringDescriptorString'.)
+
+    @param aThread A pointer to the thread the LDD requesting the setting of the string is running in.
+    @param aString A reference to a buffer which contains the string to be set (most likely located
+    user-side).
+
+    @return KErrNoMemory if not enough memory for the new descriptor or the string could be allocated, the
+    return value of the thread read operation, Kern::ThreadRead(), if reading from the source buffer goes wrong,
+    KErrNone if new string descriptor successfully set.
+*/
+EXPORT_C TInt DUsbClientController::SetSerialNumberStringDescriptor(DThread* aThread, const TDes8& aString)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetSerialNumberStringDescriptor()"));
+    return iDescriptors.SetSerialNumberStringDescriptorTC(aThread, aString);
+    }
+
+
+/** Removes (deletes) the Serial Number string descriptor (which is referenced by the
+    iSerialNumber field in the device descriptor).
+
+    @return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found
+*/
+EXPORT_C TInt DUsbClientController::RemoveSerialNumberStringDescriptor()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RemoveSerialNumberStringDescriptor()"));
+    return iDescriptors.RemoveSerialNumberStringDescriptor();
+    }
+
+
+/** Returns the currently set Configuration string (which is referenced by the iConfiguration field in the
+    configuration descriptor).
+
+    (Thus, the function should actually be called either 'GetConfigurationString' or
+    'GetConfigurationStringDescriptorString'.)
+
+    @param aThread A pointer to the thread the LDD requesting the string is running in.
+    @param aString A reference to a buffer into which the requested string should be written (most likely
+    located user-side).
+
+    @return KErrNotFound if the string descriptor couldn't be found (PIL internal error), otherwise the return
+    value of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
+*/
+EXPORT_C TInt DUsbClientController::GetConfigurationStringDescriptor(DThread* aThread, TDes8& aString)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetConfigurationStringDescriptor()"));
+    return iDescriptors.GetConfigurationStringDescriptorTC(aThread, aString);
+    }
+
+
+/** Sets a new Configuration string in the Configuration string descriptor (which is referenced by the
+    iConfiguration field in the configuration descriptor).
+
+    (Thus, the function should actually be called either
+    'SetConfigurationString' or 'SetConfigurationStringDescriptorString'.)
+
+    @param aThread A pointer to the thread the LDD requesting the setting of the string is running in.
+    @param aString A reference to a buffer which contains the string to be set (most likely located
+    user-side).
+
+    @return KErrNoMemory if not enough memory for the new descriptor or the string could be allocated, the
+    return value of the thread read operation, Kern::ThreadRead(), if reading from the source buffer goes wrong,
+    KErrNone if new string descriptor successfully set.
+*/
+EXPORT_C TInt DUsbClientController::SetConfigurationStringDescriptor(DThread* aThread, const TDes8& aString)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetConfigurationStringDescriptor()"));
+    return iDescriptors.SetConfigurationStringDescriptorTC(aThread, aString);
+    }
+
+
+/** Removes (deletes) the Configuration string descriptor (which is referenced by the
+    iConfiguration field in the configuration descriptor).
+
+    @return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found.
+*/
+EXPORT_C TInt DUsbClientController::RemoveConfigurationStringDescriptor()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RemoveConfigurationStringDescriptor()"));
+    return iDescriptors.RemoveConfigurationStringDescriptor();
+    }
+
+
+/** Copies the string descriptor at the specified index in the string descriptor array into
+    the aString argument.
+
+    @param aIndex The position of the string descriptor in the string descriptor array.
+    @param aThread A pointer to the thread the LDD requesting the string is running in.
+    @param aString A reference to a buffer into which the requested string should be written (most likely
+    located user-side).
+
+    @return KErrNone if successful, KErrNotFound if no string descriptor exists at the specified index, or the
+    return value of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
+*/
+EXPORT_C TInt DUsbClientController::GetStringDescriptor(DThread* aThread, TUint8 aIndex, TDes8& aString)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetStringDescriptor(%d)", aIndex));
+    return iDescriptors.GetStringDescriptorTC(aThread, aIndex, aString);
+    }
+
+
+/** Sets the aString argument to be a string descriptor at the specified index in the string
+    descriptor array. If a string descriptor already exists at that position then it will be replaced.
+
+    @param aIndex The position of the string descriptor in the string descriptor array.
+    @param aThread A pointer to the thread the LDD requesting the setting of the string is running in.
+    @param aString A reference to a buffer which contains the string to be set (most likely located
+    user-side).
+
+    @return KErrNone if successful, KErrArgument if aIndex is invalid, KErrNoMemory if no memory is available
+    to store the new string (an existing descriptor at that index will be preserved), or the return value of
+    the thread read operation, Kern::ThreadRead(), if reading from the source buffer goes wrong.
+*/
+EXPORT_C TInt DUsbClientController::SetStringDescriptor(DThread* aThread, TUint8 aIndex, const TDes8& aString)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetStringDescriptor(%d)", aIndex));
+    return iDescriptors.SetStringDescriptorTC(aThread, aIndex, aString);
+    }
+
+
+/** Removes (deletes) the string descriptor at the specified index in the string descriptor array.
+
+    @param aIndex The position of the string descriptor in the string descriptor array.
+
+    @return KErrNone if successful, KErrNotFound if no string descriptor exists at the specified index.
+*/
+EXPORT_C TInt DUsbClientController::RemoveStringDescriptor(TUint8 aIndex)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RemoveStringDescriptor(%d)", aIndex));
+    return iDescriptors.RemoveStringDescriptor(aIndex);
+    }
+
+
+/** Queries the use of and endpoint resource.
+
+    If the resource gets successfully allocated, it will be used from when the current bus transfer
+    has been completed.
+
+    @param aClientId A pointer to the LDD querying the endpoint resource.
+    @param aEndpointNum The number of the endpoint.
+    @param aResource The endpoint resource to be queried.
+
+    @return ETrue if the specified resource is in use at the endpoint, EFalse if not or if there was any error
+    during the execution of the function.
+*/
+EXPORT_C TBool DUsbClientController::QueryEndpointResource(const DBase* /*aClientId*/, TInt aEndpointNum,
+                                                           TUsbcEndpointResource aResource)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::QueryEndpointResource()"));
+    return iController.QueryEndpointResource(aEndpointNum, aResource);
+    }
+
+
+EXPORT_C TInt DUsbClientController::EndpointPacketSize(const DBase* aClientId, TInt aEndpointNum)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EndpointPacketSize(0x%08x, %d)",
+                                    aClientId, aEndpointNum));
+
+    const TUsbcInterfaceSet* const ifcset_ptr = ClientId2InterfacePointer(aClientId);
+    if (!ifcset_ptr)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: interface or clientid not found"));
+        return -1;
+        }
+    const TUsbcInterface* const ifc_ptr = ifcset_ptr->iInterfaces[ifcset_ptr->iCurrentInterface];
+    const RPointerArray<TUsbcLogicalEndpoint>& ep_array = ifc_ptr->iEndpoints;
+    const TInt n = ep_array.Count();
+    for (TInt i = 0; i < n; i++)
+        {
+        const TUsbcLogicalEndpoint* const ep = ep_array[i];
+        if (EpAddr2Idx(ep->iPEndpoint->iEndpointAddr) == static_cast<TUint>(aEndpointNum))
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  Endpoint packet sizes: FS = %d  HS = %d",
+                                            ep->iEpSize_Fs, ep->iEpSize_Hs));
+            const TInt size = iHighSpeed ? ep->iEpSize_Hs : ep->iEpSize_Fs;
+            __KTRACE_OPT(KUSB, Kern::Printf("  Returning %d", size));
+            return size;
+            }
+        }
+    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: endpoint not found"));
+    return -1;
+    }
+    
+EXPORT_C TDfcQue*  DUsbClientController::DfcQ(TInt /*aIndex*/)
+    {
+    return iControllerProperties.iDfcQueue;
+    }
+    
+EXPORT_C void DUsbClientController::DumpRegisters()
+    {
+    return;
+    }
+    
+EXPORT_C TInt DUsbClientController::SignalRemoteWakeup()
+    {
+    return iController.SignalRemoteWakeup();
+    }
+    
+EXPORT_C TBool DUsbClientController::CurrentlyUsingHighSpeed()
+    {
+    UsbShai::TSpeed speed = iController.DeviceOperatingSpeed();
+    
+    return (speed == UsbShai::EHighSpeed)?ETrue:EFalse;
+    }
+
+//
+// === USB Controller member function implementations - PSL API (public) ===========================
+//
+
+/** Gets called by the PSL to register a newly created derived class controller object.
+
+    @param aUdc The number of the new UDC. It should be 0 for the first (or only) UDC in the system, 1 for the
+    second one, and so forth. KUsbcMaxUdcs determines how many UDCs are supported.
+
+    @return A pointer to the controller if successfully registered, NULL if aUdc out of (static) range.
+
+    @publishedPartner @released
+*/
+TInt DUsbClientController::RegisterUdc(TInt aUdc)
+    {
+    TInt err = KErrNone;
+    
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RegisterUdc()"));
+    
+    if (aUdc < 0 || aUdc > (KUsbcMaxUdcs - 1))
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: aUdc out of range (%d)", aUdc));
+        return KErrInUse;
+        }
+    else
+        {
+        UsbClientController[aUdc] = this;
+        }
+        
+    return err;
+    }
+
+
+//
+// === USB Controller member function implementations - PSL API (protected) ========================
+//
+
+/** Initialises an instance of this class, which is the base class of the derived class (= PSL, which is
+    supposed to call this function).
+
+    It does the following things:
+
+    - disconnects the UDC from the bus,
+    - initialises the USB descriptor pool, uses data from the PSL (see function argument list)
+    - creates and initialises the basic USB device configuration
+    - initialises the array of physical endpoints
+    - initialises Ep0 structures (but doesn't configure & enable Ep0 yet)
+    - creates and installs the USB power handler
+
+    @param aDeviceDesc A pointer to a valid standard USB device descriptor or NULL. The values initially
+    required in the descriptor follow from its constructor. The descriptor is not copied over, but rather this
+    pointer is queued directly into the descriptor pool. Must be writable memory.
+
+    @param aConfigDesc A pointer to a valid standard USB configuration descriptor or NULL. The values
+    initially required in the descriptor follow from its constructor. The descriptor is not copied over, but
+    rather this pointer is queued directly into the descriptor pool. Must be writable memory.
+
+    @param aLangId A pointer to a valid USB language ID (string) descriptor. The values initially required in
+    the descriptor follow from its constructor. The descriptor is not copied over, but rather this pointer is
+    queued directly into the descriptor pool. Must be writable memory. Other than the remaining four string
+    descriptors, this one is not optional. The reason is that the USB spec mandates a LangId descriptor as
+    soon as a single string descriptor gets returned by the device. So, even though the device might omit the
+    Manufacturer, Product, SerialNumber, and Configuration string descriptors, it is at this point not known
+    whether there will be any Interface string descriptors. Since any USB API user can create an interface
+    with an Interface string descriptor, we have to insist here on the provision of a LangId string
+    descriptor. (The PIL decides at run-time whether or not to return the LangId string descriptor to the
+    host, depending on whether there exist any string descriptors at that time.)
+
+    @param aManufacturer A pointer to a valid USB string descriptor or NULL. The values initially required in
+    the descriptor follow from its constructor. The descriptor is not copied over, but rather this pointer is
+    queued directly into the descriptor pool. Must be writable memory. This descriptor will be referenced by
+    the iManufacturer field in the device descriptor.
+
+    @param aProduct A pointer to a valid USB string descriptor or NULL. The values initially required in the
+    descriptor follow from its constructor. The descriptor is not copied over, but rather this pointer is
+    queued directly into the descriptor pool. Must be writable memory. This descriptor will be referenced by
+    the iProduct field in the device descriptor.
+
+    @param aSerialNum A pointer to a valid USB string descriptor or NULL. The values initially required in the
+    descriptor follow from its constructor. The descriptor is not copied over, but rather this pointer is
+    queued directly into the descriptor pool. Must be writable memory. This descriptor will be referenced by
+    the iSerialNumber field in the device descriptor.
+
+    @param aConfig A pointer to a valid USB string descriptor or NULL. The values initially required in the
+    descriptor follow from its constructor. The descriptor is not copied over, but rather this pointer is
+    queued directly into the descriptor pool. Must be writable memory. This descriptor will be referenced by
+    the iConfiguration field in the configuration descriptor.
+
+    @param aOtgDesc A pointer to a valid USB OTG descriptor (if OTG is supported by this device and is to be
+    supported by the driver) or NULL. The values initially required in the descriptor follow from its
+    constructor. The descriptor is not copied over, but rather this pointer is queued directly into the
+    descriptor pool. Must be writable memory.
+
+    @return EFalse, if USB descriptor pool initialisation fails, or if configuration creation fails, or if the
+    PSL reports more endpoints than the constant KUsbcMaxEndpoints permits, or if the Ep0 logical endpoint
+    creation fails, or if the creation of the power handler fails; ETrue, if base class object successfully
+    initialised.
+
+    @publishedPartner @released
+*/
+TBool DUsbClientController::Initialise(TUsbPeripheralDescriptorPool& aDescPool,
+                                       const UsbShai::TUsbPeripheralEndpointCaps* aEndpointCaps,
+                                       TInt aTotalEndpoints)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::InitialiseBaseClass()"));
+    
+    // We don't want the host to see us (at least not yet):
+    UsbDisconnect();
+    
+    iDeviceTotalEndpoints = aTotalEndpoints;    
+    
+    // Initialise USB descriptor pool
+    if (iDescriptors.Init(aDescPool.iDeviceDesc, 
+                          aDescPool.iConfigDesc, 
+                          aDescPool.iLangId, 
+                          aDescPool.iManufacturer, 
+                          aDescPool.iProduct,
+                          aDescPool.iSerialNum, 
+                          aDescPool.iConfig, 
+                          aDescPool.iOtgDesc) != KErrNone)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Error: Descriptor initialization failed"));
+        return EFalse;
+        }
+
+    if (aDescPool.iOtgDesc)
+        {
+        iOtgSupport = ETrue;
+        iOtgFuncMap = aDescPool.iOtgDesc->DescriptorData()[2];
+        }
+
+    // Some member variables
+    iSelfPowered  = aDescPool.iConfigDesc->Byte(7) & (1 << 6);        // Byte 7: bmAttributes
+    iRemoteWakeup = aDescPool.iConfigDesc->Byte(7) & (1 << 5);
+
+    if (iControllerProperties.iControllerCaps & UsbShai::KDevCapHighSpeed)
+        {
+        if (iDescriptors.InitHs() != KErrNone)
+            {
+            return EFalse;
+            }
+        }
+
+    // Create and initialise our first (and only) configuration
+    TUsbcConfiguration* config = new TUsbcConfiguration(1);
+    if (!config)
+        {
+        return EFalse;
+        }
+    iConfigs.Append(config);
+
+    // Initialise the array of physical endpoints    
+    __KTRACE_OPT(KUSB, Kern::Printf("  DeviceTotalEndpoints: %d", aTotalEndpoints));
+    
+    // KUsbcMaxEndpoints doesn't include ep 0
+    if ((aTotalEndpoints > (KUsbcMaxEndpoints + 2)) ||
+        ((aTotalEndpoints * sizeof(TUsbcPhysicalEndpoint)) > sizeof(iRealEndpoints)))
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: too many endpoints! (change KUsbcMaxEndpoints: %d)",
+                                          KUsbcMaxEndpoints));
+        return EFalse;
+        }      
+    
+    for (TInt i = 0; i < aTotalEndpoints; ++i)
+        {
+        iRealEndpoints[i].iEndpointAddr = EpIdx2Addr(i);
+        
+        __KTRACE_OPT(KUSB, Kern::Printf("  aEndpointCaps[%02d] - iTypes: 0x%08x iSizes: 0x%08x",
+                                        i, aEndpointCaps[i].iTypesAndDir, aEndpointCaps[i].iSizes));
+                                                                                
+        iRealEndpoints[i].iCaps = aEndpointCaps[i];
+        
+        // Reset revered bytes to zero
+        iRealEndpoints[i].iCaps.iReserved[0] = 0;
+        iRealEndpoints[i].iCaps.iReserved[1] = 0;
+        
+        if ((i > 1) && (aEndpointCaps[i].iTypesAndDir != UsbShai::KUsbEpNotAvailable))
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  --> UsableEndpoint: #%d", i));
+            iDeviceUsableEndpoints++;
+            }
+        }
+
+    // Initialise Ep0 structures (logical endpoints are numbered 1..KMaxEndpointsPerClient,
+    // and virtual 0 is real 0):
+    // -- Ep0 OUT
+    iEp0MaxPacketSize = MaxEndpointPacketSize(aEndpointCaps[0].iSizes);
+    __KTRACE_OPT(KUSB, Kern::Printf("  using Ep0 maxpacketsize of %d bytes", iEp0MaxPacketSize));
+    
+    TUsbcEndpointInfo info(UsbShai::KUsbEpTypeControl, UsbShai::KUsbEpDirOut, 0);
+    TUsbcLogicalEndpoint* ep = NULL;
+    
+    info.iSize = iEp0MaxPacketSize;
+    ep = new TUsbcLogicalEndpoint(this, 0, info, NULL, &iRealEndpoints[KEp0_Out]);
+    if (!ep)
+        {
+        return EFalse;
+        }
+        
+    __KTRACE_OPT(KUSB, Kern::Printf("  creating ep: mapping real ep %d --> logical ep 0", KEp0_Out));
+    iRealEndpoints[KEp0_Out].iLEndpoint = ep;
+    
+    // -- Ep0 IN
+    info.iDir = UsbShai::KUsbEpDirIn;
+    ep = new TUsbcLogicalEndpoint(this, 0, info, NULL, &iRealEndpoints[KEp0_In]);
+    if (!ep)
+        {
+        delete iRealEndpoints[KEp0_Out].iLEndpoint;
+        iRealEndpoints[KEp0_Out].iLEndpoint = NULL;
+        return EFalse;
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("  creating ep: mapping real ep %d --> logical ep 0", KEp0_In));
+    iRealEndpoints[KEp0_In].iLEndpoint = ep;    
+    
+    iPowerHandler = new DUsbcPowerHandler(this);
+    if (!iPowerHandler)
+        {
+        delete iRealEndpoints[KEp0_Out].iLEndpoint;
+        iRealEndpoints[KEp0_Out].iLEndpoint = NULL;
+        delete iRealEndpoints[KEp0_In].iLEndpoint;
+        iRealEndpoints[KEp0_In].iLEndpoint = NULL;
+        return EFalse;
+        }
+    iPowerHandler->Add();
+
+    return ETrue;    
+    }
+
+/** The standard constructor for this class.
+
+    @publishedPartner @released
+ */
+DUsbClientController::DUsbClientController(UsbShai::MPeripheralControllerIf&               aPeripheralControllerIf, 
+                                           const UsbShai::TPeripheralControllerProperties& aProperties,
+                                           TBool                                  aIsOtgPort)
+    : iEp0ReceivedNonStdRequest(EFalse),
+      iRmWakeupStatus_Enabled(EFalse),
+      iEp0_RxBuf(),
+      iDeviceTotalEndpoints(0),
+      iDeviceUsableEndpoints(0),
+      iDeviceState(UsbShai::EUsbPeripheralStateUndefined),
+      iDeviceStateB4Suspend(UsbShai::EUsbPeripheralStateUndefined),
+      iSelfPowered(EFalse),
+      iRemoteWakeup(EFalse),
+      iHardwareActivated(EFalse),
+      iOtgSupport(EFalse),
+      iOtgFuncMap(0),
+      iHighSpeed(EFalse),
+      iEp0MaxPacketSize(0),
+      iEp0ClientId(NULL),
+      iEp0DataReceived(0),
+      iEp0WritePending(EFalse),
+      iEp0ClientDataTransmitting(EFalse),
+      iEp0DeviceControl(NULL),
+      iDescriptors(iEp0_TxBuf),
+      iCurrentConfig(0),
+      iConfigs(1),
+      iRealEndpoints(),
+      iEp0_TxBuf(),
+      iEp0_RxExtraCount(0),
+      iEp0_TxNonStdCount(0),
+      iEp0ReadRequestCallbacks(_FOFF(TUsbcRequestCallback, iLink)),
+      iClientCallbacks(_FOFF(TUsbcClientCallback, iLink)),
+      iStatusCallbacks(_FOFF(TUsbcStatusCallback, iLink)),
+      iEpStatusCallbacks(_FOFF(TUsbcEndpointStatusCallback, iLink)),
+      iOtgCallbacks(_FOFF(TUsbcOtgFeatureCallback, iLink)),
+      iReconnectTimer(ReconnectTimerCallback, this),
+      iUsbLock(TSpinLock::EOrderGenericIrqLow3),      
+      iController(aPeripheralControllerIf),
+      iControllerProperties(aProperties),
+      iIsOtgPort(aIsOtgPort),
+      iOtgObserver(NULL),
+      iConTransferMgr(NULL),
+      iLastError(EFalse),
+      iSetupPacketPending(EFalse),
+      iCommonDfcQThread(NULL),
+      iPowerUpDfc(PowerUpDfc, this, 3),
+      iPowerDownDfc(PowerDownDfc, this, 3),
+      iDeviceEventNotifyDfc(DeviceEventNotifyDfc,this,3),
+      iThreadContextFinder(ThreadContextFinderDfc,this,3),
+      iStandby(EFalse),
+      iStackIsActive(EFalse),
+      iClientSupportReady(EFalse),
+      iUsbResetDeferred(EFalse),
+      iEnablePullUpOnDPlus(NULL),
+      iDisablePullUpOnDPlus(NULL),
+      iOtgContext(NULL)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DUsbClientController()"));
+    
+    iLastError = KErrNone;
+    
+#ifndef SEPARATE_USB_DFC_QUEUE
+    iPowerUpDfc.SetDfcQ(Kern::DfcQue0());
+    iPowerDownDfc.SetDfcQ(Kern::DfcQue0());
+#endif // SEPARATE_USB_DFC_QUEUE
+
+    for (TInt i = 0; i < KUsbcEpArraySize; i++)
+        iRequestCallbacks[i] = NULL;
+    }
+
+TInt DUsbClientController::Construct()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::Construct"));
+    
+    // Setup the state machines of ep0
+    TInt err = SetupEp0StateMachine();
+    if( err != KErrNone)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("    Can not setup state machines, exit"));
+        return err;
+        }
+        
+#ifdef SEPARATE_USB_DFC_QUEUE
+    iPowerUpDfc.SetDfcQ(iControllerProperties.iDfcQueue);
+    iPowerDownDfc.SetDfcQ(iControllerProperties.iDfcQueue);
+#endif  // SEPARATE_USB_DFC_QUEUE
+    
+    iDeviceEventNotifyDfc.SetDfcQ(iControllerProperties.iDfcQueue);
+    iThreadContextFinder.SetDfcQ(iControllerProperties.iDfcQueue);
+    
+    // Register 
+    if( RegisterUdc(0) != KErrNone)
+        {
+        // This is the only reason.
+        return KErrInUse;
+        }
+        
+    __KTRACE_OPT(KUSB, Kern::Printf("    peripheral controller registered"));
+    TUsbPeripheralDescriptorPool descPool;       
+    
+    if( CreateDescriptors(descPool) == KErrNone)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("    descriptors created"));
+        
+        // Initialise the array of physical endpoints 
+        __KTRACE_OPT(KUSB, Kern::Printf("    initialising PIL "));
+        TBool initOk = Initialise(descPool,
+                                  iControllerProperties.iDeviceEndpointCaps,
+                                  iControllerProperties.iDeviceTotalEndpoints);
+        
+        // Let UDC has a changes to know the callback interface is ready.
+        // Any further initialization/startup/preparation etc can be performed now.
+        if  ( initOk )
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("    Initializing PSL "));
+            
+            // Set Rx buffer for endpoint zero
+            iController.SetEp0RxBuffer(iEp0_RxBuf,KUsbcBufSzControl);
+            
+            // Set pil callback interface for PSL.
+            iController.SetPilCallbackInterface(*this);
+            
+            }
+        else
+            {
+            return KErrNoMemory;
+            }
+        }
+    
+    // Register ourself as the ONLY one client of charger detection observer
+    gChargerObsever = this;
+    
+    // In case the charger detector already registered, start monitor
+    // Charger type notifications
+    if( gChargerDetector != NULL )
+        {
+        gChargerDetector->SetChargerDetectorObserver(*gChargerObsever);
+        }
+    
+    iThreadContextFinder.Enque();
+    
+    return KErrNone;
+    }
+
+// This function doesn't consider the situation of OOM.
+// Because, this function will be call during extension's entry point,
+// There is no way to start up phone successfully if anything failed anyway...
+TInt DUsbClientController::SetupEp0StateMachine()
+    {
+	// Create the state machine first
+	__ASSERT_DEBUG((iConTransferMgr == NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
+	iConTransferMgr = new DControlTransferManager(*this);
+	if(iConTransferMgr == 0)
+		{
+		return KErrNoMemory;
+		}
+		
+    // Add UsbShai::EControlTransferStageSetup stage machine
+    TControlStageSm* stageSm = new DSetupStageSm(*iConTransferMgr);    
+    __ASSERT_DEBUG((stageSm != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
+    if(stageSm != NULL)
+        {
+        iConTransferMgr->AddState(UsbShai::EControlTransferStageSetup,*stageSm);
+        }
+    else
+        {
+        return KErrNoMemory;
+        }
+        
+    // Add EControlTransferStageDataOut stage state machine        
+    stageSm = new DDataOutStageSm(*iConTransferMgr);
+    __ASSERT_DEBUG((stageSm != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
+    if(stageSm != NULL)
+        {
+        iConTransferMgr->AddState(UsbShai::EControlTransferStageDataOut,*stageSm);
+        }
+    else
+        {
+        // we don't need bother to delete the previous allocated memory
+        // system can not bootup if we return error
+        return KErrNoMemory;
+        }
+        
+    // Add EControlTransferStageStatusIn stage state machine     
+    stageSm = new DStatusInStageSm(*iConTransferMgr);
+    __ASSERT_DEBUG((stageSm != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
+    if(stageSm != NULL)
+        {
+        iConTransferMgr->AddState(UsbShai::EControlTransferStageStatusIn,*stageSm); 
+        }
+    else
+        {
+        return KErrNoMemory;
+        }
+            
+    // Add EControlTransferStageDataIn stage state machine    
+    stageSm = new DDataInStageSm(*iConTransferMgr);
+    __ASSERT_DEBUG((stageSm != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
+   if(stageSm != NULL)
+        {
+        iConTransferMgr->AddState(UsbShai::EControlTransferStageDataIn,*stageSm);
+        }
+    else
+        {
+        return KErrNoMemory;
+        }
+    
+    // Add EControlTransferStageStatusOut stage state machine    
+    stageSm = new DStatusOutStageSm(*iConTransferMgr);
+    __ASSERT_DEBUG((stageSm != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
+    if(stageSm != NULL)
+        {
+        iConTransferMgr->AddState(UsbShai::EControlTransferStageStatusOut,*stageSm);
+        }    
+    else
+        {
+        return KErrNoMemory;
+        }
+        
+    return KErrNone;
+    }
+    
+// ---------------------------------------------------------------------------
+// From MUsbPeripheralPilCallbackIf.
+// Enable the peripheral stack
+// ---------------------------------------------------------------------------
+//
+void DUsbClientController::EnablePeripheralStack()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EnablePeripheralStack"));
+
+    if (iStackIsActive)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Already enabled - returning"));
+        return;
+        }
+
+    // Mark stack is enabled, Waiting upper application to power controller
+    // Anyway, this will lead us to attached state
+    iStackIsActive = ETrue;    
+    NextDeviceState(UsbShai::EUsbPeripheralStateAttached);
+    
+    // If hardware is not activated yet, do it here.
+    if(iClientSupportReady && !iHardwareActivated)
+        {
+        // PowerUpUdc only do Activating Hardware when there are at least 1
+        // Iterface registered.
+        PowerUpUdc();
+        }
+    
+    }
+
+
+// ---------------------------------------------------------------------------
+// From MUsbPeripheralPilCallbackIf.
+// Disable the peripheral stack
+// ---------------------------------------------------------------------------
+//
+void DUsbClientController::DisablePeripheralStack()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DisablePeripheralStack"));
+
+    if (!iStackIsActive)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Already disabled - returning"));
+        return;
+        }
+
+    // Reset OTG features, leave attributes as is (just as in USB Reset case)
+    // (OTG spec 1.3 sections 6.5.x all say "... on a bus reset or at the end
+    //  of a session." VBus drop is the end of a session.)
+    iOtgFuncMap &= KUsbOtgAttr_SrpSupp | KUsbOtgAttr_HnpSupp;
+    OtgFeaturesNotify();
+    // Tear down the current configuration (if any)
+    ChangeConfiguration(0);
+
+    if (iDeviceState != UsbShai::EUsbPeripheralStateUndefined)
+        {
+        // Not being in state UNDEFINED implies that the cable is inserted.
+        if (iHardwareActivated)
+            {
+            NextDeviceState(UsbShai::EUsbPeripheralStatePowered);
+            }
+        // (If the hardware is NOT activated at this point, we can only be in
+        //    state UsbShai::EUsbPeripheralStateAttached, so we don't have to move to it.)
+        }
+    DeActivateHardwareController();                     // turn off UDC altogether
+    iStackIsActive = EFalse;
+    // Notify registered clients on the user side about a USB device state
+    // change event and a transition to the "Undefined" state.
+    // Note: the state should be changed to "Undefined" before calling RunClientCallbacks(), 
+    //       otherwise the "Undefined" state will probably be lost.
+    NextDeviceState(UsbShai::EUsbPeripheralStateUndefined);
+    // Complete all pending requests, returning KErrDisconnected
+    RunClientCallbacks();
+    }
+
+
+// ---------------------------------------------------------------------------
+// From MUsbPeripheralPilCallbackIf.
+// Set the OTG Observer
+// ---------------------------------------------------------------------------
+//
+void DUsbClientController::SetOtgObserver(MUsbOtgPeripheralObserverIf* aObserver)
+    {
+    iOtgObserver = aObserver;
+    }
+
+
+/** This function gets called by the PSL upon detection of either of the following events:
+    - USB Reset,
+    - USB Suspend event,
+    - USB Resume signalling,
+    - The USB cable has been attached (inserted) or detached (removed).
+
+    @param anEvent An enum denoting the event that has occured.
+
+    @return KErrArgument if the event is not recognized, otherwise KErrNone.
+
+    @publishedPartner @released
+*/
+TInt DUsbClientController::DeviceEventNotification(UsbShai::TUsbPeripheralEvent anEvent)
+    {
+    TInt err = KErrNone;
+    
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeviceEventNotification(anEvent=%d)", anEvent));
+    
+    switch (anEvent)
+        {
+        case UsbShai::EUsbEventSuspend:
+        case UsbShai::EUsbEventResume:
+        case UsbShai::EUsbEventReset:
+        case UsbShai::EUsbEventVbusRisen:
+        case UsbShai::EUsbEventVbusFallen:
+            {
+            TInt nkern_curr_ctx= NKern::CurrentContext();
+            
+            if( (nkern_curr_ctx != NKern::EInterrupt) && (nkern_curr_ctx != NKern::EIDFC))
+                {
+                // Normal context
+                __ASSERT_DEBUG((iCommonDfcQThread != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
+                if(iCommonDfcQThread == &(Kern::CurrentThread().iNThread))
+                    {
+                    // we already in the correct context, just run processes here directly.
+                    __KTRACE_OPT(KUSB, Kern::Printf("  Correct thread context"));
+                    ProcessDeviceEventNotification(anEvent);
+                    }
+                else
+                    {
+                    // we're in a normal thread, but it is not the same as the DfcQ context
+                    // passed by PSL, queue it
+                    __KTRACE_OPT(KUSB, Kern::Printf("  Incorrect thread context"));
+                    iDevEventQueue.FifoAdd(anEvent);
+                    iDeviceEventNotifyDfc.Enque();
+                    }
+                }
+            else
+                {                
+                // We're in a ISR or IDFC context
+                __KTRACE_OPT(KUSB, Kern::Printf("  ISR|IDFC context"));
+                iDevEventQueue.FifoAdd(anEvent);
+                iDeviceEventNotifyDfc.Add();
+                }
+            }
+            break;
+            
+        default:
+            err = KErrArgument;
+        }
+    
+    return err;    
+    }
+
+
+/** This function gets called by the PSL upon completion of a pending data transfer request.
+
+    This function is not to be used for endpoint zero completions (use Ep0RequestComplete instead).
+
+    @param aCallback A pointer to a data transfer request callback structure which was previously passed to
+    the PSL in a SetupReadBuffer() or SetupWriteBuffer() call.
+
+    @publishedPartner @released
+*/
+void DUsbClientController::EndpointRequestComplete(UsbShai::TUsbPeripheralRequest* aCallback)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EndpointRequestComplete(%p)", aCallback));
+    
+    TUsbcRequestCallback* cb = static_cast<TUsbcRequestCallback*>(aCallback);
+    // This function may be called by the PSL from within an ISR -- so we have
+    // to take care what we do here (and also in all functions that get called
+    // from here).
+
+    // We don't test aCallback for NULL here (and therefore risk a crash)
+    // because the PSL should never give us a NULL argument. If it does it
+    // means the PSL is buggy and ought to be fixed.
+    ProcessDataTransferDone(*cb);
+    }
+
+
+/** This function should be called by the PSL after reception of an Ep0
+    SET_FEATURE request with a feature selector of either {b_hnp_enable,
+    a_hnp_support, a_alt_hnp_support}, but only when that Setup packet is not
+    handed up to the PIL (for instance because it is auto-decoded and
+    'swallowed' by the UDC hardware).
+
+    @param aHnpState A bitmask indicating the present state of the three OTG
+    feature selectors as follows:
+
+    bit.0 == a_alt_hnp_support
+    bit.1 == a_hnp_support
+    bit.2 == b_hnp_enable
+
+    @see DUsbClientController::ProcessSetClearDevFeature()
+
+    @publishedPartner @released
+*/
+void DUsbClientController::HandleHnpRequest(TInt aHnpState)
+// This function is called by the PSL from within an ISR -- so we have to take care what we do here
+// (and also in all functions that get called from here).
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::HandleHnpRequest(%d)", aHnpState));
+
+    if (!iOtgSupport)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Request only supported on a OTG device"));
+        return;
+        }
+    if (!(iOtgFuncMap & KUsbOtgAttr_HnpSupp))
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Request only valid if OTG device supports HNP"));
+        return;
+        }
+    //    (case KUsbFeature_B_HnpEnable:)
+    if (aHnpState & 0x04)
+        {
+        iOtgFuncMap |= KUsbOtgAttr_B_HnpEnable;
+        }
+    // (case KUsbFeature_A_HnpSupport:)
+    if (aHnpState & 0x02)
+        {
+        iOtgFuncMap |= KUsbOtgAttr_A_HnpSupport;
+        }
+    // (case KUsbFeature_A_AltHnpSupport:)
+    if (aHnpState & 0x01)
+        {
+        iOtgFuncMap |= KUsbOtgAttr_A_AltHnpSupport;
+        }
+    OtgFeaturesNotify();
+    }
+
+void DUsbClientController::GetEp0RxBufferInfo(TUint8*& aBuffer, TInt& aBufferLen)
+    {
+    aBuffer = iEp0_RxBuf;
+    aBufferLen = KUsbcBufSzControl;
+    }
+    
+UsbShai::TUsbPeripheralState DUsbClientController::DeviceStatus() const
+    {
+    return iDeviceState;
+    }
+
+TBool DUsbClientController::Ep0ReceivedNonStdRequest()
+    {
+    return iEp0ReceivedNonStdRequest;
+    }
+    
+/** This function gets called by the PSL upon completion of a pending endpoint zero data transfer request.
+
+    @param aRealEndpoint Either 0 for Ep0 OUT (= Read), or 1 for Ep0 IN (= Write).
+    @param aCount The number of bytes received or transmitted, respectively.
+    @param aError The error status of the completed transfer request. Can be KErrNone if no error, KErrCancel
+    if transfer was cancelled, or KErrPrematureEnd if a premature status end was encountered.
+
+    @return KErrNone if no error during transfer completion processing, KErrGeneral if the request was a read &
+    a Setup packet was received & the recipient for that packet couldn't be found (invalid packet: Ep0 has been
+    stalled), KErrNotFound if the request was a read & the recipient for that packet (Setup or data) _was_
+    found - however no read had been set up by that recipient (this case should be used by the PSL to disable
+    the Ep0 interrupt at that point and give the LDD time to set up a new Ep0 read; once the 'missing' read
+    was set up either Ep0ReceiveProceed or Ep0ReadSetupPktProceed will be called by the PIL).
+
+    @publishedPartner @released
+*/
+TInt DUsbClientController::Ep0RequestComplete(TInt aRealEndpoint,
+                                              TInt aCount, 
+                                              TInt aError, 
+                                              UsbShai::TControlPacketType aPktType)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::Ep0RequestComplete(%d)", aRealEndpoint));
+    
+    iLastError = KErrNone;
+    
+    iConTransferMgr->Ep0RequestComplete(iEp0_RxBuf,aCount,aError,aPktType);
+    
+    __KTRACE_OPT(KUSB, Kern::Printf("    iLastError(%d)", iLastError));
+    
+    if(iEp0WritePending == EFalse)
+        {
+        iConTransferMgr->SetupEndpointZeroRead();
+        }
+        
+    __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::Ep0RequestComplete"));
+    return iLastError;
+    }    
+
+/** This function should be called by the PSL once the UDC (and thus the USB device) is in the Address state.
+
+    @publishedPartner @released
+*/
+void DUsbClientController::MoveToAddressState()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::MoveToAddressState()"));
+
+    // This function may be called by the PSL from within an ISR -- so we have
+    // to take care what we do here (and also in all functions that get called
+    // from here).
+
+    NextDeviceState(UsbShai::EUsbPeripheralStateAddress);
+    }
+
+
+TBool DUsbClientController::CreateDescriptors(TUsbPeripheralDescriptorPool& aOutput)
+    {
+    TInt errCode = KErrNone;
+    
+    // Create all the string descriptors
+    TUsbcDeviceDescriptor* deviceDesc = TUsbcDeviceDescriptor::New(
+                                                0,     // aDeviceClass, will be changed later by upper app
+                                                0,     // aDeviceSubClass, will be changed later by upper app
+                                                0,     // aDeviceProtocol, will be changed later by upper app
+                                                iControllerProperties.iMaxEp0Size  ,   // aMaxPacketSize0
+                                                KUsbVendorId,           // aVendorId
+                                                KUsbProductId ,         // aProductId
+                                                iControllerProperties.iDeviceRelease,         // aDeviceRelease
+                                                KUsbNumberOfConfiguration);// aNumConfigurations
+    __ASSERT_DEBUG( (deviceDesc != NULL), Kern::Fault( "USB PSL Out of memory, deviceDesc", __LINE__ ));    
+    
+    TUsbcConfigDescriptor* configDesc = TUsbcConfigDescriptor::New(
+                                            1,       // Only one configruation is supported current.
+                                            EFalse,  // at here, we always mark it as bus powered.
+                                            (iControllerProperties.iControllerCaps & UsbShai::KDevCapRemoteWakeupSupport)?ETrue:EFalse,  // remote wakeup
+                                            100);    // 100 is a default value, thise value will be changed by
+    
+    __ASSERT_DEBUG( (configDesc != NULL), Kern::Fault( "USB PSL Out of memory, configDesc", __LINE__ ));
+        
+    TUsbcLangIdDescriptor* stringDescLang = TUsbcLangIdDescriptor::New(KUsbLangId);
+    __ASSERT_DEBUG( (stringDescLang != NULL), Kern::Fault( "USB PSL Out of memory, stringDescLang", __LINE__ ));
+    
+    // Default manufacturer string
+    TPtrC8 aString;
+    aString.Set(reinterpret_cast<const TUint8*>(KStringManufacturer), sizeof(KStringManufacturer) - 2);
+    TUsbcStringDescriptor* stringDescManu = TUsbcStringDescriptor::New(aString);
+    __ASSERT_DEBUG( (stringDescManu != NULL), Kern::Fault( "USB PSL Out of memory, stringDescManu", __LINE__ ));
+    
+    // Default product name string
+    aString.Set(reinterpret_cast<const TUint8*>(KStringProduct), sizeof(KStringProduct) - 2);
+    TUsbcStringDescriptor* stringDescProd = TUsbcStringDescriptor::New(aString);
+    __ASSERT_DEBUG( (stringDescProd != NULL), Kern::Fault( "USB PSL Out of memory, stringDescProd", __LINE__ ));
+    
+    // Default configuration name string
+    aString.Set(reinterpret_cast<const TUint8*>(KStringConfig), sizeof(KStringConfig) - 2);
+    TUsbcStringDescriptor* stringDescConf = TUsbcStringDescriptor::New(aString);
+    __ASSERT_DEBUG( (stringDescConf != NULL), Kern::Fault( "USB PSL Out of memory, stringDescConf", __LINE__ ));
+    
+    // Default serial bumber string
+    aString.Set(reinterpret_cast<const TUint8*>(KStringSerial), sizeof(KStringSerial) - 2);
+    TUsbcStringDescriptor* stringSerial = TUsbcStringDescriptor::New(aString);
+    __ASSERT_DEBUG( (stringSerial != NULL), Kern::Fault( "USB PSL Out of memory, stringDescConf", __LINE__ ));
+   
+    TUsbcOtgDescriptor* otgDesc = NULL;
+
+    // In an OTG-environment, we also need to create the OTG
+    // descriptor. The PSL supports both HNP and SRP and hence we
+    // report support for them. Upper layers will override the
+    // descriptors anyway.
+    if (iIsOtgPort)
+        {
+        TBool srpSupported = (iControllerProperties.iControllerCaps & UsbShai::KDevCapSrpSupport)?ETrue:EFalse;
+        TBool hnpSupported = (iControllerProperties.iControllerCaps & UsbShai::KDevCapHnpSupport)?ETrue:EFalse;
+        
+        otgDesc = TUsbcOtgDescriptor::New(srpSupported,
+                                          hnpSupported);
+        
+        __ASSERT_DEBUG( (otgDesc != NULL), Kern::Fault( "USB PSL Out of memory, otgDesc", __LINE__ ));     
+        }
+    
+    if( (deviceDesc != NULL) && 
+        (configDesc != NULL) && 
+        (stringDescLang != NULL) &&
+        (stringDescManu != NULL) && 
+        (stringDescProd != NULL) && 
+        (stringDescConf != NULL) &&
+        ((!iIsOtgPort) || (iIsOtgPort && (otgDesc != NULL))))
+        {    
+        aOutput.iDeviceDesc = deviceDesc;
+        aOutput.iConfigDesc = configDesc;
+        aOutput.iLangId = stringDescLang;
+        aOutput.iManufacturer = stringDescManu;
+        aOutput.iProduct = stringDescProd;
+        aOutput.iConfig = stringDescConf;
+        aOutput.iSerialNum = stringSerial;
+        aOutput.iOtgDesc = otgDesc;
+        }
+    else
+        {
+        if( deviceDesc != NULL )
+            {
+            delete deviceDesc;
+            }
+        
+        if( configDesc != NULL )
+            {
+            delete configDesc;
+            }
+            
+        if( stringDescLang != NULL )
+            {
+            delete stringDescLang;
+            }
+            
+        if( stringDescManu != NULL )
+            {
+            delete stringDescManu;
+            }
+            
+        if( stringDescProd != NULL )
+            {
+            delete stringDescProd;
+            }
+            
+        if( stringDescConf != NULL )
+            {
+            delete stringDescConf;
+            }
+            
+        if( stringSerial != NULL )
+            {
+            delete stringSerial;
+            }
+            
+        if( otgDesc != NULL )
+            {
+            delete otgDesc;
+            }
+        
+        errCode = KErrNoMemory;
+        }
+    
+    // We don't support serial number 
+    aOutput.iSerialNum = NULL;
+    
+    return errCode;    
+    }
+    
+//
+// === USB Controller member function implementations - Internal utility functions (private) =======
+//
+
+TInt DUsbClientController::DeRegisterClientCallback(const DBase* aClientId)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterClientCallback()"));
+    __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
+    TSglQueIter<TUsbcClientCallback> iter(iClientCallbacks);
+    TUsbcClientCallback* p;
+    while ((p = iter++) != NULL)
+        if (p->Owner() == aClientId)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  removing ClientCallback @ 0x%x", p));
+            iClientCallbacks.Remove(*p);
+            return KErrNone;
+            }
+    __KTRACE_OPT(KUSB, Kern::Printf("  Client not found"));
+    return KErrNotFound;
+    }
+
+
+TBool DUsbClientController::CheckEpAvailability(TInt aEndpointsUsed,
+                                                const TUsbcEndpointInfoArray& aEndpointData,
+                                                TInt aIfcNumber) const
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CheckEpAvailability()"));
+    if (aEndpointsUsed > KMaxEndpointsPerClient)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: too many endpoints claimed (%d)", aEndpointsUsed));
+        return EFalse;
+        }
+    TBool reserve[KUsbcEpArraySize]; // iDeviceTotalEndpoints can be equal to 32
+    memset(reserve, EFalse, sizeof(reserve));                // reset the array
+    for (TInt i = 0; i < aEndpointsUsed; ++i)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  checking for (user) endpoint #%d availability...", i + 1));
+        TInt j = 2;
+        while (j < iDeviceTotalEndpoints)
+            {
+            if ((iRealEndpoints[j].EndpointSuitable(&aEndpointData[i], aIfcNumber)) &&
+                (reserve[j] == EFalse))
+                {
+                __KTRACE_OPT(KUSB, Kern::Printf("  ---> found suitable endpoint: RealEndpoint #%d", j));
+                reserve[j] = ETrue;                            // found one: mark this ep as reserved
+                break;
+                }
+            __KTRACE_OPT(KUSB, Kern::Printf("  -> endpoint not suitable: RealEndpoint #%d", j));
+            j++;
+            }
+        if (j == iDeviceTotalEndpoints)
+            {
+            return EFalse;
+            }
+        }
+    return ETrue;
+    }
+
+
+TUsbcInterface* DUsbClientController::CreateInterface(const DBase* aClientId, TInt aIfc, TUint32 aFeatureWord)
+// We know that 9.2.3 says: "Interfaces are numbered from zero to one less than the number of
+// concurrent interfaces supported by the configuration."  But since we permit the user to
+// change interface numbers, we can neither assume nor enforce anything about them here.
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CreateInterface(x, aIfc=%d)", aIfc));
+    TUsbcInterfaceSet* ifcset_ptr = NULL;
+    TInt ifcset = ClientId2InterfaceNumber(aClientId);
+    TBool new_ifc;
+    if (ifcset < 0)
+        {
+        // New interface(set), so we need to find a number for it.
+        new_ifc = ETrue;
+        const TInt num_ifcsets = iConfigs[0]->iInterfaceSets.Count();
+        if (num_ifcsets == 255)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Too many interfaces already exist: 255"));
+            return NULL;
+            }
+        // Find the smallest interface number that has not yet been used.
+        for (ifcset = 0; ifcset < 256; ++ifcset)
+            {
+            TBool n_used = EFalse;
+            for (TInt i = 0; i < num_ifcsets; ++i)
+                {
+                if ((iConfigs[0]->iInterfaceSets[i]->iInterfaceNumber) == ifcset)
+                    {
+                    __KTRACE_OPT(KUSB, Kern::Printf("  interface number %d already used", ifcset));
+                    n_used = ETrue;
+                    break;
+                    }
+                }
+            if (!n_used)
+                {
+                break;
+                }
+            }
+        if (ifcset == 256)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: no available interface number found"));
+            return NULL;
+            }
+        // append the ifcset
+        __KTRACE_OPT(KUSB, Kern::Printf("  creating new InterfaceSet %d first", ifcset));
+        if (aIfc != 0)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: invalid interface setting number (1): %d", aIfc));
+            return NULL;
+            }
+        if ((ifcset_ptr = new TUsbcInterfaceSet(aClientId, ifcset)) == NULL)
+            {
+            __KTRACE_OPT(KPANIC,
+                         Kern::Printf("  Error: new TUsbcInterfaceSet(aClientId, ifcset_num) failed"));
+            return NULL;
+            }
+        iConfigs[0]->iInterfaceSets.Append(ifcset_ptr);
+        }
+    else /* if (ifcset_num >= 0) */
+        {
+        // use an existent ifcset
+        new_ifc = EFalse;
+        __KTRACE_OPT(KUSB, Kern::Printf("  using existing InterfaceSet %d", ifcset));
+        ifcset_ptr = InterfaceNumber2InterfacePointer(ifcset);
+        if (aIfc != ifcset_ptr->iInterfaces.Count())
+            {
+            // 9.2.3: "Alternate settings range from zero to one less than the number of alternate
+            // settings for a specific interface." (Thus we can here only append a setting.)
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: invalid interface setting number (2): %d", aIfc));
+            return NULL;
+            }
+        // Check whether the existing interface belongs indeed to this client
+        if (ifcset_ptr->iClientId != aClientId)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: iClientId (%p) != aClientId (%p)",
+                                              ifcset_ptr->iClientId, aClientId));
+            return NULL;
+            }
+        }
+    const TBool no_ep0_requests = aFeatureWord & KUsbcInterfaceInfo_NoEp0RequestsPlease;
+    TUsbcInterface* const ifc_ptr = new TUsbcInterface(ifcset_ptr, aIfc, no_ep0_requests);
+    if (!ifc_ptr)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: new TUsbcInterface(ifcset, aIfc) failed"));
+        if (new_ifc)
+            {
+            DeleteInterfaceSet(ifcset);
+            }
+        return NULL;
+        }
+    ifcset_ptr->iInterfaces.Append(ifc_ptr);
+    return ifc_ptr;
+    }
+
+
+#define RESET_SETTINGRESERVE \
+    for (TInt i = start_ep; i < iDeviceTotalEndpoints; i++) \
+        { \
+        if (iRealEndpoints[i].iSettingReserve) \
+            iRealEndpoints[i].iSettingReserve = EFalse; \
+        } \
+
+TInt DUsbClientController::CreateEndpoints(TUsbcInterface* aIfc, TInt aEndpointsUsed,
+                                           const TUsbcEndpointInfoArray& aEndpointData,
+                                           TInt aRealEpNumbers[])
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CreateEndpoints()"));
+    const TInt ifc_num = aIfc->iInterfaceSet->iInterfaceNumber;
+    const TInt start_ep = 2;
+    for (TInt i = 0; i < aEndpointsUsed; ++i)
+        {
+        for (TInt j = start_ep; j < iDeviceTotalEndpoints; ++j)
+            {
+            if (iRealEndpoints[j].EndpointSuitable(&aEndpointData[i], ifc_num))
+                {
+                // Logical endpoints are numbered 1..KMaxEndpointsPerClient (virtual 0 is real 0 and 1)
+                TUsbcLogicalEndpoint* const ep = new TUsbcLogicalEndpoint(this, i + 1, aEndpointData[i],
+                                                                          aIfc, &iRealEndpoints[j]);
+                if (!ep)
+                    {
+                    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: new TUsbcLogicalEndpoint() failed"));
+                    aIfc->iEndpoints.ResetAndDestroy();
+                    RESET_SETTINGRESERVE;
+                    return KErrNoMemory;
+                    }
+                aIfc->iEndpoints.Append(ep);
+                // Check on logical endpoint's sizes for compliance with special restrictions.
+                if (aIfc->iSettingCode == 0)
+                    {
+                    // For details see last paragraph of 5.7.3 "Interrupt Transfer Packet Size Constraints".
+                    if ((ep->iInfo.iType == UsbShai::KUsbEpTypeInterrupt) && (ep->iEpSize_Hs > 64))
+                        {
+                        __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: INT ep HS size = %d on default ifc setting",
+                                                          ep->iEpSize_Hs));
+                        __KTRACE_OPT(KPANIC, Kern::Printf("           (should be <= 64)"));
+                        }
+                    // For details see last paragraph of 5.6.3 "Isochronous Transfer Packet Size Constraints".
+                    else if ((ep->iInfo.iType == UsbShai::KUsbEpTypeIsochronous) && (ep->iInfo.iSize > 0))
+                        {
+                        __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: ISO ep size = %d on default ifc setting",
+                                                          ep->iInfo.iSize));
+                        __KTRACE_OPT(KPANIC, Kern::Printf("           (should be zero or ep non-existent)"));
+                        }
+                    }
+                // If the endpoint doesn't support DMA (now or never) the next operation
+                // will be a successful no-op.
+                /*
+                const TInt r = OpenDmaChannel(j);
+                if (r != KErrNone)
+                    {
+                    __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Opening of DMA channel failed"));
+                    aIfc->iEndpoints.ResetAndDestroy();
+                    RESET_SETTINGRESERVE;
+                    return r;
+                    }
+                */
+                __KTRACE_OPT(KUSB, Kern::Printf("  creating ep: mapping real ep %d -> logical ep %d",
+                                                j, i + 1));
+                iRealEndpoints[j].iIfcNumber = &aIfc->iInterfaceSet->iInterfaceNumber;
+                iRealEndpoints[j].iSettingReserve = ETrue;
+                __KTRACE_OPT(KUSB,
+                             Kern::Printf("  ep->iInfo: iType=0x%x iDir=0x%x iSize=%d iInterval=%d",
+                                          ep->iInfo.iType, ep->iInfo.iDir, ep->iInfo.iSize,
+                                          ep->iInfo.iInterval));
+                __KTRACE_OPT(KUSB,
+                             Kern::Printf("  ep->iInfo: iInterval_Hs=%d iTransactions=%d iExtra=%d",
+                                          ep->iInfo.iInterval_Hs, ep->iInfo.iTransactions,
+                                          ep->iInfo.iExtra));
+                // Store real endpoint numbers:
+                // array[x] holds the number for logical ep x.
+                aRealEpNumbers[i + 1] = j;
+                break;
+                }
+            }
+        }
+    aRealEpNumbers[0] = 0;                                // ep0: 0.
+    __KTRACE_OPT(KUSB,{
+        Kern::Printf("  Endpoint Mapping for Interface %d / Setting %d:", ifc_num, aIfc->iSettingCode);
+        Kern::Printf("Logical  | Real");
+        Kern::Printf("Endpoint | Endpoint");
+        for (TInt ep = 0; ep <= aEndpointsUsed; ++ep) Kern::Printf("   %2d       %3d",ep, aRealEpNumbers[ep]);
+        });
+    RESET_SETTINGRESERVE;
+    return KErrNone;
+    }
+
+
+TInt DUsbClientController::SetupIfcDescriptor(TUsbcInterface* aIfc, TUsbcClassInfo& aClass, DThread* aThread,
+                                              TDesC8* aString, const TUsbcEndpointInfoArray& aEndpointData)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetupIfcDescriptor()"));
+
+    // Interface descriptor
+    TUsbcDescriptorBase* d = TUsbcInterfaceDescriptor::New(aIfc->iInterfaceSet->iInterfaceNumber,
+                                                           aIfc->iSettingCode,
+                                                           aIfc->iEndpoints.Count(),
+                                                           aClass);
+    if (!d)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for ifc desc failed."));
+        return KErrNoMemory;
+        }
+    iDescriptors.InsertDescriptor(d);
+
+    // Interface string descriptor
+    if (aString)
+        {
+        // we don't know the length of the string, so we have to allocate memory dynamically
+        TUint strlen = Kern::ThreadGetDesLength(aThread, aString);
+        if (strlen > KUsbStringDescStringMaxSize)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Warning: $ descriptor too long - string will be truncated"));
+            strlen = KUsbStringDescStringMaxSize;
+            }
+        HBuf8* const stringbuf = HBuf8::New(strlen);
+        if (!stringbuf)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for ifc $ desc string failed."));
+            iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber,
+                                             aIfc->iSettingCode);
+            return KErrNoMemory;
+            }
+        stringbuf->SetMax();
+        // the aString points to data that lives in user memory, so we have to copy it:
+        TInt r = Kern::ThreadDesRead(aThread, aString, *stringbuf, 0);
+        if (r != KErrNone)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Thread read error"));
+            iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber,
+                                             aIfc->iSettingCode);
+            delete stringbuf;
+            return r;
+            }
+        TUsbcStringDescriptor* const sd = TUsbcStringDescriptor::New(*stringbuf);
+        if (!sd)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for ifc $ desc failed."));
+            iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber,
+                                             aIfc->iSettingCode);
+            delete stringbuf;
+            return KErrNoMemory;
+            }
+        iDescriptors.SetIfcStringDescriptor(sd, aIfc->iInterfaceSet->iInterfaceNumber, aIfc->iSettingCode);
+        delete stringbuf;                                    // the (EPOC) descriptor was copied by New()
+        }
+
+    // Endpoint descriptors
+    for (TInt i = 0; i < aIfc->iEndpoints.Count(); ++i)
+        {
+        // The reason for using another function argument for Endpoint Info
+        // (and not possibly - similar to the Endpoint Address -
+        // "aIfc->iEndpoints[i]->iPEndpoint->iLEndpoint->iInfo") is that this time
+        // there are no logical endpoints associated with our real endpoints,
+        // i.e. iLEndpoint is NULL!.
+        if (aEndpointData[i].iExtra)
+            {
+            // if a non-standard endpoint descriptor is requested...
+            if (aEndpointData[i].iExtra != 2)
+                {
+                // ...then it must be a Audio Class endpoint descriptor. Else...
+                __KTRACE_OPT(KPANIC, Kern::Printf("  Error: EP desc extension > 2 bytes (%d)",
+                                                  aEndpointData[i].iExtra));
+                iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber,
+                                                 aIfc->iSettingCode);
+                return KErrArgument;
+                }
+            d = TUsbcAudioEndpointDescriptor::New(aIfc->iEndpoints[i]->iPEndpoint->iEndpointAddr,
+                                                  aEndpointData[i]);
+            }
+        else
+            {
+            d = TUsbcEndpointDescriptor::New(aIfc->iEndpoints[i]->iPEndpoint->iEndpointAddr,
+                                             aEndpointData[i]);
+            }
+        if (!d)
+            {
+            __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for ep desc #%d failed.", i));
+            iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber,
+                                             aIfc->iSettingCode);
+            return KErrNoMemory;
+            }
+        iDescriptors.InsertDescriptor(d);
+        }
+
+    return KErrNone;
+    }
+
+
+TInt DUsbClientController::ClientId2InterfaceNumber(const DBase* aClientId) const
+    {
+    const TInt num_ifcsets = iConfigs[0]->iInterfaceSets.Count();
+    for (TInt i = 0; i < num_ifcsets; ++i)
+        {
+        if (iConfigs[0]->iInterfaceSets[i]->iClientId == aClientId)
+            {
+            return iConfigs[0]->iInterfaceSets[i]->iInterfaceNumber;
+            }
+        }
+    return -1;
+    }
+
+
+TUsbcInterfaceSet* DUsbClientController::ClientId2InterfacePointer(const DBase* aClientId) const
+    {
+    const TInt num_ifcsets = iConfigs[0]->iInterfaceSets.Count();
+    for (TInt i = 0; i < num_ifcsets; ++i)
+        {
+        if (iConfigs[0]->iInterfaceSets[i]->iClientId == aClientId)
+            {
+            return iConfigs[0]->iInterfaceSets[i];
+            }
+        }
+    return NULL;
+    }
+
+
+const DBase* DUsbClientController::InterfaceNumber2ClientId(TInt aIfcSet) const
+    {
+    if (!InterfaceExists(aIfcSet))
+        {
+        return NULL;
+        }
+    return InterfaceNumber2InterfacePointer(aIfcSet)->iClientId;
+    }
+
+
+TUsbcInterfaceSet* DUsbClientController::InterfaceNumber2InterfacePointer(TInt aIfcSet) const
+    {
+    const TInt num_ifcsets = iConfigs[0]->iInterfaceSets.Count();
+    for (TInt i = 0; i < num_ifcsets; ++i)
+        {
+        if ((iConfigs[0]->iInterfaceSets[i]->iInterfaceNumber) == aIfcSet)
+            {
+            return iConfigs[0]->iInterfaceSets[i];
+            }
+        }
+    return NULL;
+    }
+
+
+TInt DUsbClientController::ActivateHardwareController()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::ActivateHardwareController()"));
+    
+    // iStackIsActive must be ETrue at this time
+    // the caller of this function shall checked that iStackIsActive is ETrue
+    __ASSERT_DEBUG(iStackIsActive, Kern::Fault(KUsbPILPanicCat, __LINE__));   
+    
+    if (iHardwareActivated)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  already active -> returning"));
+        return KErrNone;
+        }
+    // Initialise HW
+    TInt r = iController.StartPeripheralController();
+    if (r != KErrNone)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: StartPeripheralController() failed"));
+        return KErrHardwareNotAvailable;
+        }
+    
+    iHardwareActivated = ETrue;
+
+    // Configure & enable endpoint zero
+    const TUsbcLogicalEndpoint* const ep0_0 = iRealEndpoints[0].iLEndpoint;
+    const TUsbcLogicalEndpoint* const ep0_1 = iRealEndpoints[1].iLEndpoint;
+    if (iHighSpeed)
+        {
+        const_cast<TUsbcLogicalEndpoint*>(ep0_0)->iInfo.iSize = ep0_0->iEpSize_Hs;
+        const_cast<TUsbcLogicalEndpoint*>(ep0_1)->iInfo.iSize = ep0_1->iEpSize_Hs;
+        }
+    else
+        {
+        const_cast<TUsbcLogicalEndpoint*>(ep0_0)->iInfo.iSize = ep0_0->iEpSize_Fs;
+        const_cast<TUsbcLogicalEndpoint*>(ep0_1)->iInfo.iSize = ep0_1->iEpSize_Fs;
+        }
+    iController.ConfigureEndpoint(0, ep0_0->iInfo);
+    iController.ConfigureEndpoint(1, ep0_1->iInfo);
+    iEp0MaxPacketSize = ep0_0->iInfo.iSize;
+
+    __KTRACE_OPT(KUSB, Kern::Printf("  Controller activated."));
+    
+    // Controller is powered up, changes device state to powered
+    NextDeviceState(UsbShai::EUsbPeripheralStatePowered);
+    
+    __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::ActivateHardwareController()"));
+    return  KErrNone;;
+    }
+
+
+void DUsbClientController::DeActivateHardwareController()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeActivateHardwareController()"));
+    if (!iHardwareActivated)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  not active -> returning"));
+        return;
+        }
+    // Deconfigure & disable endpoint zero
+    iController.DeConfigureEndpoint(KEp0_Out);
+    iController.DeConfigureEndpoint(KEp0_In);
+    // Stop HW
+    iController.StopPeripheralController();
+    iHardwareActivated = EFalse;
+    __KTRACE_OPT(KUSB, Kern::Printf("  Controller deactivated."));
+    
+    // Always go to attached state, until statck is disabled
+    NextDeviceState(UsbShai::EUsbPeripheralStateAttached);
+    
+    return;
+    }
+
+
+void DUsbClientController::DeleteInterfaceSet(TInt aIfcSet)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteInterfaceSet(%d)", aIfcSet));
+    TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(aIfcSet);
+    if (!ifcset_ptr)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: invalid interface number: %d", aIfcSet));
+        return;
+        }
+    const TInt idx = iConfigs[0]->iInterfaceSets.Find(ifcset_ptr);
+    if (idx == KErrNotFound)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: interface not found in array"));
+        return;
+        }
+    //Add this mutex to protect the interface set data structure
+    if (NKern::CurrentContext() == EThread)
+        {
+        NKern::FMWait(&iMutex);
+        }
+    
+    iConfigs[0]->iInterfaceSets.Remove(idx);
+    if (NKern::CurrentContext() == EThread)
+        {
+        NKern::FMSignal(&iMutex);    
+        }
+    delete ifcset_ptr;
+    }
+
+
+void DUsbClientController::DeleteInterface(TInt aIfcSet, TInt aIfc)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteInterface(%d, %d)", aIfcSet, aIfc));
+    TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(aIfcSet);
+    if (!ifcset_ptr)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: invalid interface number: %d", aIfcSet));
+        return;
+        }
+    if (ifcset_ptr->iInterfaces.Count() <= aIfc)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: invalid interface setting: %d", aIfc));
+        return;
+        }
+    //Add this mutex to protect the interface set data structure
+    if (NKern::CurrentContext() == EThread)
+        {
+        NKern::FMWait(&iMutex);
+        }    
+    TUsbcInterface* const ifc_ptr = ifcset_ptr->iInterfaces[aIfc];
+    // Always first remove, then delete (see ~TUsbcLogicalEndpoint() for the reason why)
+    ifcset_ptr->iInterfaces.Remove(aIfc);
+
+    if (aIfc == ifcset_ptr->iCurrentInterface)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf(" > Warning: deleting current interface setting"));
+        ifcset_ptr->iCurrentInterface = 0;
+        }
+    if (NKern::CurrentContext() == EThread)
+        {
+        NKern::FMSignal(&iMutex);
+        }    
+    delete ifc_ptr;
+    }
+
+
+void DUsbClientController::CancelTransferRequests(TInt aRealEndpoint)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CancelTransferRequests(aRealEndpoint=%d)",
+                                    aRealEndpoint));
+    const DBase* const clientId = PEndpoint2ClientId(aRealEndpoint);
+    if (EpIdx2Addr(aRealEndpoint) & KUsbEpAddress_In)
+        {
+        CancelWriteBuffer(clientId, aRealEndpoint);
+        }
+    else
+        {
+        CancelReadBuffer(clientId, aRealEndpoint);
+        }
+    }
+
+
+void DUsbClientController::DeleteRequestCallback(const DBase* aClientId, TInt aEndpointNum,
+                                                 UsbShai::TTransferDirection aTransferDir)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteRequestCallback()"));
+    // Ep0 OUT
+    if (aEndpointNum == 0)
+        {
+        const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
+        TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks);
+        TUsbcRequestCallback* p;
+        while ((p = iter++) != NULL)
+            {
+            if (p->Owner() == aClientId)
+                {
+                __ASSERT_DEBUG((p->iRealEpNum == 0), Kern::Fault(KUsbPILPanicCat, __LINE__));
+                __ASSERT_DEBUG((p->iTransferDir == UsbShai::EControllerRead), Kern::Fault(KUsbPILPanicCat, __LINE__));
+                __KTRACE_OPT(KUSB, Kern::Printf("  removing RequestCallback @ 0x%x (ep0)", p));
+                iEp0ReadRequestCallbacks.Remove(*p);
+                }
+            }
+        __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+        return;
+        }
+    // Other endpoints
+    TUsbcRequestCallback* const p = iRequestCallbacks[aEndpointNum];
+    if (p)
+        {
+         __ASSERT_DEBUG((p->Owner() == aClientId), Kern::Fault(KUsbPILPanicCat, __LINE__));
+        __ASSERT_DEBUG((p->iTransferDir == aTransferDir), Kern::Fault(KUsbPILPanicCat, __LINE__));
+        __KTRACE_OPT(KUSB, Kern::Printf("  removing RequestCallback @ 0x%x", p));
+        iRequestCallbacks[aEndpointNum] = NULL;
+        }
+    }
+
+
+void DUsbClientController::DeleteRequestCallbacks(const DBase* aClientId)
+    {
+    // aClientId being NULL means: delete all requests for *all* clients.
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteRequestCallbacks()"));
+    // Ep0 OUT
+    const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
+    TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks);
+    TUsbcRequestCallback* p;
+    while ((p = iter++) != NULL)
+        {
+        if (!aClientId || p->Owner() == aClientId)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  removing RequestCallback @ 0x%x (ep0)", p));
+            iEp0ReadRequestCallbacks.Remove(*p);
+            }
+        }
+    __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+    // Other endpoints
+    for (TInt i = 1; i < KUsbcEpArraySize; i++)
+        {
+        TUsbcRequestCallback* const p = iRequestCallbacks[i];
+        if (p && (!aClientId || p->Owner() == aClientId))
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  removing RequestCallback @ 0x%x", p));
+            iRequestCallbacks[i] = NULL;
+            }
+        }
+    }
+
+
+void DUsbClientController::StatusNotify(UsbShai::TUsbPeripheralState aState, const DBase* aClientId)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::StatusNotify()"));
+
+    // This function may be called by the PSL (via chapter9.cpp) from within an
+    // ISR -- so we have to take care what we do here (and also in all
+    // functions that get called from here).
+
+    TSglQueIter<TUsbcStatusCallback> iter(iStatusCallbacks);
+    TUsbcStatusCallback* p;
+    while ((p = iter++) != NULL)
+        {
+        if (!aClientId || aClientId == p->Owner())
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  notifying LDD @ 0x%x about %d", p->Owner(), aState));
+            p->SetState(aState);
+            p->DoCallback();
+            }
+        }
+    }
+
+
+void DUsbClientController::EpStatusNotify(TInt aRealEndpoint)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EpStatusNotify()"));
+
+    // This function may be called by the PSL (via chapter9.cpp) from within an
+    // ISR -- so we have to take care what we do here (and also in all
+    // functions that get called from here).
+
+    const DBase* const client_id = PEndpoint2ClientId(aRealEndpoint);
+    if (!client_id)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Client not found for real ep %d", aRealEndpoint));
+        return;
+        }
+    // Check if there is a notification request queued for that client (if not, we can return here).
+    TSglQueIter<TUsbcEndpointStatusCallback> iter(iEpStatusCallbacks);
+    TUsbcEndpointStatusCallback* p;
+    while ((p = iter++) != NULL)
+        {
+        if (p->Owner() == client_id)
+            {
+            break;
+            }
+        }
+    if (!p)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  No notification request for that client, returning"));
+        return;
+        }
+    const TInt ifcset = ClientId2InterfaceNumber(client_id);
+    if (ifcset < 0)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Ifcset not found for clientid %d", client_id));
+        return;
+        }
+    const TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(ifcset);
+    if (!ifcset_ptr)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Ifcset pointer not found for ifcset %d", ifcset));
+        return;
+        }
+    const TUsbcInterface* const ifc_ptr = ifcset_ptr->CurrentInterface();
+    if (!ifc_ptr)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Current ifc pointer not found for ifcset %d", ifcset));
+        return;
+        }
+    TUint state = 0;
+    const TInt eps = ifc_ptr->iEndpoints.Count();
+    for (TInt i = 0; i < eps; i++)
+        {
+        const TUsbcLogicalEndpoint* const ep_ptr = ifc_ptr->iEndpoints[i];
+        __KTRACE_OPT(KUSB, Kern::Printf("  checking logical ep #%d for stall state...",
+                                        ep_ptr->iLEndpointNum));
+        if (ep_ptr->iPEndpoint->iHalt)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  -- stalled"));
+            // set the bit n to 1, where n is the logical endpoint number minus one
+            state |= (1 << (ep_ptr->iLEndpointNum - 1));
+            }
+        else
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  -- not stalled"));
+            }
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf(" passing ep state 0x%x on to LDD @ 0x%x", state, client_id));
+    p->SetState(state);
+    p->DoCallback();
+    }
+
+
+void DUsbClientController::OtgFeaturesNotify()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::OtgFeaturesNotify()"));
+
+    // This function may be called from the PSL (via PIL's chapter9.cpp) from
+    // within an ISR -- so we have to take care what we do here (and also in
+    // all functions that get called from here).
+
+    TSglQueIter<TUsbcOtgFeatureCallback> iter(iOtgCallbacks);
+    TUsbcOtgFeatureCallback* p;
+    while ((p = iter++) != NULL)
+        {
+        p->SetFeatures(iOtgFuncMap & 0x1C);
+        p->DoCallback();
+        }
+    }
+
+
+void DUsbClientController::RunClientCallbacks()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RunClientCallbacks()"));
+    TSglQueIter<TUsbcClientCallback> iter(iClientCallbacks);
+    TUsbcClientCallback* p;
+    while ((p = iter++) != NULL)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("Callback 0x%x", p));
+        p->DoCallback();
+        }
+    }
+
+
+void DUsbClientController::ProcessDataTransferDone(TUsbcRequestCallback& aRcb)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessDataTransferDone()"));
+    // This piece can only be called in thread context from ProcessEp0DataReceived() /
+    // ProcessEp0SetupReceived() via the call to ProcessEp0ReceiveDone() in
+    // SetupReadBuffer(), which is guarded by an interrupt lock.
+    TInt ep = aRcb.iRealEpNum;
+    if (ep == 0)
+        {
+        if (aRcb.iTransferDir == UsbShai::EControllerRead)
+            {
+            // Ep0 OUT is special
+            iEp0ReadRequestCallbacks.Remove(aRcb);
+            }
+        else                                                // UsbShai::EControllerWrite
+            {
+            // Ep0 IN needs to be adjusted: it's '1' within the PIL.
+            ep = KEp0_Tx;
+            }
+        }
+    if (ep > 0)                                                // not 'else'!
+        {
+        __ASSERT_DEBUG((iRequestCallbacks[ep] == &aRcb), Kern::Fault(KUsbPILPanicCat, __LINE__));
+        __KTRACE_OPT(KUSB, Kern::Printf(" > removing RequestCallback[%d] @ 0x%x", ep, &aRcb));
+        iRequestCallbacks[ep] = NULL;
+        }
+    aRcb.DoCallback();
+    }
+
+
+void DUsbClientController::NextDeviceState(UsbShai::TUsbPeripheralState aNextState)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::NextDeviceState()"));
+#ifdef _DEBUG
+    const char* const states[] = {"Undefined", "Attached", "Powered", "Default",
+                                  "Address", "Configured", "Suspended"};
+    if ((aNextState >= UsbShai::EUsbPeripheralStateUndefined) &&
+        (aNextState <= UsbShai::EUsbPeripheralStateSuspended))
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  next device state: %s", states[aNextState]));
+        }
+    else
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Unknown next device state: %d", aNextState));
+        }
+    // Print a warning when an invalid state transition is detected
+    // 'Undefined' is not a state that is mentioned in the USB spec, but
+    // that's what we're in once the cable gets pulled (for instance).
+    switch (iDeviceState)
+        {
+    case UsbShai::EUsbPeripheralStateUndefined:
+        // valid: Undefined -> Attached
+        if (aNextState != UsbShai::EUsbPeripheralStateAttached)
+            break;
+        goto OK;
+    case UsbShai::EUsbPeripheralStateAttached:
+        // valid: Attached -> {Undefined, Powered}
+        if ((aNextState != UsbShai::EUsbPeripheralStateUndefined) &&
+            (aNextState != UsbShai::EUsbPeripheralStatePowered))
+            break;
+        goto OK;
+    case UsbShai::EUsbPeripheralStatePowered:
+        // valid: Powered -> {Undefined, Attached, Default, Suspended}
+        if ((aNextState != UsbShai::EUsbPeripheralStateUndefined) &&
+            (aNextState != UsbShai::EUsbPeripheralStateAttached) &&
+            (aNextState != UsbShai::EUsbPeripheralStateDefault)     &&
+            (aNextState != UsbShai::EUsbPeripheralStateSuspended))
+            break;
+        goto OK;
+    case UsbShai::EUsbPeripheralStateDefault:
+        // valid: Default -> {Undefined, Powered, Default, Address, Suspended}
+        if ((aNextState != UsbShai::EUsbPeripheralStateUndefined) &&
+            (aNextState != UsbShai::EUsbPeripheralStatePowered) &&
+            (aNextState != UsbShai::EUsbPeripheralStateDefault) &&
+            (aNextState != UsbShai::EUsbPeripheralStateAddress) &&
+            (aNextState != UsbShai::EUsbPeripheralStateSuspended))
+            break;
+        goto OK;
+    case UsbShai::EUsbPeripheralStateAddress:
+        // valid: Address -> {Undefined, Powered, Default, Configured, Suspended}
+        if ((aNextState != UsbShai::EUsbPeripheralStateUndefined) &&
+            (aNextState != UsbShai::EUsbPeripheralStatePowered) &&
+            (aNextState != UsbShai::EUsbPeripheralStateDefault) &&
+            (aNextState != UsbShai::EUsbPeripheralStateConfigured) &&
+            (aNextState != UsbShai::EUsbPeripheralStateSuspended))
+            break;
+        goto OK;
+    case UsbShai::EUsbPeripheralStateConfigured:
+        // valid: Configured -> {Undefined, Powered, Default, Address, Suspended}
+        if ((aNextState != UsbShai::EUsbPeripheralStateUndefined) &&
+            (aNextState != UsbShai::EUsbPeripheralStatePowered) &&
+            (aNextState != UsbShai::EUsbPeripheralStateDefault) &&
+            (aNextState != UsbShai::EUsbPeripheralStateAddress) &&
+            (aNextState != UsbShai::EUsbPeripheralStateSuspended))
+            break;
+        goto OK;
+    case UsbShai::EUsbPeripheralStateSuspended:
+        // valid: Suspended -> {Undefined, Powered, Default, Address, Configured}
+        if ((aNextState != UsbShai::EUsbPeripheralStateUndefined) &&
+            (aNextState != UsbShai::EUsbPeripheralStatePowered) &&
+            (aNextState != UsbShai::EUsbPeripheralStateDefault) &&
+            (aNextState != UsbShai::EUsbPeripheralStateAddress) &&
+            (aNextState != UsbShai::EUsbPeripheralStateConfigured))
+            break;
+        goto OK;
+    default:
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: Unknown current device state: %d", iDeviceState));
+        goto OK;
+        }
+    // KUSB only (instead of KPANIC) so as not to worry people too much where
+    // a particular h/w regularly enforces invalid (but harmless) transitions
+    __KTRACE_OPT(KUSB, Kern::Printf("  Warning: Invalid next state from %s", states[iDeviceState]));
+OK:
+#endif // _DEBUG
+
+    iDeviceState = aNextState;
+    StatusNotify(iDeviceState);
+    }
+
+
+TInt DUsbClientController::ProcessSuspendEvent()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSuspendEvent()"));
+    // A suspend interrupt has been received and needs attention.
+    iDeviceStateB4Suspend = iDeviceState;
+    
+    // We have to move to the Suspend state immediately (in case it's a genuine Suspend)
+    // because 7.1.7.6 says: "The device must actually be suspended, [...] after no more
+    // than 10ms of bus inactivity [...]." Assuming we got the interrupt 3ms after the
+    // Suspend condition arose, we have now 7ms left.
+    NextDeviceState(UsbShai::EUsbPeripheralStateSuspended);
+    iController.Suspend();
+    
+    return KErrNone;
+    }
+
+TInt DUsbClientController::ProcessResumeEvent()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessResumeEvent()"));
+    if (iDeviceState == UsbShai::EUsbPeripheralStateSuspended)
+        {
+        NextDeviceState(iDeviceStateB4Suspend);
+        }
+    iController.Resume();
+    return KErrNone;
+    }
+
+
+TInt DUsbClientController::ProcessResetEvent(TBool aPslUpcall)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessResetEvent()"));
+
+    if (aPslUpcall)
+        {
+        // Call back into PSL if we're coming from there.
+        // Also, do it always, even when PIL processing will be deferred.
+        iController.Reset();
+        }
+
+    // In an OTG-environment, some OTG controllers have implemented
+    // the OTG state machine in HW and connect to the bus
+    // automatically already before the SW has indicated
+    // readiness. Peripheral PSL operating on top of such controller
+    // may report a reset event already before the upper layers are
+    // ready. In this case we defer the reset processing to after the
+    // upper layers have indicated their readiness.
+    if (iUsbResetDeferred)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  User-side (still) not ready -> returning"));
+        return KErrNone;
+        }
+    else if (!iClientSupportReady)
+        {
+        // Wait with the PIL Reset processing until user-side is ready
+        __KTRACE_OPT(KUSB, Kern::Printf("  User-side not ready -> deferring"));
+        iUsbResetDeferred = ETrue;
+        return KErrNone;
+        }
+
+    if (iDeviceState == UsbShai::EUsbPeripheralStateAttached)
+        {
+        NextDeviceState(UsbShai::EUsbPeripheralStatePowered);
+        }
+    // Notify the world. (This will just queue a DFC, so users won't actually be
+    // notified before we return. But we change the device state already here so
+    // ChangeConfiguration will see the correct one.)
+    NextDeviceState(UsbShai::EUsbPeripheralStateDefault);
+    // Tear down the current configuration (never called from thread)
+    ChangeConfiguration(0);
+    // Reset essential vars
+    ResetEp0DataOutVars();
+    //iEp0_RxExtraData = EFalse;
+    iEp0WritePending = EFalse;
+    iEp0ClientDataTransmitting = EFalse;
+    
+    iLastError = KErrNone;
+    iSetupPacketPending = EFalse;
+    //iEp0_RxExtraError = 0;
+    iConTransferMgr->Reset();
+    
+    // Reset OTG features, leave attributes as is
+    iOtgFuncMap &= KUsbOtgAttr_SrpSupp | KUsbOtgAttr_HnpSupp;
+    if (iOtgSupport)
+        {
+        OtgFeaturesNotify();
+        }
+
+    // Check whether there's a speed change
+    const TBool was_hs = iHighSpeed;
+    iHighSpeed = CurrentlyUsingHighSpeed();
+    if (!was_hs && iHighSpeed)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Moving to High-speed"));
+        EnterHighSpeed();
+        }
+    else if (was_hs && !iHighSpeed)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Moving to Full-speed"));
+        EnterFullSpeed();
+        }
+
+    // Setup initial Ep0 read (SetupEndpointZeroRead never called from thread)
+    if (iConTransferMgr->SetupEndpointZeroRead() != KErrNone)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: while setting up Ep0 read"));
+        return KErrGeneral;
+        }
+
+    return KErrNone;
+    }
+
+
+TInt DUsbClientController::ProcessVbusRisenEvent()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessVbusRisenEvent()"));
+    if (iIsOtgPort)
+        {
+        // In an OTG environment, this notification is not expected
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: EUsbEventVbusRisen shouldn't be sent by an OTG Client PSL"));
+        return KErrArgument;
+        }
+    else
+        {
+        // In a non-OTG environment, seeing VBUS rising causes the
+        // peripheral stack to be enabled
+        EnablePeripheralStack();
+        return KErrNone;
+        }
+    }
+
+
+TInt DUsbClientController::ProcessVbusFallenEvent()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessVbusFallenEvent()"));
+    if (iIsOtgPort)
+        {
+        // In an OTG environment, this notification is not expected
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: EUsbEventVbusFallen shouldn't be sent by an OTG Client PSL"));
+        return KErrArgument;
+        }
+    else
+        {
+        // In a non-OTG environment, seeing VBUS falling causes the
+        // peripheral stack to be disabled
+        DisablePeripheralStack();
+        return KErrNone;
+        }
+    }
+
+
+void DUsbClientController::EnterFullSpeed()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EnterFullSpeed()"));
+    iDescriptors.UpdateDescriptorsFs();
+    }
+
+
+void DUsbClientController::EnterHighSpeed()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EnterHighSpeed()"));
+    iDescriptors.UpdateDescriptorsHs();
+    }
+
+
+//
+// DFC (static), we are runing in a DFC context.
+//
+void DUsbClientController::ReconnectTimerCallback(TAny *aPtr)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ReconnectTimerCallback()"));
+    if (!aPtr)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: !aPtr"));
+        return;
+        }
+    
+    DUsbClientController* const ptr = static_cast<DUsbClientController*>(aPtr);
+    
+    ptr->UsbConnect();
+    
+    }
+
+//
+// static Dfc function
+//
+void DUsbClientController::PowerUpDfc(TAny* aPtr)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::PowerUpDfc"));
+    if (!aPtr)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("     Error: !aPtr"));
+        return;
+        }
+    
+    DUsbClientController* const ptr = static_cast<DUsbClientController*>(aPtr);
+    
+    __PM_ASSERT(ptr->iStandby);
+    
+    ptr->iStandby = EFalse;
+    
+    // We have nothing to do when powerup
+    ptr->iPowerHandler->PowerUpDone();
+    
+    __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::PowerUpDfc"));
+    return ;
+    }
+
+//
+// static Dfc function
+//
+void DUsbClientController::PowerDownDfc(TAny* aPtr)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::PowerDownDfc"));
+    if (!aPtr)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("     Error: !aPtr"));
+        return;
+        }
+        
+    DUsbClientController* const ptr = static_cast<DUsbClientController*>(aPtr);
+    __PM_ASSERT(!ptr->iStandby);
+    
+    ptr->iStandby = ETrue;
+    
+    // Disable stack(stop controller inside)
+    ptr->DisablePeripheralStack();
+    
+    ptr->iPowerHandler->PowerDownDone();
+    
+    __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::PowerDownDfc"));
+    return ;
+    }
+
+//
+// Static Dfc function
+//
+void DUsbClientController::DeviceEventNotifyDfc(TAny* aPtr)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::DeviceEventNotifyDfc"));
+    DUsbClientController* const ptr = static_cast<DUsbClientController*>(aPtr);
+    
+    UsbShai::TUsbPeripheralEvent event = ptr->iDevEventQueue.FifoGet();
+    
+    if( event == -1)
+        {
+        // No event queued
+        __KTRACE_OPT(KUSB, Kern::Printf("  Warning, No event found, exit !!!"));
+        return;
+        }
+    
+    ptr->ProcessDeviceEventNotification(event);
+    __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::DeviceEventNotifyDfc"));
+    }
+
+//
+// Static Dfc function
+//    
+void DUsbClientController::ThreadContextFinderDfc(TAny* aPtr)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::ThreadContextFinderDfc"));
+
+    DUsbClientController* const ptr = static_cast<DUsbClientController*>(aPtr);
+    
+    ptr->iCommonDfcQThread = NKern::CurrentThread();
+    __KTRACE_OPT(KUSB, Kern::Printf("  iCommonDfcQThread = %d",ptr->iCommonDfcQThread));
+
+    __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::ThreadContextFinderDfc"));    
+    }
+//
+// 
+//
+void DUsbClientController::ProcessDeviceEventNotification(UsbShai::TUsbPeripheralEvent aEvent)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::ProcessDeviceEventNotification %d",aEvent));    
+    // If an OTG Observer has registered, forward the event
+    // notification to it as well
+    if (iOtgObserver != NULL)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Forwarding to OTG Observer"));
+        iOtgObserver->NotifyPeripheralEvent(aEvent);
+        }
+
+    // This function may be called by the PSL from within an ISR -- so we have
+    // to take care what we do here (and also in all functions that get called
+    // from here).
+
+    switch (aEvent)
+        {
+    case UsbShai::EUsbEventSuspend:
+        ProcessSuspendEvent();
+        break;
+    case UsbShai::EUsbEventResume:
+        ProcessResumeEvent();
+        break;
+    case UsbShai::EUsbEventReset:
+        ProcessResetEvent();
+        break;
+    case UsbShai::EUsbEventVbusRisen:
+        ProcessVbusRisenEvent();
+        break;
+    case UsbShai::EUsbEventVbusFallen:
+        ProcessVbusFallenEvent();
+        break;
+        
+    default:
+        break;
+        }
+        
+    __KTRACE_OPT(KUSB, Kern::Printf("< DUsbClientController::ProcessDeviceEventNotification"));    
+    }
+    
+// Functions from UsbShai::MChargerDetectorObserverIf
+void DUsbClientController::NotifyPortType(UsbShai::TPortType aPortType)
+    {
+    // FIXME: Not yet implemented!
+    }
+
+void DUsbClientController::Buffer2Setup(const TAny* aBuf, TUsbcSetup& aSetup) const
+	{
+	// TUint8 index
+	aSetup.iRequestType = static_cast<const TUint8*>(aBuf)[0];
+	aSetup.iRequest		= static_cast<const TUint8*>(aBuf)[1];
+	// TUint16 index from here!
+	aSetup.iValue  = SWAP_BYTES_16((static_cast<const TUint16*>(aBuf))[1]);
+	aSetup.iIndex  = SWAP_BYTES_16((static_cast<const TUint16*>(aBuf))[2]);
+	aSetup.iLength = SWAP_BYTES_16((static_cast<const TUint16*>(aBuf))[3]);
+	}
+    
+TUsbPeriDeviceEventQueue::TUsbPeriDeviceEventQueue()
+    {
+    iDeviceQueueHead = 0;
+    iDeviceQueueTail = 0;
+    }
+
+// FifoAdd will be called from Isr or IDfc context
+// be careful when processing
+void TUsbPeriDeviceEventQueue::FifoAdd(UsbShai::TUsbPeripheralEvent aDeviceEvent)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> TUsbPeriDeviceEventQueue::FifoAdd %d , %d",iDeviceQueueHead,iDeviceQueueTail));
+    iDeviceEventQueue[iDeviceQueueTail] = aDeviceEvent;
+    
+    iDeviceQueueTail ++;
+    iDeviceQueueTail %= KUsbDeviceEventQueueDepth;
+    if(iDeviceQueueTail == iDeviceQueueHead)
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("TUsbPeriDeviceEventQueue::FifoAdd overflow, oldest event missed"));
+        iDeviceQueueHead ++;
+        iDeviceQueueHead %= KUsbDeviceEventQueueDepth;
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("< TUsbPeriDeviceEventQueue::FifoAdd %d , %d",iDeviceQueueHead,iDeviceQueueTail));
+    }
+
+// FifoAdd will be called from thread context
+UsbShai::TUsbPeripheralEvent TUsbPeriDeviceEventQueue::FifoGet()
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> TUsbPeriDeviceEventQueue::FifoGet %d , %d",iDeviceQueueHead,iDeviceQueueTail));    
+    UsbShai::TUsbPeripheralEvent ret = (UsbShai::TUsbPeripheralEvent)-1;
+    
+    if(iDeviceQueueHead != iDeviceQueueTail)
+        {
+        ret = iDeviceEventQueue[iDeviceQueueHead];    
+        iDeviceQueueHead++;
+        iDeviceQueueHead %= KUsbDeviceEventQueueDepth;
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("< TUsbPeriDeviceEventQueue::FifoGet %d , %d",iDeviceQueueHead,iDeviceQueueTail));
+    return ret;
+    }
+    
+/** Sets some data members of this request for a read request.
+
+    @param aBufferStart The start of the data buffer to be filled.
+    @param aBufferAddr The physical address of the buffer (used for DMA).
+    @param aPacketIndex A pointer to the packet index values array.
+    @param aPacketSize A pointer to the packet size values array.
+    @param aLength The number of bytes to be received.
+*/
+EXPORT_C void TUsbcRequestCallback::SetRxBufferInfo(TUint8* aBufferStart, TUintPtr aBufferAddr,
+                                           TUint32* aPacketIndex,
+                                           TUint32* aPacketSize,
+                                           TInt aLength)
+    {
+    iTransferDir = UsbShai::EControllerRead;
+    iBufferStart = aBufferStart;
+    iBufferAddr = aBufferAddr;
+    iPacketIndex = aPacketIndex;
+    iPacketSize = aPacketSize;
+    iLength = aLength;
+    }
+
+
+/** Sets some data members of this request for a write request.
+
+    @param aBufferStart The start of the buffer that contains the data to be sent.
+    @param aBufferAddr The physical address of the buffer (used for DMA).
+    @param aLength The number of bytes to be transmitted.
+*/
+EXPORT_C void TUsbcRequestCallback::SetTxBufferInfo(TUint8* aBufferStart, TUintPtr aBufferAddr, TInt aLength)
+    {
+    iTransferDir = UsbShai::EControllerWrite;
+    iBufferStart = aBufferStart;
+    iBufferAddr = aBufferAddr;
+    iLength = aLength;
+    }
+
+EXPORT_C UsbShai::TUsbPeripheralRequest::TUsbPeripheralRequest(TInt aRealEpNum):
+    iRealEpNum(aRealEpNum),
+    iBufferStart(NULL), 
+    iBufferAddr(0),
+    iLength(0),
+    iTxBytes(0),
+    iRxPackets(0),   
+    iPacketIndex(NULL),          // actually TUint16 (*)[]
+    iPacketSize(NULL),           // actually TUint16 (*)[]
+    iTransferDir(EControllerNone),
+    iZlpReqd(EFalse),
+    iError(KErrNone)
+    {
+    }
+
+// Peripheral PSL use this interface to register itself to PIL layer, in our case, 
+// DUsbClientController instance
+//
+// param aPeripheralControllerIf point to an implementation of 
+// UsbShai::MPeripheralControllerIf which represent a peripheral controller hardware.
+EXPORT_C void UsbShai::UsbPeripheralPil::RegisterPeripheralController( UsbShai::MPeripheralControllerIf& aPeripheralControllerIf, 
+                                                              const UsbShai::TPeripheralControllerProperties& aProperties)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("> UsbPeripheralPil::RegisterPeripheralController enter."));
+    
+    DUsbClientController* usbcc = DUsbClientController::Create(aPeripheralControllerIf,
+                                                               aProperties,
+                                                               /*aIsOtgPort=*/EFalse);
+    __ASSERT_DEBUG( (usbcc != NULL),
+                    Kern::Fault( "DUsbClientController extension entry point: USB PSL Out of memory", __LINE__ ) );
+    }
+
+// The way for charger detector(PSL) to make it known to us.
+EXPORT_C void UsbShai::UsbChargerDetectionPil::RegisterChargerDetector(UsbShai::MChargerDetectorIf&         aChargerDetector,
+                                                                       UsbShai::TChargerDetectorProperties& aProperties)
+    {
+    // Only on charger detector is allowed per system.
+    if( gChargerDetector != NULL)
+        {
+        return ;
+        }
+        
+    gChargerDetector = &aChargerDetector;
+    
+    if(gChargerObsever != NULL)
+        {
+        // Register to charger detector to listen to any charger type change
+        // events.
+        gChargerDetector->SetChargerDetectorObserver(*gChargerObsever);
+        }
+    }
+
+// -EOF-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/pdd/pil/src/queue.cpp	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,124 @@
+// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\drivers\usbcc\queue.cpp
+// Platform independent layer (PIL) of the USB Device controller driver:
+// Simple singly linked list + its iterator.
+// 
+//
+
+/**
+ @file queue.cpp
+ @internalTechnology
+*/
+//#include <drivers/usbc.h>
+#include <usb/usbc.h>
+
+
+void TSglQueLink::Enque(TSglQueLink* aLink)
+//
+// Enque this after aLink.
+//
+    {
+    iNext = aLink->iNext;
+    aLink->iNext = this;
+    }
+
+
+TSglQueBase::TSglQueBase(TInt aOffset)
+//
+// Constructor
+//
+    : iHead(NULL), iLast((TSglQueLink*) &iHead), iOffset(aOffset), iElements(0)
+    {
+    // ESQueOffsetNotAligned
+    __ASSERT_ALWAYS((iOffset % 4 == 0), Kern::Fault(KUsbPILPanicCat, __LINE__));
+    }
+
+
+void TSglQueBase::DoAddLast(TAny* aPtr)
+//
+// Add the object at the end of the queue.
+//
+    {
+    TSglQueLink* pL = PtrAdd((TSglQueLink*) aPtr, iOffset);
+    pL->Enque(iLast);
+    iLast = pL;
+    iElements++;
+    __ASSERT_DEBUG((iElements > 0), Kern::Fault(KUsbPILPanicCat, __LINE__));
+    }
+
+
+void TSglQueBase::DoRemove(TAny* aPtr)
+//
+// Remove the object from the queue.
+//
+    {
+    TSglQueLink* pP = (TSglQueLink*) (&iHead);
+    TSglQueLink* pL = PtrAdd((TSglQueLink*) aPtr, iOffset);
+    TSglQueLink* pN = pP->iNext;
+    while (pN)
+        {
+        if (pN == pL)
+            {
+            pP->iNext = pN->iNext;
+            if (iLast == pL)
+                {
+                iLast = pP;
+                if (iLast == NULL)
+                    iLast = (TSglQueLink*) (&iHead);
+                }
+            iElements--;
+            __ASSERT_DEBUG((iElements >= 0), Kern::Fault(KUsbPILPanicCat, __LINE__));
+            return;
+            }
+        pP = pN;
+        pN = pP->iNext;
+        }
+    // This doesn't have to indicate an error (but might):
+    __KTRACE_OPT(KPANIC, Kern::Printf("TSglQueBase::DoRemove: ESQueLinkNotQueued"));
+    }
+
+
+TSglQueIterBase::TSglQueIterBase(TSglQueBase& aQue)
+//
+// Constructor.
+//
+    : iOffset(aQue.iOffset), iHead(aQue.iHead), iNext(aQue.iHead)
+    {
+    }
+
+
+void TSglQueIterBase::SetToFirst()
+//
+// Start from the beginning of the que.
+//
+    {
+    iNext = iHead->iNext;
+    }
+
+
+TAny* TSglQueIterBase::DoPostInc()
+//
+// Return the current pointer and increment.
+//
+    {
+    TAny* pN = iNext;
+    if (pN == NULL)
+        return NULL;
+    iNext = iNext->iNext;
+    return PtrSub(pN, iOffset);
+    }
+
+
+//---
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/public/d32usbc.h	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,1163 @@
+// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32/include/d32usbc.h
+// User side class definitions for USB Device support.
+// 
+//
+
+/**
+ @file d32usbc.h
+ @publishedPartner
+ @released
+*/
+
+#ifndef __D32USBC_H__
+#define __D32USBC_H__
+
+#include <e32ver.h>
+#include <usb/usb.h>
+#include <usb/d32usbcshared.h>
+
+
+
+/** @internalComponent
+*/
+enum TTransferType
+	{
+	ETransferTypeReadData,
+	ETransferTypeReadPacket,
+	ETransferTypeWrite,
+	ETransferTypeNone,
+	ETransferTypeReadOneOrMore,
+	ETransferTypeReadUntilShort
+	};
+
+
+/** Available endpoints. At most only these are available per interface.
+*/
+enum TEndpointNumber
+	{
+	EEndpoint0 = 0,
+	EEndpoint1 = 1,
+	EEndpoint2 = 2,
+	EEndpoint3 = 3,
+	EEndpoint4 = 4,
+	EEndpoint5 = 5
+	};
+
+
+
+
+/** Bandwidth indicators for an Interface
+
+	@see RDevUsbcClient::SetInterface()
+*/
+enum TUsbcBandwidthPriority
+	{
+	/** Economical OUT buffering. */
+	EUsbcBandwidthOUTDefault = 0x00,
+	/** More memory than Default for OUT buffering. */
+	EUsbcBandwidthOUTPlus1   = 0x01,
+	/** More memory than Plus1 for OUT buffering. */
+	EUsbcBandwidthOUTPlus2   = 0x02,
+	/** Maximum memory for OUT buffering.
+		Use this value for high volume USB High-speed
+		data transfers only, otherwise memory will be wasted.
+	*/
+	EUsbcBandwidthOUTMaximum = 0x03,
+	//
+	/** Economical IN buffering */
+	EUsbcBandwidthINDefault  = 0x00,
+	/** More memory than Default for IN buffering */
+	EUsbcBandwidthINPlus1    = 0x10,
+	/** More memory than Plus1 for IN buffering */
+	EUsbcBandwidthINPlus2    = 0x20,
+	/** Maximum memory for IN buffering.
+		Use this value for high volume USB High-speed
+		data transfers only, otherwise memory will be wasted.
+	*/
+	EUsbcBandwidthINMaximum  = 0x30
+	};
+
+
+
+
+
+
+
+/** Bit positions of endpoints.
+
+	@see RDevUsbcClient::EndpointStatusNotify()
+	@see RDevUsbcClient::EndpointTransferCancel()
+
+	Bit position of endpoint0.
+*/
+const TUint KUsbcEndpoint0Bit = 1<<EEndpoint0;
+/** Bit position of endpoint1.
+*/
+const TUint KUsbcEndpoint1Bit = 1<<EEndpoint1;
+/** Bit position of endpoint2.
+*/
+const TUint KUsbcEndpoint2Bit = 1<<EEndpoint2;
+/** Bit position of endpoint3.
+*/
+const TUint KUsbcEndpoint3Bit = 1<<EEndpoint3;
+/** Bit position of endpoint4.
+*/
+const TUint KUsbcEndpoint4Bit = 1<<EEndpoint4;
+/** Bit position of endpoint5.
+*/
+const TUint KUsbcEndpoint5Bit = 1<<EEndpoint5;
+
+
+
+
+
+
+
+
+/** This must be filled in prior to a call to RDevUsbcClient::SetInterface().
+*/
+class TUsbcInterfaceInfo
+	{
+public:
+	TUsbcInterfaceInfo(TInt aClass=0, TInt aSubClass=0, TInt aProtocol=0,
+					   TDesC16* aString=NULL, TUint aTotalEndpoints=0);
+public:
+	/** The class, subclass and protocol that this interface supports. */
+	TUsbcClassInfo iClass;
+	/** The description string for the interface. Used to construct the interface string descriptor. */
+	const TDesC16* iString;
+	/** Total number of endpoints being requested (0-5). Endpoint 0 should not be included in this number. */
+	TUint iTotalEndpointsUsed;
+	/** Desired properties of the endpoints requested.
+		Do NOT include endpoint 0.
+		APIs use endpoint numbers that are offsets into this array.
+	*/
+	TUsbcEndpointInfo iEndpointData[KMaxEndpointsPerClient];
+	/** 32 flag bits used for specifying miscellaneous Interface features.
+		Currently defined are:
+		- KUsbcInterfaceInfo_NoEp0RequestsPlease = 0x00000001
+	*/
+	TUint32 iFeatureWord;
+	};
+
+
+/** Package buffer for a TUsbcInterfaceInfo object.
+
+	@see TUsbcInterfaceInfo
+*/
+typedef TPckgBuf<TUsbcInterfaceInfo> TUsbcInterfaceInfoBuf;
+
+
+/** The user side handle to the USB client driver.
+*/
+class RDevUsbcClient : public RBusLogicalChannel
+	{
+public:
+	/** @internalComponent */
+	enum TVer
+		{
+		EMajorVersionNumber = 0,
+		EMinorVersionNumber = 1,
+		EBuildVersionNumber = KE32BuildVersionNumber
+		};
+
+	enum TRequest
+		{
+		// Positive requests.
+		ERequestEp0 = 0x0,
+		ERequestEp1 = EEndpoint1,
+		ERequestEp2 = EEndpoint2,
+		ERequestEp3 = EEndpoint3,
+		ERequestEp4 = EEndpoint4,
+		ERequestEp5 = EEndpoint5,
+		ERequestUnused = 6,
+		ERequestAlternateDeviceStatusNotify = 7,
+		ERequestReEnumerate = 8,
+		ERequestEndpointStatusNotify = 9,
+		// The cancel TRequest's are interpreted as bitmaps. As they're not mixed
+		// with the previous ones, it doesn't matter if they have the same absolute
+		// value as those.
+		ERequestEp0Cancel = 1<<ERequestEp0,
+		ERequestEp1Cancel = 1<<ERequestEp1,
+		ERequestEp2Cancel = 1<<ERequestEp2,
+		ERequestEp3Cancel = 1<<ERequestEp3,
+		ERequestEp4Cancel = 1<<ERequestEp4,
+		ERequestEp5Cancel = 1<<ERequestEp5,
+		ERequestUnusedCancel = 1<<ERequestUnused,
+        ERequestAllCancel = (ERequestEp0Cancel | ERequestEp1Cancel |
+							 ERequestEp2Cancel | ERequestEp3Cancel |
+							 ERequestEp4Cancel | ERequestEp5Cancel |
+							 ERequestUnusedCancel),
+		ERequestAlternateDeviceStatusNotifyCancel = 1<<ERequestAlternateDeviceStatusNotify,
+		ERequestReEnumerateCancel = 1<<ERequestReEnumerate,
+		ERequestEndpointStatusNotifyCancel = 1<<ERequestEndpointStatusNotify,
+        ERequestOtgFeaturesNotify = 10,
+        ERequestOtgFeaturesNotifyCancel = 1<<ERequestOtgFeaturesNotify,
+		};
+
+	enum TControl
+		{
+		// Changing the order of these enums will break BC.
+		EControlEndpointZeroRequestError,					// 0
+		EControlEndpointCaps,
+		EControlDeviceCaps,
+		EControlGetAlternateSetting,
+		EControlDeviceStatus,
+		EControlEndpointStatus,
+		EControlSetInterface,
+		EControlReleaseInterface,
+		EControlQueryReceiveBuffer,
+		EControlSendEp0StatusPacket,						// 9
+		//
+		EControlHaltEndpoint,								// 10
+		EControlClearHaltEndpoint,
+		EControlSetDeviceControl,
+		EControlReleaseDeviceControl,
+		EControlEndpointZeroMaxPacketSizes,
+		EControlSetEndpointZeroMaxPacketSize,
+		EControlGetDeviceDescriptor,
+		EControlSetDeviceDescriptor,
+		EControlGetDeviceDescriptorSize,
+		EControlGetConfigurationDescriptor,					// 19
+		//
+		EControlSetConfigurationDescriptor,					// 20
+		EControlGetConfigurationDescriptorSize,
+		EControlGetInterfaceDescriptor,
+		EControlSetInterfaceDescriptor,
+		EControlGetInterfaceDescriptorSize,
+		EControlGetEndpointDescriptor,
+		EControlSetEndpointDescriptor,
+		EControlGetEndpointDescriptorSize,
+		EControlGetCSInterfaceDescriptor,
+		EControlSetCSInterfaceDescriptor,					// 29
+		//
+		EControlGetCSInterfaceDescriptorSize,				// 30
+		EControlGetCSEndpointDescriptor,
+		EControlSetCSEndpointDescriptor,
+		EControlGetCSEndpointDescriptorSize,
+		EControlSignalRemoteWakeup,
+		EControlGetStringDescriptorLangId,
+		EControlSetStringDescriptorLangId,
+		EControlGetManufacturerStringDescriptor,
+		EControlSetManufacturerStringDescriptor,
+		EControlRemoveManufacturerStringDescriptor,			// 39
+		//
+		EControlGetProductStringDescriptor,					// 40
+		EControlSetProductStringDescriptor,
+		EControlRemoveProductStringDescriptor,
+		EControlGetSerialNumberStringDescriptor,
+		EControlSetSerialNumberStringDescriptor,
+		EControlRemoveSerialNumberStringDescriptor,
+		EControlGetConfigurationStringDescriptor,
+		EControlSetConfigurationStringDescriptor,
+		EControlRemoveConfigurationStringDescriptor,
+		EControlDeviceDisconnectFromHost,					// 49
+		//
+		EControlDeviceConnectToHost,						// 50
+		EControlDevicePowerUpUdc,
+		EControlDumpRegisters,
+		EControlSetInterface1,								// (not used)
+		EControlAllocateEndpointResource,
+		EControlDeAllocateEndpointResource,
+		EControlQueryEndpointResourceUse,
+		EControlGetEndpointZeroMaxPacketSize,
+		EControlGetDeviceQualifierDescriptor,
+		EControlSetDeviceQualifierDescriptor,				// 59
+		//
+		EControlGetOtherSpeedConfigurationDescriptor,		// 60
+		EControlSetOtherSpeedConfigurationDescriptor,
+		EControlCurrentlyUsingHighSpeed,
+		EControlSetStringDescriptor,
+		EControlGetStringDescriptor,
+		EControlRemoveStringDescriptor,
+        EControlSetOtgDescriptor,
+        EControlGetOtgDescriptor,
+        EControlGetOtgFeatures
+		};
+
+public:
+
+#ifndef __KERNEL_MODE__
+
+	/** Opens a channel.
+
+		@param aUnit This should be 0 (zero).
+
+		@return KErrNone if successful.
+	*/
+	inline TInt Open(TInt aUnit);
+
+	inline TVersion VersionRequired() const;
+
+	/** Stalls ep0 to signal command fault to the host.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt EndpointZeroRequestError();
+
+	/** Retrieves the capabilities of all the endpoints on the device.
+
+		Suggested use is as follows:
+
+		@code
+		TUsbcEndpointData data[KUsbcMaxEndpoints];
+		TPtr8 dataPtr(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data));
+		ret = usbPort.EndpointCaps(dataPtr);
+		@endcode
+
+		@param aEpCapsBuf a descriptor encapsulating an array of TUsbcEndpointData.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt EndpointCaps(TDes8& aEpCapsBuf);
+
+	/** Retrieves the capabilities of the USB device.
+
+		@see TUsbDeviceCaps
+
+		@param aDevCapsBuf a TUsbDeviceCaps object.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt DeviceCaps(TUsbDeviceCaps& aDevCapsBuf);
+
+	/** Copies the current alternate setting for this interface into aInterfaceNumber
+		For USB Interfaces whose main interface is active, this will be 0 (zero).
+
+		@param aInterfaceNumber current alternate setting for this interface is copied into this.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt GetAlternateSetting(TInt& aInterfaceNumber);
+
+	/** Copies the current device status into aDeviceStatus.
+
+		@param aDeviceStatus current device status is copied into this.
+
+		@return KErrNone if successful
+	*/
+	inline TInt DeviceStatus(TUsbcDeviceState& aDeviceStatus);
+
+	/** Copies the current endpoint status into aEndpointStatus.
+
+		@param aEndpoint endpoint number valid for the current alternate setting.
+		@param aEndpointStatus the current endpoint status, might be stalled, not stalled or unknown.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt EndpointStatus(TEndpointNumber aEndpoint, TEndpointState& aEndpointStatus);
+
+	/** Copies the number of bytes available in the aEndpoint read buffer into aNumberOfBytes.
+
+		@param aEndpoint endpoint number valid for the current alternate setting.
+		@param aNumberOfBytes number of bytes available in the aEndpoint read buffer.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt QueryReceiveBuffer(TEndpointNumber aEndpoint, TInt& aNumberOfBytes);
+
+	/** Requests that a zero length status packet be sent to the host in response
+		to a class or vendor specific ep0 SETUP packet.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt SendEp0StatusPacket();
+
+	/** Stalls endpoint aEndpoint, usually to indicate an error condition with a previous command.
+		The host will normally send a SET_FEATURE command on ep0 to acknowledge and clear the stall.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt HaltEndpoint(TEndpointNumber aEndpoint);
+
+	/** Clears the stall condition on endpoint aEndpoint. This is inluded for symmetry and test purposes.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt ClearHaltEndpoint(TEndpointNumber aEndpoint);
+
+	/** Requests that device control be allocated to this channel.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt SetDeviceControl();
+
+	/** Relinquishes device control previously allocated to this channel.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt ReleaseDeviceControl();
+
+	/** Returns a bitmap of available ep0 maximum packet sizes.
+
+		@return bitmap of available ep0 maximum packet sizes.
+	*/
+	inline TUint EndpointZeroMaxPacketSizes();
+
+	/** Requests that a maximum packet size of aMaxPacketSize be set on ep0.
+
+		@param aMaxPacketSize The maximum packet size.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt SetEndpointZeroMaxPacketSize(TInt aMaxPacketSize);
+
+	/** Queries the current maximum packet size on ep0.
+
+		@return The currently set maximum packet size on ep0.
+	*/
+	inline TInt GetEndpointZeroMaxPacketSize();
+
+	/** Copies the current device descriptor into aDeviceDescriptor.
+
+		@param aDeviceDescriptor Receives the current device descriptor.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt GetDeviceDescriptor(TDes8& aDeviceDescriptor);
+
+	/** Sets the contents of aDeviceDescriptor to be the current device descriptor.
+
+		@param aDeviceDescriptor contains the device descriptor.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt SetDeviceDescriptor(const TDesC8& aDeviceDescriptor);
+
+	/** Gets the size of the current device descriptor. This is unlikely to be anything other than 9.
+
+		@param aSize receives the size of the current device descriptor.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt GetDeviceDescriptorSize(TInt& aSize);
+
+	/** Copies the current configuration descriptor into aConfigurationDescriptor.
+
+		@param aConfigurationDescriptor Receives the current configuration descriptor.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt GetConfigurationDescriptor(TDes8& aConfigurationDescriptor);
+
+	/** Sets the contents of aConfigurationDescriptor to be the current configuration descriptor.
+
+		@param aConfigurationDescriptor contains the configuration descriptor.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt SetConfigurationDescriptor(const TDesC8& aConfigurationDescriptor);
+
+	/** Gets the size of the current configuration descriptor.
+
+		@param aSize receives the size of the current configuration descriptor.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt GetConfigurationDescriptorSize(TInt& aSize);
+
+	/** Copies the interface descriptor into aInterfaceDescriptor for the interface with alternate
+		setting aSettingNumber, 0 for the main interface.
+
+		@param aSettingNumber Alternate setting number on the interface, 0 for the main interface.
+		@param aInterfaceDescriptor Receives the interface descriptor.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt GetInterfaceDescriptor(TInt aSettingNumber, TDes8& aInterfaceDescriptor);
+
+	/** Sets the interface descriptor contained in aInterfaceDescriptor for the interface with
+		alternate setting aSettingNumber, 0 for the main interface, for transmission to the host
+		during enumeration.
+
+		@param aSettingNumber Alternate setting number on the interface, 0 for the main interface.
+		@param aInterfaceDescriptor Contains the interface descriptor to be set.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt SetInterfaceDescriptor(TInt aSettingNumber, const TDesC8& aInterfaceDescriptor);
+
+	/** Copies the size of the interface descriptor for the interface with alternate
+		setting aSettingNumber, 0 for the main interface, into aSize.
+
+		@param aSettingNumber The alternate setting.
+		@param aSize receives the size of the interface descriptor.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt GetInterfaceDescriptorSize(TInt aSettingNumber, TInt& aSize);
+
+	/** Copies the endpoint descriptor for logical endpoint number aEndpointNumber into aEndpointDescriptor
+		for the interface with alternate setting aSettingNumber, 0 for the main interface.
+
+		@param aSettingNumber Alternate setting number on the interface, 0 for the main interface.
+		@param aEndpointNumber.
+		@param aEndpointDescriptor Receives the endpoint descriptor.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt GetEndpointDescriptor(TInt aSettingNumber, TInt aEndpointNumber, TDes8& aEndpointDescriptor);
+
+	/** Sets the endpoint descriptor for logical endpoint number aEndpointNumber contained in
+		aEndpointDescriptor for the interface with alternate setting aSettingNumber, 0 for the main interface,
+		for transmission to the host during enumeration.
+
+		@param aSettingNumber Alternate setting number on the interface, 0 for the main interface.
+		@param aEndpointNumber Valid endpoint number on this interface.
+		@param aEndpointDescriptor Contains the endpoint descriptor to be set.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt SetEndpointDescriptor(TInt aSettingNumber, TInt aEndpointNumber,
+									  const TDesC8& aEndpointDescriptor);
+
+	/** Copies the size of the endpoint descriptor for logical endpoint number aEndpointNumber for the
+		interface with alternate setting aSettingNumber, 0 for the main interface, into aSize.
+
+		@param aSettingNumber Alternate setting number on the interface, 0 for the main interface.
+		@param aEndpointNumber Valid endpoint number on this interface.
+		@param aSize receives the size of the endpoint descriptor.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt GetEndpointDescriptorSize(TInt aSettingNumber, TInt aEndpointNumber, TInt& aSize);
+
+    /** Get OTG descriptor size
+
+		@param aSize TInt reference which contains OTG descriptor size on return
+    */
+    inline void GetOtgDescriptorSize(TInt& aSize);
+
+    /** Get OTG descriptor of USB on-the-go feature
+
+		@param aOtgDesc User-side buffer to store copy of descriptor
+
+		@return KErrNone if successful
+    */
+    inline TInt GetOtgDescriptor(TDes8& aOtgDesc);
+
+    /** Set OTG descriptor by user to enable/disable USB on-the-go feature
+
+		@param aOtgDesc Descriptor buffer containing OTG features
+
+		@return KErrNone if successful
+    */
+    inline TInt SetOtgDescriptor(const TDesC8& aOtgDesc);
+
+	/** Copies the current device_qualifier descriptor into aDescriptor.
+
+		@param aDescriptor Receives the current device_qualifier descriptor.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt GetDeviceQualifierDescriptor(TDes8& aDescriptor);
+
+	/** Sets the device_qualifier descriptor to the contents of aDescriptor.
+
+		@param aDescriptor contains the new device_qualifier descriptor.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt SetDeviceQualifierDescriptor(const TDesC8& aDescriptor);
+
+	/** Copies the current other_speed_configuration descriptor into aDescriptor.
+
+		@param aDescriptor Receives the current other_speed_configuration descriptor.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt GetOtherSpeedConfigurationDescriptor(TDes8& aDescriptor);
+
+	/** Sets the other_speed_configuration descriptor to the contents of aDescriptor.
+
+		@param aDescriptor contains the new other_speed_configuration descriptor.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt SetOtherSpeedConfigurationDescriptor(const TDesC8& aDescriptor);
+
+	/** Copies the class specific interface descriptor block into aInterfaceDescriptor for the interface
+		with alternate setting aSettingNumber, 0 for the main interface.
+
+		@param aSettingNumber Alternate setting number on the interface, 0 for the main interface.
+		@param aInterfaceDescriptor Contains the interface descriptor to be set.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt GetCSInterfaceDescriptorBlock(TInt aSettingNumber, TDes8& aInterfaceDescriptor);
+
+	/** aSettingNumber is the alternate interface setting, 0 for the main interface, that the descriptor block
+		aDes should be attached to. aDes is a block of data containing at least one class specific descriptor
+		for transmission during enumeration after the class interface descriptor (or alternate interface
+		descriptor) has been sent, but before the endpoint descriptors belonging to this interface are sent.
+		aDes may contain as many descriptors as are necessary or only 1. SetCSInterfaceDescriptorBlock()
+		should be called at any time after SetInterface() has been called to establish a main interface or an
+		alternate interface. More than one call may be made - the data blocks will be concatenated prior to
+		sending. No checking or validation of the contents of aDes will be made and it is the caller's
+		responsibility to ensure that the data supplied is correct and appropriate to the interface identified
+		by aSettingNumber.
+
+		@param aSettingNumber Alternate setting number on the interface, 0 for the main interface.
+		@param aInterfaceDescriptor Contains the interface descriptor to be set.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt SetCSInterfaceDescriptorBlock(TInt aSettingNumber, const TDesC8& aInterfaceDescriptor);
+
+	/** Copies the size of the class specific interface descriptor block for the interface with alternate
+		setting aSettingNumber, 0 for the main interface, into aSize.
+
+		@param aSettingNumber The alternate setting number.
+		@param aSize receives the size of the interface descriptor.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt GetCSInterfaceDescriptorBlockSize(TInt aSettingNumber, TInt& aSize);
+
+	/** Copies the class specific endpoint descriptor for logical endpoint number aEndpointNumber
+		into aEndpointDescriptor for the interface with alternate setting aSettingNumber, 0 for the main
+		interface.
+
+		@param aSettingNumber Alternate setting number on the interface, 0 for the main interface.
+		@param aEndpointNumber Valid endpoint number on this interface.
+		@param aEndpointDescriptor Receives the endpoint descriptor.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt GetCSEndpointDescriptorBlock(TInt aSettingNumber, TInt aEndpointNumber,
+											 TDes8& aEndpointDescriptor);
+
+	/** Sets the class specific endpoint descriptor for logical endpoint number aEndpointNumber contained in
+		aEndpointDescriptor for the interface with alternate setting aSettingNumber, 0 for the main interface,
+		for transmission to the host during enumeration.
+
+		@param aSettingNumber Alternate setting number on the interface, 0 for the main interface.
+		@param aEndpointNumber Valid endpoint number on this interface.
+		@param aEndpointDescriptor Contains the endpoint descriptor to be set.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt SetCSEndpointDescriptorBlock(TInt aSettingNumber, TInt aEndpointNumber,
+											 const TDesC8& aEndpointDescriptor);
+
+	/** Copies the size of the class specific endpoint descriptor block for logical endpoint number
+		aEndpointNumber for the interface with alternate setting aSettingNumber, 0 for the main interface,
+		into aSize.
+
+		@param aSettingNumber Alternate setting number on the interface, 0 for the main interface.
+		@param aEndpointNumber Valid endpoint number on this interface.
+		@param aSize On return, contains the size of the class specific endpoint descriptor block.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt GetCSEndpointDescriptorBlockSize(TInt aSettingNumber, TInt aEndpointNumber, TInt& aSize);
+
+	/** Generates a Remote Wakeup bus condition
+		The capability of the device to generate Remote Wakeup signalling is enquired in
+		RDevUsbcClient::DeviceCaps.
+
+		@return KErrNone if this signalling is possible and the signal has been generated.
+	*/
+	inline TInt SignalRemoteWakeup();
+
+	/** Simulates a physical removal of the USB cable by disabling the D+/- pull-ups.The iConnect member of
+		TUsbDeviceCapsV01, returned by RDevUsbcClient::DeviceCaps(), indicates whether this functionality is
+		supported.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt DeviceDisconnectFromHost();
+
+	/** Simulates a physical insertion of the USB cable by enabling the D+/- pull-ups.The iConnect member
+		of TUsbDeviceCapsV01, returned by RDevUsbcClient::DeviceCaps(),  indicates whether this functionality
+		is supported.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt DeviceConnectToHost();
+
+	/** Powers up the UDC and connects it to the bus if one or more interfaces exist.
+
+		@return KErrNone if UDC successfully powered up, KErrNotReady if no
+		interfaces have been registered yet, KErrHardwareNotAvailable if UDC
+		couldn't be activated.
+	*/
+	inline TInt PowerUpUdc();
+
+	/** Enquires about the current operating speed of the UDC.
+
+		@return ETrue if the UDC is currently operating at High speed, EFalse otherwise.
+	*/
+	inline TBool CurrentlyUsingHighSpeed();
+
+	/** Allocates the use of aResource to aEndpoint. it will be used from when the current bus transfer	has been
+		completed.
+
+		@param aResource is typically some rationed hardware resource or possibly specifies a type of endpoint
+		behaviour. aResource is not a bitmap and TEndpointResource values should not be combined.
+		@param aEndpoint The endpoint number to which the resource is to be allocated.
+
+		@return KErrNone if successful, KErrInUse if the resource is already consumed and cannot be allocated,
+		KErrNotSupported if the endpoint does not support the resource requested.
+
+		@publishedPartner @deprecated
+
+		@see TUsbcEndpointInfo
+	*/
+	inline TInt AllocateEndpointResource(TInt aEndpoint, TUsbcEndpointResource aResource);
+
+	/** Deallocates the use of aResource aEndpoint or ends a specified endpoint behaviour.
+
+		@param aResource is typically some rationed hardware resource or possibly specifies a type of endpoint
+		behaviour. aResource is not a bitmap and TEndpointResource values should not be combined.
+		@param aEndpoint The endpoint number from which the resource is to be removed.
+
+		@return KErrNone if the resource has been successfully deallocated, KErrNotSupported if the endpoint
+		does not support the resource requested.
+
+		@publishedPartner @deprecated
+
+		@see TUsbcEndpointInfo
+	*/
+	inline TInt DeAllocateEndpointResource(TInt aEndpoint, TUsbcEndpointResource aResource);
+
+	/** Queries endpoint resource use.
+
+		@param aResource is typically some rationed hardware resource or possibly specifies a type of endpoint
+		behaviour. aResource is not a bitmap and TEndpointResource values should not be combined.
+		@param aEndpoint The endpoint number at which the resource is to be queried.
+
+		@return ETrue is the specified resource is in use at the endpoint and EFalse if not.
+	*/
+	inline TBool QueryEndpointResourceUse(TInt aEndpoint, TUsbcEndpointResource aResource);
+
+	/** Request (i.e. claim for this channel) up to five endpoints and set the class type for this USB
+		interface. 'aInterfaceData' is a package buffer which describes the interface and all the endpoints
+		being requested by the driver for this interface.
+
+		@param aInterfaceNumber Distinguishes between alternate interfaces. If these are not be used then this
+		should always be zero. If this parameter is used, then its value must be one more than that of the
+		proceeding alternate interface.
+		@param aInterfaceData a package buffer which describes the interface and all the endpoints being
+		requested by the driver for this interface.
+		@param aBandwidthPriority is a bitmap combining the required IN and OUT priorities. Values are in the
+		range [0,3] from the lowest priority bandwidth, 0, to the highest 3 and are separately specified for
+		IN and OUT endpoints. Interfaces requiring higher bandwidth are allocated significantly more buffering
+		than low bandwidth interfaces. Interfaces should not be given a higher bandwidth priority than they
+		require.
+
+		@return KErrInUse if any of the endpoints being requested have already been claimed by another channel
+		KErrNotSupported if an endpoint with all of the specified properties is not supported on this
+		platform. KErrNoMemory if insufficient memory is available to complete the operation.
+	*/
+	inline TInt SetInterface(TInt aInterfaceNumber, TUsbcInterfaceInfoBuf& aInterfaceData,
+							 TUint32 aBandwidthPriority =
+							 (EUsbcBandwidthOUTDefault | EUsbcBandwidthINDefault));
+
+	/** Release an interface previously claimed by this channel. Alternate interfaces need to be released
+		in strict descending order, starting with the last (i.e. highest numbered) one.
+		It is not necessary to release an interface that wasn't successfully requested.
+
+		@param aInterfaceNumber Specifies the alternate setting number 'aInterfaceNum' of the interface to be
+		released.
+
+		@return KErrNone if successful. KErrArgument if the alternate setting doesn't exist or is released out
+		of order.
+	*/
+	inline TInt ReleaseInterface(TInt aInterfaceNumber);
+
+	/** Copies the current string descriptor language ID (LANGID) code into the aLangId argument. Even though
+		the USB spec allows for the existence of a whole array of LANGID codes, we only support one.
+
+		@param aLangId receives the LANGID code.
+
+		@return KErrNone if successful, KErrArgument if problem with argument (memory cannot be written to, etc.).
+	*/
+	inline TInt GetStringDescriptorLangId(TUint16& aLangId);
+
+	/** Sets the string descriptor language ID (LANGID). Even though the USB spec allows for the existence of
+		a whole array of LANGID codes, we only support one.
+
+		@param aLangId the LANGID code to be set.
+
+		@return KErrNone if successful.
+	*/
+	inline TInt SetStringDescriptorLangId(TUint16 aLangId);
+
+	/** Copies the string descriptor identified by the iManufacturer index field of the Standard Device
+		Descriptor into the aString argument.
+
+		@param aString receives manufacturer string.
+
+		@return KErrNone if successful, KErrArgument if MaxLength of aString is too small to hold the entire
+		descriptor, KErrNotFound if the string descriptor couldn't be found.
+	*/
+	inline TInt GetManufacturerStringDescriptor(TDes16& aString);
+
+	/** Sets the string descriptor identified by the iManufacturer index field of the Standard Device
+		Descriptor to the aString argument.
+
+		@param aString Contains the new manufacturer string descriptor.
+
+		@return KErrNone if successful, KErrNoMemory if no memory is available to store the new string from
+		aString (in which case the old string descriptor will be preserved).
+	*/
+	inline TInt SetManufacturerStringDescriptor(const TDesC16& aString);
+
+	/** Removes (deletes) the string descriptor identified by the iManufacturer index field of the Standard
+		Device Descriptor and sets that field to zero.
+
+		@return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found.
+	*/
+	inline TInt RemoveManufacturerStringDescriptor();
+
+	/** Retrieves the string descriptor identified by the iProduct index field of the Standard Device
+		Descriptor into the aString argument.
+
+		@param aString receives product string.
+
+		@return KErrNone if successful, KErrArgument if MaxLength of aString is too small to hold the entire
+		descriptor, KErrNotFound if the string descriptor couldn't be found.
+	*/
+	inline TInt GetProductStringDescriptor(TDes16& aString);
+
+	/** Sets the string descriptor identified by the iProduct index field of the Standard Device Descriptor to
+		the aString argument.
+
+		@param aString Contains the new product string descriptor.
+
+		@return KErrNone if successful, KErrNoMemory if no memory is available to store the new string from
+		aString (in which case the old string descriptor will be preserved).
+	*/
+	inline TInt SetProductStringDescriptor(const TDesC16& aString);
+
+	/** Removes (deletes) the string descriptor identified by the iProduct index field of the Standard Device
+		Descriptor and sets that field to zero.
+
+		@return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found.
+	*/
+	inline TInt RemoveProductStringDescriptor();
+
+	/** Retrieves the string descriptor identified by the iSerialNumber index field of the Standard Device
+		Descriptor into the aString argument.
+
+		@param aString receives product string.
+
+		@return KErrNone if successful, KErrArgument if MaxLength of aString is too small to hold the entire
+		descriptor, KErrNotFound if the string descriptor couldn't be found.
+	*/
+	inline TInt GetSerialNumberStringDescriptor(TDes16& aString);
+
+	/** Sets the string descriptor identified by the iSerialNumber index field of the Standard Device
+		Descriptor to the aString argument.
+
+		@param aString Contains the new serial number string descriptor.
+
+		@return KErrNone if successful, KErrNoMemory if no memory is available to store the new string from
+		aString (in which case the old string descriptor will be preserved).
+	*/
+	inline TInt SetSerialNumberStringDescriptor(const TDesC16& aString);
+
+	/** Removes (deletes) the string descriptor identified by the iSerialNumber index field of the Standard
+		Device Descriptor and sets that field to zero.
+
+		@return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found.
+	*/
+	inline TInt RemoveSerialNumberStringDescriptor();
+
+	/** Retrieves the string descriptor identified by the iConfiguration index field of the (first) Standard
+		Configuration Descriptor into the aString argument.
+
+		@param aString receives configuration string.
+
+		@return KErrNone if successful, KErrArgument if MaxLength of aString is too small to hold the entire
+		descriptor, KErrNotFound if the string descriptor couldn't be found.
+	*/
+	inline TInt GetConfigurationStringDescriptor(TDes16& aString);
+
+	/** Sets the string descriptor identified by the iConfiguration index field of the Standard Configuration
+		Descriptor to the aString argument.
+
+		@param aString Contains the new serial number string descriptor.
+
+		@return KErrNone if successful, KErrNoMemory if no memory is available to store the new string from
+		aString (in which case the old string descriptor will be preserved).
+	*/
+	inline TInt SetConfigurationStringDescriptor(const TDesC16& aString);
+
+	/** Removes (deletes) the string descriptor identified by the iConfiguration index field of the Standard
+		Configuration Descriptor and sets that field to zero.
+
+		@return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found.
+	*/
+	inline TInt RemoveConfigurationStringDescriptor();
+
+	/** Copies the string of the USB string descriptor at the specified index in the string descriptor array
+		into the aString argument.
+
+		Although this function can also be used for it, for querying most standard string descriptors
+		there exists a set of dedicated access functions.
+
+		@see RDevUsbcClient::GetStringDescriptorLangId
+		@see RDevUsbcClient::GetManufacturerStringDescriptor
+		@see RDevUsbcClient::GetProductStringDescriptor
+		@see RDevUsbcClient::GetSerialNumberStringDescriptor
+		@see RDevUsbcClient::GetConfigurationStringDescriptor
+
+		@param aIndex The position of the string descriptor in the string descriptor array.
+		@param aString The target location for the string descriptor copy.
+
+		@return KErrNone if successful, KErrNotFound if no string descriptor exists at the specified index,
+		KErrArgument if MaxLength() of aString is too small to hold the entire descriptor.
+	*/
+	inline TInt GetStringDescriptor(TUint8 aIndex, TDes16& aString);
+
+	/** Sets the aString argument to be the string of a USB string descriptor at the specified index in the
+		string descriptor array. If a string descriptor already exists at that position then its string will
+		be replaced.
+
+		Care should be taken, when choosing aIndex, not to inadvertently overwrite one of the standard
+		string descriptors.	For their manipulation there exists a set of dedicated access functions.
+
+		@see RDevUsbcClient::SetStringDescriptorLangId
+		@see RDevUsbcClient::SetManufacturerStringDescriptor
+		@see RDevUsbcClient::SetProductStringDescriptor
+		@see RDevUsbcClient::SetSerialNumberStringDescriptor
+		@see RDevUsbcClient::SetConfigurationStringDescriptor
+
+		@param aIndex The position of the string descriptor in the string descriptor array.
+		@param aString Contains the string descriptor to be set.
+
+		@return KErrNone if successful, KErrArgument if aIndex is invalid, KErrNoMemory if no memory
+		is available to store the new string (an existing descriptor at that index will be preserved).
+	*/
+	inline TInt SetStringDescriptor(TUint8 aIndex, const TDesC16& aString);
+
+	/** Removes (deletes) the USB string descriptor at the specified index in the string descriptor array.
+		The position in the array of other string descriptors is not affected.
+
+		Care should be taken, when choosing aIndex, not to inadvertently delete a standard string descriptor
+		(also because index references from non-string descriptors would be invalidated). For the deletion
+		of most standard string descriptors there exists a set of dedicated functions.
+
+		@see RDevUsbcClient::RemoveManufacturerStringDescriptor
+		@see RDevUsbcClient::RemoveProductStringDescriptor
+		@see RDevUsbcClient::RemoveSerialNumberStringDescriptor
+		@see RDevUsbcClient::RemoveConfigurationStringDescriptor
+
+		@param aIndex The position of the string descriptor in the string descriptor array.
+
+		@return KErrNone if successful, KErrNotFound if no string descriptor exists at the specified index.
+	*/
+	inline TInt RemoveStringDescriptor(TUint8 aIndex);
+
+	/** Asynchronously read data from endpoint 'aEndpoint' into the descriptor 'aDes'.
+		Request completes when the specified number of bytes is received, length taken from max. length of
+		descriptor.
+
+		@param aStatus The request status.
+		@param aEndpoint The endpoint number to read from.
+		@param aDes	Descriptor to receive the data.
+	*/
+	inline void Read(TRequestStatus& aStatus, TEndpointNumber aEndpoint, TDes8& aDes);
+
+	/** Asynchronously read data from endpoint 'aEndpoint' into the descriptor 'aDes'.
+		Request completes when the specified number of bytes is received.
+
+		@param aStatus The request status.
+		@param aEndpoint The endpoint number to read from.
+		@param aDes	Descriptor to receive the data.
+		@param aLen The number of bytes to read.
+	*/
+	inline void Read(TRequestStatus& aStatus, TEndpointNumber aEndpoint, TDes8& aDes, TInt aLen);
+
+	/** Asynchronously read an entire packet of data from endpoint 'aEndpoint' into the descriptor 'aDes'.
+		If a packet has previously been partly read. then only the remainder of the packet will be returned.
+		The request should be for the maximum packet size of the endpoint. If less data is requested, then
+		after this read completes the remainder of the data in the packet will be discarded and the next read
+		will start from the next available packet.
+		Request completes when either a complete packet is received or the length of the packet currently
+		being received exceeds 'aMaxLen'.
+
+		@param aStatus The request status.
+		@param aEndpoint The endpoint number to read from.
+		@param aDes	Descriptor to receive the data.
+		@param aMaxLen .
+	*/
+	inline void ReadPacket(TRequestStatus& aStatus, TEndpointNumber aEndpoint, TDes8& aDes, TInt aMaxLen);
+
+	/** Asynchronously read data from endpoint 'aEndpoint' into the descriptor 'aDes'.
+		Request completes when the specified number of bytes is received (in first version,
+		length taken from max. length of descriptor).
+
+		@param aStatus The request status.
+		@param aEndpoint The endpoint number to read from.
+		@param aDes	Descriptor to receive the data.
+	*/
+	inline void ReadUntilShort(TRequestStatus& aStatus, TEndpointNumber aEndpoint, TDes8& aDes);
+
+	/** Asynchronously read data from endpoint 'aEndpoint' into the descriptor 'aDes'.
+		Request completes when the specified number of bytes is received (in first version,
+		length taken from max. length of descriptor).
+
+		@param aStatus The request status.
+		@param aEndpoint The endpoint number to read from.
+		@param aDes	Descriptor to receive the data.
+		@param aLen The number of bytes to receive.
+	*/
+	inline void ReadUntilShort(TRequestStatus& aStatus, TEndpointNumber aEndpoint, TDes8& aDes, TInt aLen);
+
+	/** Asynchronously read data from endpoint 'aEndpoint' into the descriptor 'aDes'. The request completes
+		when the specified number of bytes is received, length taken from max. length of descriptor or a
+		packet whose size is smaller than the endpoint's maximum packet size is received.
+
+		@param aStatus The request status.
+		@param aEndpoint The endpoint number to read from.
+		@param aDes	Descriptor to receive the data.
+	*/
+	inline void ReadOneOrMore(TRequestStatus& aStatus, TEndpointNumber aEndpoint, TDes8& aDes);
+
+	/** Asynchronously read data from endpoint 'aEndpoint' into the descriptor 'aDes'. The request completes
+		when the specified number of bytes is received, or a packet whose size is smaller than the endpoint's
+		maximum packet size is received.
+
+		@param aStatus The request status.
+		@param aEndpoint The endpoint number to read from.
+		@param aDes	Descriptor to receive the data.
+		@param aLen The number of bytes to receive.
+	*/
+	inline void ReadOneOrMore(TRequestStatus& aStatus, TEndpointNumber aEndpoint, TDes8& aDes, TInt aLen);
+
+	/** Cancels an outstanding read request. The request will complete with whatever data is available.
+	*/
+	inline void ReadCancel(TEndpointNumber aEndpoint);
+
+	/** Asynchronously write 'aLen' bytes of data to endpoint 'aEndpoint' from descriptor 'aDes'. 'aZlpRequired'
+		(optional) signals that ZLP termination may be required.
+
+		@param aStatus The request status.
+		@param aEndpoint The endpoint number to write to.
+		@param aDes	Descriptor to provide the data.
+		@param aLen The number of bytes of data to be written.
+		@param aZlpRequired True, if ZLP termination is required; false, otherwise.
+	*/
+	inline void Write(TRequestStatus& aStatus, TEndpointNumber aEndpoint, const TDesC8& aDes, TInt aLen,
+					  TBool aZlpRequired=EFalse);
+
+	/** Cancels an outstanding write request on endpoint aEndpoint.
+
+		@param aEndpoint The endpoint number whose write is to be cancelled.
+	*/
+	inline void WriteCancel(TEndpointNumber aEndpoint);
+
+	/** Cancels any transfer on any endpoint specified in aEndpointMask.
+
+		@code
+		// Cancel transfer requests on endpoints 1, 2 & 3
+		usbPort.EndpointTransferCancel(KUsbcEndpoint1Bit | KUsbcEndpoint2Bit | KUsbcEndpoint3Bit);
+		@endcode
+
+		@param aEndpointMask bitmap of the endpoints.
+	*/
+	inline void EndpointTransferCancel(TUint aEndpointMask);
+
+	/**	Register for notification when a change of the Interface alternate setting or the USB Controller's
+		current state occurs. When the alternate setting or the Controller state changes, then the
+		asynchronous function completes and the current alternate setting number or Controller state is
+		written back to aValue. If the KUsbAlternateSetting bit is set then the remaining bits are the
+		alternate setting number. Otherwise aValue is interpreted as a TUsbcDeviceState.
+
+		@see TUsbcDeviceState
+
+		@param aStatus The request status.
+		@param aValue Receives the alternate setting number or Controller state.
+	*/
+	inline void AlternateDeviceStatusNotify(TRequestStatus& aStatus, TUint& aValue);
+
+	/** Completes an AlternateDeviceStatusNotify request. If a request has previously been made then the
+		status variable is updated with the current device state.
+	*/
+	inline void AlternateDeviceStatusNotifyCancel();
+
+	/** If the channel has changed the grouping of endpoints between interfaces or changed the interface class
+		type from the defaults then it is necessary to force a re-enumeration. This will typically involve the
+		Symbian OS device initiating a disconnection and re-connection. This is an asynchronous operation
+		which will complete when the Controller is successfully configured by the host, i.e. has achieved
+		UsbShai::EUsbPeripheralStateConfigured.  Since it is not known if the operation has failed, at the same time that
+		a ReEnumerate request is made, a timer should be set up to complete after approximately 5 seconds. It
+		can be assumed that if the operation has not completed after this time interval then it will not
+		complete.
+
+		@param aStatus The request status.
+	*/
+	inline void ReEnumerate(TRequestStatus& aStatus);
+
+	/** Cancels an outstanding ReEnumerate() request.
+	*/
+	inline void ReEnumerateCancel();
+
+	/**	Register for notification when a change in stall status of any of the interface's endpoints occurs,
+		but not ep0. When a change in stall status occurs, then the asynchronous function completes and the
+		current stall state is written back to 'aEndpointStatus' as a bit map: Only stall state changes caused
+		by SET_FEATURE and CLEAR_FEATURE standard commands on ep0 will be notified when this function
+		completes. After this request completes the request should be re-issued to obtain future
+		notifications.
+
+		@param aStatus The request status.
+		@param aEndpointMask a bitmap of the endpoints stall status. This is filled in when the call completes
+		bit 1 represents the interface's virtual endpoint 1, (KUsbcEndpoint1Bit)
+		bit 2 represents the interface's virtual endpoint 2, (KUsbcEndpoint2Bit) etc.
+		bit value 0 - not stalled,
+		bit value 1 - stalled.
+	*/
+	inline void EndpointStatusNotify(TRequestStatus& aStatus, TUint& aEndpointMask);
+
+	/** Completes an endpoint status notify request.
+	*/
+ 	inline void EndpointStatusNotifyCancel();
+
+    /** Get current on-the-go features relating to the ability of device/host pair to
+        perform OTG role swap.
+
+        @param aFeatures On return it contanis features the device currently has
+                bit 2 represents b_hnp_enable,       (KUsbOtgAttr_B_HnpEnable)
+                bit 3 represents a_hnp_support,      (KUsbOtgAttr_A_HnpSupport)
+                bit 4 represents a_alt_hnp_support,  (KUsbOtgAttr_A_AltHnpSupport)
+        @return KErrNone if successful, KErrNotSupported if OTG is not supported by
+                this device, otherwise system-wide error returns
+    */
+    inline TInt GetOtgFeatures(TUint8& aFeatures);
+
+    /** Register for notification on USB on-the-go features' change. If any OTG feature
+        is changed, request completes and current feature value is filled in aValue.
+
+        @param aStatus Request status object
+        @param aValue On request completion, it contains current OTG feature value
+    */
+    inline void OtgFeaturesNotify(TRequestStatus& aStatus, TUint8& aValue);
+
+    /** Cancel pending OTG feature request.
+    */
+    inline void OtgFeaturesNotifyCancel();
+
+#endif // #ifndef __KERNEL_MODE__
+	};
+
+
+#include <usb/d32usbc.inl>
+
+
+#endif // __D32USBC_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/public/d32usbc.inl	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,702 @@
+// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32/include/d32usbc.inl
+// User side class definitions for USB Device support (inline header).
+// 
+//
+
+/**
+ @file d32usbc.inl
+ @publishedPartner
+ @released
+*/
+
+#ifndef __D32USBC_INL__
+#define __D32USBC_INL__
+
+
+/** @internalTechnology
+*/
+struct TUsbcIfcInfo
+	{
+	TUsbcInterfaceInfoBuf* iInterfaceData;
+	TPtr8* iString;
+	TUint32 iBandwidthPriority;
+	};
+
+
+/** @internalTechnology
+*/
+struct TEndpointTransferInfo
+	{
+	TDesC8* iDes;
+	TTransferType iTransferType;
+	TInt iTransferSize;
+	TBool iZlpReqd;
+	};
+
+inline TUsbcInterfaceInfo::TUsbcInterfaceInfo(TInt aClass, TInt aSubClass,
+											  TInt aProtocol, TDesC16* aString,
+											  TUint aTotalEndpoints)
+	: iClass(aClass, aSubClass, aProtocol), iString(aString),
+	  iTotalEndpointsUsed(aTotalEndpoints), iEndpointData(), iFeatureWord(0)
+	{}
+
+
+#ifndef __KERNEL_MODE__
+
+/** @capability CommDD
+*/
+inline TInt RDevUsbcClient::Open(TInt aUnit)
+	{
+	_LIT(KUsbDevName, "Usbc");
+	return (DoCreate(KUsbDevName, VersionRequired(), aUnit, NULL, NULL, EOwnerThread));
+	}
+
+
+inline TVersion RDevUsbcClient::VersionRequired() const
+	{
+	return (TVersion(EMajorVersionNumber, EMinorVersionNumber, EBuildVersionNumber));
+	}
+
+
+inline TInt RDevUsbcClient::EndpointZeroRequestError()
+	{
+	return DoControl(EControlEndpointZeroRequestError);
+	}
+
+
+inline TInt RDevUsbcClient::EndpointCaps(TDes8& aCapsBuf)
+	{
+	return DoControl(EControlEndpointCaps, &aCapsBuf);
+	}
+
+
+inline TInt RDevUsbcClient::DeviceCaps(TUsbDeviceCaps& aCapsBuf)
+	{
+	return DoControl(EControlDeviceCaps, &aCapsBuf);
+	}
+
+
+inline TInt RDevUsbcClient::GetAlternateSetting(TInt &aInterfaceNumber)
+	{
+	return DoControl(EControlGetAlternateSetting, &aInterfaceNumber);
+	}
+
+
+inline TInt RDevUsbcClient::DeviceStatus(TUsbcDeviceState &aDeviceStatus)
+	{
+	return DoControl(EControlDeviceStatus, &aDeviceStatus);
+	}
+
+
+inline TInt RDevUsbcClient::EndpointStatus(TEndpointNumber aEndpoint,TEndpointState &aEndpointStatus)
+	{
+	return DoControl(EControlEndpointStatus,(TAny*) aEndpoint, &aEndpointStatus);
+	}
+
+
+inline TInt RDevUsbcClient::QueryReceiveBuffer(TEndpointNumber aEndpoint,TInt& aNumberOfBytes)
+	{
+	return DoControl(EControlQueryReceiveBuffer, (TAny*) aEndpoint, &aNumberOfBytes);
+	}
+
+
+inline TInt RDevUsbcClient::SendEp0StatusPacket()
+	{
+	return DoControl(EControlSendEp0StatusPacket);
+	}
+
+
+inline TInt RDevUsbcClient::HaltEndpoint(TEndpointNumber aEndpoint)
+	{
+	return DoControl(EControlHaltEndpoint, (TAny*) aEndpoint);
+	}
+
+
+inline TInt RDevUsbcClient::ClearHaltEndpoint(TEndpointNumber aEndpoint)
+	{
+	return DoControl(EControlClearHaltEndpoint, (TAny*) aEndpoint);
+	}
+
+
+inline TUint RDevUsbcClient::EndpointZeroMaxPacketSizes()
+	{
+	return DoControl(EControlEndpointZeroMaxPacketSizes);
+	}
+
+
+inline TInt RDevUsbcClient::SetEndpointZeroMaxPacketSize(TInt aMaxPacketSize)
+	{
+	return DoControl(EControlSetEndpointZeroMaxPacketSize, (TAny*) aMaxPacketSize);
+	}
+
+
+inline TInt RDevUsbcClient::GetEndpointZeroMaxPacketSize()
+	{
+	return DoControl(EControlGetEndpointZeroMaxPacketSize);
+	}
+
+
+inline TInt RDevUsbcClient::GetDeviceDescriptor(TDes8& aDeviceDescriptor)
+	{
+	return DoControl(EControlGetDeviceDescriptor, &aDeviceDescriptor);
+	}
+
+
+inline TInt RDevUsbcClient::SetDeviceDescriptor(const TDesC8& aDeviceDescriptor)
+	{
+	return DoControl(EControlSetDeviceDescriptor, const_cast<TDesC8*>(&aDeviceDescriptor));
+	}
+
+
+inline TInt RDevUsbcClient::GetDeviceDescriptorSize(TInt& aSize)
+	{
+	TPckgBuf<TInt> p;
+	TInt r = DoControl(EControlGetDeviceDescriptorSize, &p);
+	if (r == KErrNone)
+		aSize = p();
+	return r;
+	}
+
+
+inline TInt RDevUsbcClient::GetConfigurationDescriptor(TDes8& aConfigurationDescriptor)
+	{
+	return DoControl(EControlGetConfigurationDescriptor, &aConfigurationDescriptor);
+	}
+
+
+inline TInt RDevUsbcClient::SetConfigurationDescriptor(const TDesC8& aConfigurationDescriptor)
+	{
+	return DoControl(EControlSetConfigurationDescriptor, const_cast<TDesC8*> (&aConfigurationDescriptor));
+	}
+
+
+inline TInt RDevUsbcClient::GetConfigurationDescriptorSize(TInt& aSize)
+	{
+	TPckgBuf<TInt> p;
+	TInt r=DoControl(EControlGetConfigurationDescriptorSize, &p);
+	if (r == KErrNone)
+		aSize = p();
+	return r;
+	}
+
+
+inline TInt RDevUsbcClient::GetInterfaceDescriptor(TInt aSettingNumber, TDes8& aInterfaceDescriptor)
+	{
+	return DoControl(EControlGetInterfaceDescriptor,(TAny*) aSettingNumber, &aInterfaceDescriptor);
+	}
+
+
+inline TInt RDevUsbcClient::SetInterfaceDescriptor(TInt aSettingNumber, const TDesC8& aInterfaceDescriptor)
+	{
+	return DoControl(EControlSetInterfaceDescriptor,(TAny*) aSettingNumber,
+					 const_cast<TDesC8*>(&aInterfaceDescriptor));
+	}
+
+
+inline TInt RDevUsbcClient::GetInterfaceDescriptorSize(TInt aSettingNumber, TInt& aSize)
+	{
+	TPckgBuf<TInt> p;
+	TInt r = DoControl(EControlGetInterfaceDescriptorSize,(TAny*) aSettingNumber, &p);
+	if (r == KErrNone)
+		aSize = p();
+	return r;
+	}
+
+
+inline TInt RDevUsbcClient::GetEndpointDescriptor(TInt aSettingNumber, TInt aEndpointNumber,
+												  TDes8& aEndpointDescriptor)
+	{
+	TEndpointDescriptorInfo info = {aSettingNumber, aEndpointNumber, &aEndpointDescriptor};
+	return DoControl(EControlGetEndpointDescriptor, &info, NULL);
+	}
+
+
+inline TInt RDevUsbcClient::SetEndpointDescriptor(TInt aSettingNumber, TInt aEndpointNumber,
+												  const TDesC8& aEndpointDescriptor)
+	{
+	TEndpointDescriptorInfo info = {aSettingNumber, aEndpointNumber, const_cast<TDesC8*>(&aEndpointDescriptor)};
+	return DoControl(EControlSetEndpointDescriptor, &info, NULL);
+	}
+
+
+inline TInt RDevUsbcClient::GetEndpointDescriptorSize(TInt aSettingNumber, TInt aEndpointNumber, TInt& aSize)
+	{
+	TPckgBuf<TInt> p;
+	TEndpointDescriptorInfo info = {aSettingNumber, aEndpointNumber, &p};
+	TInt r = DoControl(EControlGetEndpointDescriptorSize, &info, NULL);
+	if (r == KErrNone)
+		aSize = p();
+	return r;
+	}
+
+
+inline void RDevUsbcClient::GetOtgDescriptorSize(TInt& aSize)
+	{
+	aSize = KUsbDescSize_Otg;
+	}
+
+
+inline TInt RDevUsbcClient::GetOtgDescriptor(TDes8& aOtgDesc)
+	{
+	return DoControl(EControlGetOtgDescriptor, (TAny*)&aOtgDesc);
+	}
+
+
+inline TInt RDevUsbcClient::SetOtgDescriptor(const TDesC8& aOtgDesc)
+	{
+	return DoControl(EControlSetOtgDescriptor, (TAny*)&aOtgDesc);
+	}
+
+
+inline TInt RDevUsbcClient::GetDeviceQualifierDescriptor(TDes8& aDescriptor)
+	{
+	return DoControl(EControlGetDeviceQualifierDescriptor, &aDescriptor);
+	}
+
+
+inline TInt RDevUsbcClient::SetDeviceQualifierDescriptor(const TDesC8& aDescriptor)
+	{
+	return DoControl(EControlSetDeviceQualifierDescriptor, const_cast<TDesC8*>(&aDescriptor));
+	}
+
+
+inline TInt RDevUsbcClient::GetOtherSpeedConfigurationDescriptor(TDes8& aDescriptor)
+	{
+	return DoControl(EControlGetOtherSpeedConfigurationDescriptor, &aDescriptor);
+	}
+
+
+inline TInt RDevUsbcClient::SetOtherSpeedConfigurationDescriptor(const TDesC8& aDescriptor)
+	{
+	return DoControl(EControlSetOtherSpeedConfigurationDescriptor, const_cast<TDesC8*> (&aDescriptor));
+	}
+
+
+inline TInt RDevUsbcClient::GetCSInterfaceDescriptorBlock(TInt aSettingNumber, TDes8& aInterfaceDescriptor)
+	{
+	return DoControl(EControlGetCSInterfaceDescriptor,(TAny*) aSettingNumber, &aInterfaceDescriptor);
+	}
+
+
+inline TInt RDevUsbcClient::GetCSInterfaceDescriptorBlockSize(TInt aSettingNumber, TInt& aSize)
+	{
+	TPckgBuf<TInt> p;
+	TInt r = DoControl(EControlGetCSInterfaceDescriptorSize,(TAny*) aSettingNumber, &p);
+	if (r == KErrNone)
+		aSize = p();
+	return r;
+	}
+
+
+inline TInt RDevUsbcClient::GetCSEndpointDescriptorBlock(TInt aSettingNumber, TInt aEndpointNumber,
+														 TDes8& aEndpointDescriptor)
+	{
+	TEndpointDescriptorInfo info={aSettingNumber, aEndpointNumber, &aEndpointDescriptor};
+	return DoControl(EControlGetCSEndpointDescriptor,&info,NULL);
+	}
+
+
+inline TInt RDevUsbcClient::GetCSEndpointDescriptorBlockSize(TInt aSettingNumber, TInt aEndpointNumber,
+															 TInt& aSize)
+	{
+	TPckgBuf<TInt> p;
+	TEndpointDescriptorInfo info = {aSettingNumber, aEndpointNumber, &p};
+	TInt r = DoControl(EControlGetCSEndpointDescriptorSize, &info, NULL);
+	if (r == KErrNone)
+		aSize = p();
+	return r;
+	}
+
+
+inline TInt RDevUsbcClient::SignalRemoteWakeup()
+	{
+	return DoControl(EControlSignalRemoteWakeup);
+	}
+
+
+inline TInt RDevUsbcClient::DeviceDisconnectFromHost()
+	{
+	return DoControl(EControlDeviceDisconnectFromHost);
+	}
+
+
+inline TInt RDevUsbcClient::DeviceConnectToHost()
+	{
+	return DoControl(EControlDeviceConnectToHost);
+	}
+
+
+inline TInt RDevUsbcClient::PowerUpUdc()
+	{
+	return DoControl(EControlDevicePowerUpUdc);
+	}
+
+
+inline TBool RDevUsbcClient::CurrentlyUsingHighSpeed()
+	{
+	return DoControl(EControlCurrentlyUsingHighSpeed);
+	}
+
+
+inline TInt RDevUsbcClient::SetInterface(TInt aInterfaceNumber, TUsbcInterfaceInfoBuf& aInterfaceData,
+										 TUint32 aBandwidthPriority)
+	{
+	TPtr8 name_8(NULL,0);
+	TUsbcIfcInfo ifcinfo;
+	ifcinfo.iInterfaceData = const_cast<TUsbcInterfaceInfoBuf*>(&aInterfaceData);
+	if (!aInterfaceData().iString)
+		{
+		ifcinfo.iString = NULL;
+		}
+	else
+		{
+		name_8.Set(const_cast<TUint8*>(reinterpret_cast<const TUint8*>(aInterfaceData().iString->Ptr())),
+				   aInterfaceData().iString->Size(), aInterfaceData().iString->Size());
+		ifcinfo.iString = &name_8;
+		}
+	ifcinfo.iBandwidthPriority = aBandwidthPriority;
+	return DoControl(EControlSetInterface, (TAny*)aInterfaceNumber, &ifcinfo);
+	}
+
+
+inline TInt RDevUsbcClient::ReleaseInterface(TInt aInterfaceNumber)
+	{
+	return DoControl(EControlReleaseInterface, (TAny*)aInterfaceNumber);
+	}
+
+
+inline TInt RDevUsbcClient::SetCSInterfaceDescriptorBlock(TInt aSettingNumber, const TDesC8& aInterfaceDescriptor)
+	{
+	TCSDescriptorInfo info = {aSettingNumber, 0, const_cast<TDesC8*>(&aInterfaceDescriptor),
+							  aInterfaceDescriptor.Size()};
+	return DoControl(EControlSetCSInterfaceDescriptor, &info, NULL);
+	}
+
+
+inline TInt RDevUsbcClient::SetCSEndpointDescriptorBlock(TInt aSettingNumber, TInt aEndpointNumber,
+														 const TDesC8& aEndpointDescriptor)
+	{
+	TCSDescriptorInfo info = {aSettingNumber, aEndpointNumber, const_cast<TDesC8*>(&aEndpointDescriptor),
+							  aEndpointDescriptor.Size()};
+	return DoControl(EControlSetCSEndpointDescriptor, &info, NULL);
+	}
+
+
+inline TInt RDevUsbcClient::SetDeviceControl()
+	{
+	return DoControl(EControlSetDeviceControl);
+	}
+
+
+inline TInt RDevUsbcClient::ReleaseDeviceControl()
+	{
+	return DoControl(EControlReleaseDeviceControl);
+	}
+
+
+inline TInt RDevUsbcClient::GetStringDescriptorLangId(TUint16& aLangId)
+	{
+	TPckgBuf<TUint16> p;
+	const TInt r = DoControl(EControlGetStringDescriptorLangId, &p);
+	if (r == KErrNone)
+		aLangId = p();
+	return r;
+	}
+
+
+inline TInt RDevUsbcClient::SetStringDescriptorLangId(TUint16 aLangId)
+	{
+	return DoControl(EControlSetStringDescriptorLangId, (TAny*)(TUint)aLangId);
+	}
+
+
+inline TInt RDevUsbcClient::GetManufacturerStringDescriptor(TDes16& aString)
+	{
+	TPtr8 name_8(const_cast<TUint8*>(reinterpret_cast<const TUint8*>(aString.Ptr())), aString.MaxSize());
+	const TInt r = DoControl(EControlGetManufacturerStringDescriptor, &name_8);
+	aString.SetLength(name_8.Size()/2);
+	return r;
+	}
+
+
+inline TInt RDevUsbcClient::SetManufacturerStringDescriptor(const TDesC16& aString)
+	{
+	TPtrC8 name_8(reinterpret_cast<const TUint8*>(aString.Ptr()), aString.Size());
+	return DoControl(EControlSetManufacturerStringDescriptor, &name_8);
+	}
+
+
+inline TInt RDevUsbcClient::RemoveManufacturerStringDescriptor()
+	{
+	return DoControl(EControlRemoveManufacturerStringDescriptor);
+	}
+
+
+inline TInt RDevUsbcClient::GetProductStringDescriptor(TDes16& aString)
+	{
+	TPtr8 name_8(const_cast<TUint8*>(reinterpret_cast<const TUint8*>(aString.Ptr())), aString.MaxSize());
+	const TInt r = DoControl(EControlGetProductStringDescriptor, &name_8);
+	aString.SetLength(name_8.Size()/2);
+	return r;
+	}
+
+
+inline TInt RDevUsbcClient::SetProductStringDescriptor(const TDesC16& aString)
+	{
+	TPtrC8 name_8(reinterpret_cast<const TUint8*>(aString.Ptr()), aString.Size());
+	return DoControl(EControlSetProductStringDescriptor, &name_8);
+	}
+
+
+inline TInt RDevUsbcClient::RemoveProductStringDescriptor()
+	{
+	return DoControl(EControlRemoveProductStringDescriptor);
+	}
+
+
+inline TInt RDevUsbcClient::GetSerialNumberStringDescriptor(TDes16& aString)
+	{
+	TPtr8 name_8(const_cast<TUint8*>(reinterpret_cast<const TUint8*>(aString.Ptr())), aString.MaxSize());
+	const TInt r = DoControl(EControlGetSerialNumberStringDescriptor, &name_8);
+	aString.SetLength(name_8.Size()/2);
+	return r;
+	}
+
+
+inline TInt RDevUsbcClient::SetSerialNumberStringDescriptor(const TDesC16& aString)
+	{
+	TPtrC8 name_8(reinterpret_cast<const TUint8*>(aString.Ptr()), aString.Size());
+	return DoControl(EControlSetSerialNumberStringDescriptor, &name_8);
+	}
+
+
+inline TInt RDevUsbcClient::RemoveSerialNumberStringDescriptor()
+	{
+	return DoControl(EControlRemoveSerialNumberStringDescriptor);
+	}
+
+
+inline TInt RDevUsbcClient::GetConfigurationStringDescriptor(TDes16& aString)
+	{
+	TPtr8 name_8(const_cast<TUint8*>(reinterpret_cast<const TUint8*>(aString.Ptr())), aString.MaxSize());
+	const TInt r = DoControl(EControlGetConfigurationStringDescriptor, &name_8);
+	aString.SetLength(name_8.Size() / 2);
+	return r;
+	}
+
+
+inline TInt RDevUsbcClient::SetConfigurationStringDescriptor(const TDesC16& aString)
+	{
+	TPtrC8 name_8(reinterpret_cast<const TUint8*>(aString.Ptr()), aString.Size());
+	return DoControl(EControlSetConfigurationStringDescriptor, &name_8);
+	}
+
+
+inline TInt RDevUsbcClient::RemoveConfigurationStringDescriptor()
+	{
+	return DoControl(EControlRemoveConfigurationStringDescriptor);
+	}
+
+
+inline TInt RDevUsbcClient::GetStringDescriptor(TUint8 aIndex, TDes16& aString)
+	{
+	TPtr8 name_8(const_cast<TUint8*>(reinterpret_cast<const TUint8*>(aString.Ptr())), aString.MaxSize());
+	const TInt r = DoControl(EControlGetStringDescriptor, (TAny*)(TUint)aIndex, &name_8);
+	aString.SetLength(name_8.Size() / 2);
+	return r;
+	}
+
+
+inline TInt RDevUsbcClient::SetStringDescriptor(TUint8 aIndex, const TDesC16& aString)
+	{
+	TPtrC8 name_8(reinterpret_cast<const TUint8*>(aString.Ptr()), aString.Size());
+	return DoControl(EControlSetStringDescriptor, (TAny*)(TUint)aIndex, &name_8);
+	}
+
+
+inline TInt RDevUsbcClient::RemoveStringDescriptor(TUint8 aIndex)
+	{
+	return DoControl(EControlRemoveStringDescriptor, (TAny*)(TUint)aIndex);
+	}
+
+
+inline TInt RDevUsbcClient::AllocateEndpointResource(TInt aEndpoint, TUsbcEndpointResource aResource)
+	{
+	return DoControl(EControlAllocateEndpointResource, (TAny*)aEndpoint, (TAny*)aResource);
+	}
+
+
+inline TInt RDevUsbcClient::DeAllocateEndpointResource(TInt aEndpoint, TUsbcEndpointResource aResource)
+	{
+	return DoControl(EControlDeAllocateEndpointResource, (TAny*)aEndpoint, (TAny*)aResource);
+	}
+
+
+inline TBool RDevUsbcClient::QueryEndpointResourceUse(TInt aEndpoint, TUsbcEndpointResource aResource)
+	{
+	return DoControl(EControlQueryEndpointResourceUse, (TAny*)aEndpoint, (TAny*)aResource);
+	}
+
+
+inline void RDevUsbcClient::ReadUntilShort(TRequestStatus &aStatus, TEndpointNumber aEndpoint, TDes8 &aDes)
+	{
+	TInt ep = (aEndpoint < 0 || aEndpoint > KMaxEndpointsPerClient) ? KInvalidEndpointNumber : aEndpoint;
+	TEndpointTransferInfo info = {&aDes, ETransferTypeReadUntilShort, aDes.MaxLength()};
+	DoRequest(ep, aStatus, &info, NULL);
+	}
+
+
+inline void RDevUsbcClient::ReadUntilShort(TRequestStatus &aStatus, TEndpointNumber aEndpoint, TDes8 &aDes,
+										   TInt aLen)
+	{
+	TInt ep = (aEndpoint < 0 || aEndpoint > KMaxEndpointsPerClient) ? KInvalidEndpointNumber : aEndpoint;
+	TEndpointTransferInfo info = {&aDes, ETransferTypeReadUntilShort, aLen};
+	DoRequest(ep, aStatus, &info, NULL);
+	}
+
+
+inline void RDevUsbcClient::ReadOneOrMore(TRequestStatus &aStatus, TEndpointNumber aEndpoint, TDes8 &aDes)
+	{
+	TInt ep = (aEndpoint < 0 || aEndpoint > KMaxEndpointsPerClient) ? KInvalidEndpointNumber : aEndpoint;
+	TEndpointTransferInfo info = {&aDes, ETransferTypeReadOneOrMore, aDes.MaxLength()};
+	DoRequest(ep, aStatus, &info, NULL);
+	}
+
+
+inline void RDevUsbcClient::ReadOneOrMore(TRequestStatus &aStatus, TEndpointNumber aEndpoint, TDes8 &aDes,
+										  TInt aLen)
+	{
+	TInt ep = (aEndpoint < 0 || aEndpoint > KMaxEndpointsPerClient) ? KInvalidEndpointNumber : aEndpoint;
+	TEndpointTransferInfo info = {&aDes, ETransferTypeReadOneOrMore, aLen};
+	DoRequest(ep, aStatus, &info, NULL);
+	}
+
+
+inline void RDevUsbcClient::Read(TRequestStatus &aStatus, TEndpointNumber aEndpoint, TDes8 &aDes)
+	{
+	TInt ep = (aEndpoint < 0 || aEndpoint > KMaxEndpointsPerClient) ? KInvalidEndpointNumber : aEndpoint;
+	TEndpointTransferInfo info = {&aDes, ETransferTypeReadData, aDes.MaxLength()};
+	DoRequest(ep, aStatus, &info, NULL);
+	}
+
+
+inline void RDevUsbcClient::Read(TRequestStatus &aStatus, TEndpointNumber aEndpoint, TDes8 &aDes, TInt aLen)
+	{
+	TInt ep = (aEndpoint < 0 || aEndpoint > KMaxEndpointsPerClient) ? KInvalidEndpointNumber : aEndpoint;
+	TEndpointTransferInfo info = {&aDes, ETransferTypeReadData, aLen};
+	DoRequest(ep, aStatus, &info, NULL);
+	}
+
+
+inline void RDevUsbcClient::ReadPacket(TRequestStatus &aStatus, TEndpointNumber aEndpoint, TDes8 &aDes,
+									   TInt aMaxLen)
+	{
+	TInt ep = (aEndpoint < 0 || aEndpoint > KMaxEndpointsPerClient) ? KInvalidEndpointNumber : aEndpoint;
+	TEndpointTransferInfo info = {&aDes, ETransferTypeReadPacket, aMaxLen};
+	DoRequest(ep, aStatus, &info, NULL);
+	}
+
+
+inline void RDevUsbcClient::Write(TRequestStatus &aStatus, TEndpointNumber aEndpoint, const TDesC8& aDes,
+								  TInt aLen, TBool aZlpRequired)
+	{
+	TInt ep = (aEndpoint < 0 || aEndpoint > KMaxEndpointsPerClient) ? KInvalidEndpointNumber : aEndpoint;
+	TEndpointTransferInfo info = {const_cast<TDesC8*>(&aDes), ETransferTypeWrite, aLen, aZlpRequired};
+	DoRequest(ep, aStatus, &info, NULL);
+	}
+
+
+inline void RDevUsbcClient::AlternateDeviceStatusNotify(TRequestStatus& aStatus, TUint& aValue)
+	{
+	DoRequest(ERequestAlternateDeviceStatusNotify, aStatus, &aValue);
+	}
+
+
+inline void RDevUsbcClient::ReEnumerate(TRequestStatus& aStatus)
+	{
+	DoRequest(ERequestReEnumerate, aStatus);
+	}
+
+
+inline void RDevUsbcClient::EndpointStatusNotify(TRequestStatus& aStatus, TUint& aEndpointMask)
+	{
+	DoRequest(ERequestEndpointStatusNotify, aStatus, &aEndpointMask);
+	}
+
+
+inline void RDevUsbcClient::ReadCancel(TEndpointNumber aEndpoint)
+	{
+	if (aEndpoint < 0 || aEndpoint > KMaxEndpointsPerClient)
+		return;
+	DoCancel(1 << aEndpoint);
+	}
+
+
+inline void RDevUsbcClient::WriteCancel(TEndpointNumber aEndpoint)
+	{
+	ReadCancel(aEndpoint);
+	}
+
+
+inline void RDevUsbcClient::EndpointTransferCancel(TUint aEndpointMask)
+	{
+	/* Mask off non-endpoint cancels */
+	DoCancel(aEndpointMask & ERequestAllCancel);
+	}
+
+
+inline void RDevUsbcClient::AlternateDeviceStatusNotifyCancel()
+	{
+	DoCancel(ERequestAlternateDeviceStatusNotifyCancel);
+	}
+
+
+inline void RDevUsbcClient::ReEnumerateCancel()
+	{
+	DoCancel(ERequestReEnumerateCancel);
+	}
+
+
+inline void RDevUsbcClient::EndpointStatusNotifyCancel()
+	{
+	DoCancel(ERequestEndpointStatusNotifyCancel);
+	}
+
+inline TInt RDevUsbcClient::GetOtgFeatures(TUint8& aFeatures)
+	{
+	TPckgBuf<TUint8> p;
+	TInt r = DoControl(EControlGetOtgFeatures, &p);
+	if (r == KErrNone)
+		aFeatures = p();
+	return r;
+	}
+
+
+inline void RDevUsbcClient::OtgFeaturesNotify(TRequestStatus& aStatus, TUint8& aValue)
+	{
+	DoRequest(ERequestOtgFeaturesNotify, aStatus, &aValue);
+	}
+
+
+inline void RDevUsbcClient::OtgFeaturesNotifyCancel()
+	{
+	DoCancel(ERequestOtgFeaturesNotifyCancel);
+	}
+
+
+#endif // #ifndef __KERNEL_MODE__
+
+#endif // #ifndef __D32USBC_INL__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/public/d32usbcsc.h	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,1558 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\include\d32usbcsc.h
+// User side class definitions for USB Device support.
+// 
+//
+
+/**
+ @file d32usbcsc.h
+ @publishedPartner
+ @released
+*/
+
+#ifndef __D32USBCSC_H__
+#define __D32USBCSC_H__
+
+#include <e32ver.h>
+#include <usb/usb.h>
+#include <usb/d32usbcshared.h>
+
+
+/** This means that SetInterface was called after RealizeInterface had been called.
+    RealizeInterface is meant to signal that all interfaces have been set.
+*/
+const TInt KErrUsbAlreadyRealized = -6813; //Changed from -6713 for future compatibility with the d32usbcshared.h file
+
+const TInt KErrAlternateSettingChanged = -6814;
+
+
+const TUint KChunkCellSize = 1; //1 32 bit integer
+const TInt KEpDescPacketSizeOffset = 4;
+
+/** The user side enpoint number of Endpoint Zero. */
+const TInt KEp0Number = 0;
+
+/* Used in TUsbcScHdrEndpointRecord to describe the endpoint type
+*/
+
+const TUint8 KUsbScHdrEpDirectionIn=1;
+const TUint8 KUsbScHdrEpDirectionOut=2;
+const TUint8 KUsbScHdrEpDirectionBiDir=3;
+
+
+const TUint8 KUsbScHdrEpTypeControl = 0;
+const TUint8 KUsbScHdrEpTypeIsochronous =1;
+const TUint8 KUsbScHdrEpTypeBulk = 2;
+const TUint8 KUsbScHdrEpTypeInterrupt = 3;
+const TUint8 KUsbScHdrEpTypeUnknown = ~0;
+/** Used in the the Shared Chunk Header, to represent an endpoint.
+*/
+class TUsbcScHdrEndpointRecord
+    {
+public:
+    inline TUsbcScHdrEndpointRecord(TInt aBufferNo, TUint8 aType);
+    inline TUint Direction() const;
+    inline TUint Type() const;
+public:
+    TUint8 iBufferNo;
+    TUint8 iType;
+    TUint16 iReserved;
+    };
+
+
+// This is used to hold the geometry of the shared buffers
+class TUsbcScBufferRecord
+    {
+    friend class DLddUsbcScChannel;
+
+public:
+    inline TUint Offset() const;
+    inline TUint Size() const;
+private:
+    inline void Set(TUint aOffset, TUint aEndOffset);
+    TUint iOffset;
+    TUint iSize;
+    };
+
+struct SUsbcScBufferHeader
+    {
+    TInt iHead;        // Where the LDD will next write a transfer
+    TInt iTail;        // Indicates the fist packet that user side is processing (anything prior is disposable)
+    TInt iBilTail;  // This is not used by LDD at all, but just for the BIL's benifit.
+    };
+
+
+struct SUsbcScAlternateSetting
+    {
+    TUint16 iSetting;
+    TUint16 iSequence;
+    };
+
+/** Endpoint pair information.  This can be used to control pairing of endpoint
+for classes that require explicit pairing of endpoint, such as ADC.
+
+This is currently not used.
+*/
+
+class TEndpointPairInfo
+{
+public:
+    TEndpointPairInfo(TUint8 aType=0, TUint16 aPair=0, TUint8 aSpare=0);
+public:
+    TUint8 iType;
+    TUint8 iSpare;
+    TUint16 iPair;
+}; 
+
+/**
+This is the buffer number reserved for use with endpoint zero with the  ReadDataNotify and WriteData methods.
+*/
+const TInt KUsbcScEndpointZero = -1;
+
+/**
+This flag is reserved in TUsbcscEndpointInfo::iFlags, to indicate that the client driver's client wishes reads to operate in a coupled fashion.
+This behaviour is not currently supported.
+*/
+const TUint KUsbScCoupledRead = 0x1;
+
+/**
+This flag, used in parameter aFlag of WriteData, is used to indicate that a ZLP should be sent.
+*/
+const TUint KUsbcScWriteFlagsZlp = 0x0001;
+
+
+// Bit fields used in iFlags of TUsbcScTransferHeader
+
+const TUint KUsbcScShortPacket = 0x0001;
+const TUint KUsbcScStateChange = 0x0004;
+
+class TUsbcScTransferHeader
+{
+public:
+#ifdef _DEBUG
+    TUint iHashId;
+    TUint iSequence;
+#endif
+    TUint iBytes;
+    TUint iFlags;
+    TUint iNext;
+    TUint16 iAltSettingSeq;
+    TInt16 iAltSetting;
+    union
+    {
+        TUint  i[1]; // Extends
+        TUint8 b[4]; // Extends
+    } iData;
+};
+
+/** The desired endpoint capabilities used in RDevUsbcScClient::SetInterface().
+
+This derived class has additional fields used in the shared chunk USB driver.
+*/
+class TUsbcScEndpointInfo: public TUsbcEndpointInfo
+    {
+public:
+    TUsbcScEndpointInfo(TUint aType=UsbShai::KUsbEpTypeBulk, TUint aDir=UsbShai::KUsbEpDirOut, TInt aInterval=0, TInt aExtra=0,
+                                                TUint aBufferSize=0, TUint aReadSize=0);
+
+
+public:
+    /** This indicates the requested size of the endpoint buffer and must be at
+        least as large as iReadSize.
+    */
+    TUint iBufferSize;
+
+    /** This is the amount of data that the LDD reads from the bus before it sets
+        up another read and is normally intended to read many packets.
+    */
+    TUint iReadSize;
+
+    /** TEndpointPairInfo represents pairing information for isochronous endpoints.
+        Should be zero in other cases.  If this specifies paired endpoints then
+        iExtra (in the base class TUsbcEndpointInfo) also needs to be set to the
+        class specific size for this endpoint descriptor (This is here only for future use).
+    */
+    TEndpointPairInfo iPairing;
+    
+    /** The necessary alignment, in bytes, that needs to be applied to the transfer start points
+        of the data.  This is only observed on OUT endpoints.  Zero can be specified to indicate
+        there are no class side requirements for alignment.   The alignment for OUT endpoints is
+        which ever is greater of this field or the USB hardware requirements.
+    */
+    TUint iAlignment;
+
+    /** Flags to indicate how the endpoint should function. None currently defined,
+        but could be used to allow support for direct read.
+    */
+    TUint iFlags;
+    
+    /** Reserved for future use. */
+    TUint32 iReserved2[2];
+    };
+
+/** This must be filled in prior to a call to RDevUsbcClient::SetInterface().
+*/
+class TUsbcScInterfaceInfo
+    {
+public:
+    TUsbcScInterfaceInfo(TInt aClass=0, TInt aSubClass=0, TInt aProtocol=0,
+                       TDesC16* aString=NULL, TUint aTotalEndpoints=0);
+public:
+    /** The class, subclass and protocol that this interface supports. */
+    TUsbcClassInfo iClass;
+    /** The description string for the interface. Used to construct the interface string descriptor. */
+    const TDesC16* iString;
+    /** Total number of endpoints being requested (0-5). Endpoint 0 should not be included in this number. */
+    TUint iTotalEndpointsUsed;
+    /** Desired properties of the endpoints requested.
+        Do NOT include endpoint 0.
+        APIs use endpoint numbers that are offsets into this array.
+    */
+    TUsbcScEndpointInfo iEndpointData[KMaxEndpointsPerClient];
+    /** 32 flag bits used for specifying miscellaneous Interface features.
+        Currently defined are:
+        - KUsbcInterfaceInfo_NoEp0RequestsPlease = 0x00000001
+    */
+    TUint32 iFeatureWord;
+    };
+
+/** Package buffer for a TUsbcInterfaceInfo object.
+
+    @see TUsbcInterfaceInfo
+*/
+typedef TPckgBuf<TUsbcScInterfaceInfo> TUsbcScInterfaceInfoBuf;
+
+struct TUsbcScChunkHdrOffs
+    {
+    TUint iBuffers;
+    TUint iAltSettings;
+    };
+
+
+class TUsbcScChunkBuffersHeader  // Not instantiable
+    {
+    friend class DLddUsbcScChannel;
+    friend class TRealizeInfo;
+
+public:
+    inline TUsbcScBufferRecord* Ep0Out() const;
+    inline TUsbcScBufferRecord* Ep0In() const;
+    inline TUsbcScBufferRecord* Buffers(TInt aBuffer) const;
+    inline TInt NumberOfBuffers() const;
+
+private:
+    TUsbcScChunkBuffersHeader();
+private:
+    TInt iRecordSize;
+    TInt  iNumOfBufs;
+    TUint8 iBufferOffset[8]; // Extends
+    };
+
+struct TUsbcScChunkAltSettingHeader // Not instantiable
+    {
+    TInt iEpRecordSize;
+    TInt iNumOfAltSettings;
+    TUint iAltTableOffset[1]; // Extends
+    };
+
+class TEndpointBuffer;
+
+
+/** The user side handle to the USB client driver.
+*/
+class RDevUsbcScClient : public RBusLogicalChannel
+    {
+public:
+    /** @internalComponent */
+    enum TVer
+        {
+        EMajorVersionNumber = 0,
+        EMinorVersionNumber = 1,
+        EBuildVersionNumber = KE32BuildVersionNumber
+        };
+
+// Bit pattern. s = Request/Control.  c = Cancel,  m = mode bits, B = Buffer number, R = request number.
+//    scmm mmmm |  mmmm mmmm | mmBB BBBB |RRRR RRRR  
+
+    enum TRequest
+        {
+        ERequestWriteData = 1,
+        ERequestReadDataNotify = 2,     
+        ERequestAlternateDeviceStatusNotify = 3,
+        ERequestReEnumerate = 4,
+        ERequestEndpointStatusNotify = 5,
+         ERequestOtgFeaturesNotify = 6,
+        ERequestMaxRequests, // 7
+
+        ERequestCancel = 0x40000000,
+
+        ERequestWriteDataCancel                        = ERequestWriteData                   | ERequestCancel,
+        ERequestReadDataNotifyCancel                = ERequestReadDataNotify              | ERequestCancel,
+        ERequestAlternateDeviceStatusNotifyCancel     = ERequestAlternateDeviceStatusNotify | ERequestCancel,
+        ERequestReEnumerateCancel                     = ERequestReEnumerate                 | ERequestCancel,
+        ERequestEndpointStatusNotifyCancel             = ERequestEndpointStatusNotify        | ERequestCancel,
+        ERequestOtgFeaturesNotifyCancel             = ERequestOtgFeaturesNotify           | ERequestCancel
+        };
+
+    enum TControl
+        {
+        // Changing the order of these enums will break BC.
+        EControlEndpointZeroRequestError,                    // 00
+        EControlEndpointCaps,
+        EControlDeviceCaps,
+        EControlGetAlternateSetting,
+        EControlDeviceStatus,
+        EControlEndpointStatus,
+        EControlSetInterface,
+        EControlReleaseInterface,
+        EControlSendEp0StatusPacket,
+        EControlHaltEndpoint,                                // 09
+        //
+        EControlClearHaltEndpoint,                            // 10
+        EControlSetDeviceControl,
+        EControlReleaseDeviceControl,
+        EControlEndpointZeroMaxPacketSizes,
+        EControlSetEndpointZeroMaxPacketSize,
+        EControlGetDeviceDescriptor,
+        EControlSetDeviceDescriptor,
+        EControlGetDeviceDescriptorSize,
+        EControlGetConfigurationDescriptor,
+        EControlSetConfigurationDescriptor,                    // 19
+        //
+        EControlGetConfigurationDescriptorSize,                // 20
+        EControlGetInterfaceDescriptor,
+        EControlSetInterfaceDescriptor,
+        EControlGetInterfaceDescriptorSize,
+        EControlGetEndpointDescriptor,
+        EControlSetEndpointDescriptor,
+        EControlGetEndpointDescriptorSize,
+        EControlGetCSInterfaceDescriptor,
+        EControlSetCSInterfaceDescriptor,
+        EControlGetCSInterfaceDescriptorSize,                // 29
+        //
+        EControlGetCSEndpointDescriptor,                    // 30
+        EControlSetCSEndpointDescriptor,
+        EControlGetCSEndpointDescriptorSize,
+        EControlSignalRemoteWakeup,
+        EControlGetStringDescriptorLangId,
+        EControlSetStringDescriptorLangId,
+        EControlGetManufacturerStringDescriptor,
+        EControlSetManufacturerStringDescriptor,
+        EControlRemoveManufacturerStringDescriptor,
+        EControlGetProductStringDescriptor,                    // 39
+        //
+        EControlSetProductStringDescriptor,                    // 40
+        EControlRemoveProductStringDescriptor,
+        EControlGetSerialNumberStringDescriptor,
+        EControlSetSerialNumberStringDescriptor,
+        EControlRemoveSerialNumberStringDescriptor,
+        EControlGetConfigurationStringDescriptor,
+        EControlSetConfigurationStringDescriptor,
+        EControlRemoveConfigurationStringDescriptor,
+        EControlDeviceDisconnectFromHost,
+        EControlDeviceConnectToHost,                        // 49
+        //
+        EControlDevicePowerUpUdc,                            // 50
+        EControlDumpRegisters,
+        EControlAllocateEndpointResource,
+        EControlDeAllocateEndpointResource,
+        EControlQueryEndpointResourceUse,
+        EControlGetEndpointZeroMaxPacketSize,
+        EControlGetDeviceQualifierDescriptor,
+        EControlSetDeviceQualifierDescriptor,
+        EControlGetOtherSpeedConfigurationDescriptor,
+        EControlSetOtherSpeedConfigurationDescriptor,        // 59
+        //
+        EControlCurrentlyUsingHighSpeed,                    // 60
+        EControlSetStringDescriptor,
+        EControlGetStringDescriptor,
+        EControlRemoveStringDescriptor,
+        EControlSetOtgDescriptor,
+        EControlGetOtgDescriptor,
+        EControlGetOtgFeatures, 
+        EControlRealizeInterface,
+        EControlStartNextInAlternateSetting    
+        };
+
+
+ // const static TUint KFieldIdPos     = 0;
+    const static TUint KFieldIdMask    = 0xFF;
+    const static TUint KFieldBuffPos   = 8;
+    const static TUint KFieldBuffMask  = 0x3F;
+    const static TUint KFieldFlagsPos  = 14;
+    const static TUint KFieldFlagsMask = 0xFFFF;
+
+
+public:
+
+#ifndef __KERNEL_MODE__
+
+    /** Opens a channel.
+
+        @param aUnit This should be 0 (zero).
+
+        @return KErrNone if successful.
+    */
+    inline TInt Open(TInt aUnit);
+
+    inline TVersion VersionRequired() const;
+
+    /** Stalls ep0 to signal command fault to the host.
+
+        @return KErrNone if successful.
+    */
+    inline TInt EndpointZeroRequestError();
+
+    /** Retrieves the capabilities of all the endpoints on the device.
+
+        Suggested use is as follows:
+
+        @code
+        TUsbcEndpointData data[KUsbcMaxEndpoints];
+        TPtr8 dataPtr(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data));
+        ret = usbPort.EndpointCaps(dataPtr);
+        @endcode
+
+        @param aEpCapsBuf A descriptor encapsulating an array of TUsbcEndpointData.
+
+        @return KErrNone if successful.
+    */
+    inline TInt EndpointCaps(TDes8& aEpCapsBuf);
+
+    /** Retrieves the capabilities of the USB device.
+
+        @see TUsbDeviceCaps
+
+        @param aDevCapsBuf A TUsbDeviceCaps object.
+
+        @return KErrNone if successful.
+    */
+    inline TInt DeviceCaps(TUsbDeviceCaps& aDevCapsBuf);
+
+    /** Copies the current alternate setting for this interface into aInterfaceNumber
+        For USB Interfaces whose main interface is active, this will be 0 (zero).
+
+        @param aInterfaceNumber Current alternate setting for this interface is copied into this.
+
+        @return KErrNone if successful.
+    */
+    inline TInt GetAlternateSetting(TInt& aInterfaceNumber);
+
+    /** Copies the current device status into aDeviceStatus.
+
+        @param aDeviceStatus Current device status is copied into this.
+
+        @return KErrNone if successful
+    */
+    inline TInt DeviceStatus(TUsbcDeviceState& aDeviceStatus);
+
+    /** Copies the current endpoint status into aEndpointStatus.
+
+        @param aEndpoint Endpoint number valid for the current alternate setting.
+        @param aEndpointStatus The current endpoint status, might be stalled, not stalled or unknown.
+
+        @return KErrNone if successful.
+    */
+    inline TInt EndpointStatus(TInt aEndpoint, TEndpointState& aEndpointStatus);
+
+
+    /** Requests that a zero length status packet be sent to the host in response
+        to a class or vendor specific ep0 SETUP packet.
+
+        @return KErrNone if successful.
+    */
+    inline TInt SendEp0StatusPacket();
+
+    /** Stalls endpoint aEndpoint, usually to indicate an error condition with a previous command.
+        The host will normally send a SET_FEATURE command on ep0 to acknowledge and clear the stall.
+
+        @return KErrNone if successful.
+    */
+    inline TInt HaltEndpoint(TInt aEndpoint);
+
+    /** Clears the stall condition on endpoint aEndpoint. This is inluded for symmetry and test purposes.
+
+        @return KErrNone if successful.
+    */
+    inline TInt ClearHaltEndpoint(TInt aEndpoint);
+
+    /** Requests that device control be allocated to this channel.
+
+        @return KErrNone if successful.
+    */
+    inline TInt SetDeviceControl();
+
+    /** Relinquishes device control previously allocated to this channel.
+
+        @return KErrNone if successful.
+    */
+    inline TInt ReleaseDeviceControl();
+
+    /** Returns a bitmap of available ep0 maximum packet sizes.
+
+        @return bitmap of available ep0 maximum packet sizes.
+    */
+    inline TUint EndpointZeroMaxPacketSizes();
+
+    /** Requests that a maximum packet size of aMaxPacketSize be set on ep0.
+
+        @param aMaxPacketSize The maximum packet size.
+
+        @return KErrNone if successful.
+    */
+    inline TInt SetEndpointZeroMaxPacketSize(TInt aMaxPacketSize);
+
+    /** Queries the current maximum packet size on ep0.
+
+        @return The currently set maximum packet size on ep0.
+    */
+    inline TInt GetEndpointZeroMaxPacketSize();
+
+    /** Copies the current device descriptor into aDeviceDescriptor.
+
+        @param aDeviceDescriptor Receives the current device descriptor.
+
+        @return KErrNone if successful.
+    */
+    inline TInt GetDeviceDescriptor(TDes8& aDeviceDescriptor);
+
+    /** Sets the contents of aDeviceDescriptor to be the current device descriptor.
+
+        @param aDeviceDescriptor Contains the device descriptor.
+
+        @return KErrNone if successful.
+    */
+    inline TInt SetDeviceDescriptor(const TDesC8& aDeviceDescriptor);
+
+    /** Gets the size of the current device descriptor. This is unlikely to be anything other than 9.
+
+        @param aSize Receives the size of the current device descriptor.
+
+        @return KErrNone if successful.
+    */
+    inline TInt GetDeviceDescriptorSize(TInt& aSize);
+
+    /** Copies the current configuration descriptor into aConfigurationDescriptor.
+
+        @param aConfigurationDescriptor Receives the current configuration descriptor.
+
+        @return KErrNone if successful.
+    */
+    inline TInt GetConfigurationDescriptor(TDes8& aConfigurationDescriptor);
+
+    /** Sets the contents of aConfigurationDescriptor to be the current configuration descriptor.
+
+        @param aConfigurationDescriptor Contains the configuration descriptor.
+
+        @return KErrNone if successful.
+    */
+    inline TInt SetConfigurationDescriptor(const TDesC8& aConfigurationDescriptor);
+
+    /** Gets the size of the current configuration descriptor.
+
+        @param aSize Receives the size of the current configuration descriptor.
+
+        @return KErrNone if successful.
+    */
+    inline TInt GetConfigurationDescriptorSize(TInt& aSize);
+
+    /** Copies the interface descriptor into aInterfaceDescriptor for the interface with alternate
+        setting aSettingNumber, 0 for the main interface.
+
+        @param aSettingNumber Alternate setting number on the interface, 0 for the main interface.
+        @param aInterfaceDescriptor Receives the interface descriptor.
+
+        @return KErrNone if successful.
+    */
+    inline TInt GetInterfaceDescriptor(TInt aSettingNumber, TDes8& aInterfaceDescriptor);
+
+    /** Sets the interface descriptor contained in aInterfaceDescriptor for the interface with
+        alternate setting aSettingNumber, 0 for the main interface, for transmission to the host
+        during enumeration.
+
+        @param aSettingNumber Alternate setting number on the interface, 0 for the main interface.
+        @param aInterfaceDescriptor Contains the interface descriptor to be set.
+
+        @return KErrNone if successful.
+    */
+    inline TInt SetInterfaceDescriptor(TInt aSettingNumber, const TDesC8& aInterfaceDescriptor);
+
+    /** Copies the size of the interface descriptor for the interface with alternate
+        setting aSettingNumber, 0 for the main interface, into aSize.
+
+        @param aSettingNumber The alternate setting.
+        @param aSize receives the size of the interface descriptor.
+
+        @return KErrNone if successful.
+    */
+    inline TInt GetInterfaceDescriptorSize(TInt aSettingNumber, TInt& aSize);
+
+    /** Copies the endpoint descriptor for logical endpoint number aEndpointNumber into aEndpointDescriptor
+        for the interface with alternate setting aSettingNumber, 0 for the main interface.
+
+        @param aSettingNumber Alternate setting number on the interface, 0 for the main interface.
+        @param aEndpointNumber The endpoint number of the endpoint.
+        @param aEndpointDescriptor Receives the endpoint descriptor.
+
+        @return KErrNone if successful.
+    */
+    inline TInt GetEndpointDescriptor(TInt aSettingNumber, TInt aEndpointNumber, TDes8& aEndpointDescriptor);
+
+    /** Sets the endpoint descriptor for logical endpoint number aEndpointNumber contained in
+        aEndpointDescriptor for the interface with alternate setting aSettingNumber, 0 for the main interface,
+        for transmission to the host during enumeration.
+
+        @param aSettingNumber Alternate setting number on the interface, 0 for the main interface.
+        @param aEndpointNumber Valid endpoint number on this interface.
+        @param aEndpointDescriptor Contains the endpoint descriptor to be set.
+
+        @return KErrNone if successful.
+    */
+    inline TInt SetEndpointDescriptor(TInt aSettingNumber, TInt aEndpointNumber,
+                                      const TDesC8& aEndpointDescriptor);
+
+    /** Copies the size of the endpoint descriptor for logical endpoint number aEndpointNumber for the
+        interface with alternate setting aSettingNumber, 0 for the main interface, into aSize.
+
+        @param aSettingNumber Alternate setting number on the interface, 0 for the main interface.
+        @param aEndpointNumber Valid endpoint number on this interface.
+        @param aSize Receives the size of the endpoint descriptor.
+
+        @return KErrNone if successful.
+    */
+    inline TInt GetEndpointDescriptorSize(TInt aSettingNumber, TInt aEndpointNumber, TInt& aSize);
+
+    /** Get OTG descriptor size
+
+        @param aSize TInt Reference which contains OTG descriptor size on return.
+    */
+    inline void GetOtgDescriptorSize(TInt& aSize);
+
+    /** Get OTG descriptor of USB on-the-go feature.
+
+        @param aOtgDesc User-side buffer to store copy of descriptor.
+
+        @return KErrNone if successful.
+    */
+    inline TInt GetOtgDescriptor(TDes8& aOtgDesc);
+
+    /** Set OTG descriptor by user to enable/disable USB on-the-go feature.
+
+        @param aOtgDesc Descriptor buffer containing OTG features.
+
+        @return KErrNone if successful.
+    */
+    inline TInt SetOtgDescriptor(const TDesC8& aOtgDesc);
+
+    /** Copies the current device_qualifier descriptor into aDescriptor.
+
+        @param aDescriptor Receives the current device_qualifier descriptor.
+
+        @return KErrNone if successful.
+    */
+    inline TInt GetDeviceQualifierDescriptor(TDes8& aDescriptor);
+
+    /** Sets the device_qualifier descriptor to the contents of aDescriptor.
+
+        @param aDescriptor Contains the new device_qualifier descriptor.
+
+        @return KErrNone if successful.
+    */
+    inline TInt SetDeviceQualifierDescriptor(const TDesC8& aDescriptor);
+
+    /** Copies the current other_speed_configuration descriptor into aDescriptor.
+
+        @param aDescriptor Receives the current other_speed_configuration descriptor.
+
+        @return KErrNone if successful.
+    */
+    inline TInt GetOtherSpeedConfigurationDescriptor(TDes8& aDescriptor);
+
+    /** Sets the other_speed_configuration descriptor to the contents of aDescriptor.
+
+        @param aDescriptor Contains the new other_speed_configuration descriptor.
+
+        @return KErrNone if successful.
+    */
+    inline TInt SetOtherSpeedConfigurationDescriptor(const TDesC8& aDescriptor);
+
+    /** Copies the class specific interface descriptor block into aInterfaceDescriptor for the interface
+        with alternate setting aSettingNumber, 0 for the main interface.
+
+        @param aSettingNumber Alternate setting number on the interface, 0 for the main interface.
+        @param aInterfaceDescriptor Contains the interface descriptor to be set.
+
+        @return KErrNone if successful.
+    */
+    inline TInt GetCSInterfaceDescriptorBlock(TInt aSettingNumber, TDes8& aInterfaceDescriptor);
+
+    /** aSettingNumber is the alternate interface setting, 0 for the main interface, that the descriptor block
+        aDes should be attached to. aDes is a block of data containing at least one class specific descriptor
+        for transmission during enumeration after the class interface descriptor (or alternate interface
+        descriptor) has been sent, but before the endpoint descriptors belonging to this interface are sent.
+        aDes may contain as many descriptors as are necessary or only one. SetCSInterfaceDescriptorBlock()
+        should be called at any time after SetInterface() has been called to establish a main interface or an
+        alternate interface. More than one call may be made - the data blocks will be concatenated prior to
+        sending. No checking or validation of the contents of aDes will be made and it is the caller's
+        responsibility to ensure that the data supplied is correct and appropriate to the interface identified
+        by aSettingNumber.
+
+        @param aSettingNumber Alternate setting number on the interface, 0 for the main interface.
+        @param aInterfaceDescriptor Contains the interface descriptor to be set.
+
+        @return KErrNone if successful.
+    */
+    inline TInt SetCSInterfaceDescriptorBlock(TInt aSettingNumber, const TDesC8& aInterfaceDescriptor);
+
+    /** Copies the size of the class specific interface descriptor block for the interface with alternate
+        setting aSettingNumber, 0 for the main interface, into aSize.
+
+        @param aSettingNumber The alternate setting number.
+        @param aSize receives the size of the interface descriptor.
+
+        @return KErrNone if successful.
+    */
+    inline TInt GetCSInterfaceDescriptorBlockSize(TInt aSettingNumber, TInt& aSize);
+
+    /** Copies the class specific endpoint descriptor for logical endpoint number aEndpointNumber
+        into aEndpointDescriptor for the interface with alternate setting aSettingNumber, 0 for the main
+        interface.
+
+        @param aSettingNumber Alternate setting number on the interface, 0 for the main interface.
+        @param aEndpointNumber Valid endpoint number on this interface.
+        @param aEndpointDescriptor Receives the endpoint descriptor.
+
+        @return KErrNone if successful.
+    */
+    inline TInt GetCSEndpointDescriptorBlock(TInt aSettingNumber, TInt aEndpointNumber,
+                                             TDes8& aEndpointDescriptor);
+
+    /** Sets the class specific endpoint descriptor for logical endpoint number aEndpointNumber contained in
+        aEndpointDescriptor for the interface with alternate setting aSettingNumber, 0 for the main interface,
+        for transmission to the host during enumeration.
+
+        @param aSettingNumber Alternate setting number on the interface, 0 for the main interface.
+        @param aEndpointNumber Valid endpoint number on this interface.
+        @param aEndpointDescriptor Contains the endpoint descriptor to be set.
+
+        @return KErrNone if successful.
+    */
+    inline TInt SetCSEndpointDescriptorBlock(TInt aSettingNumber, TInt aEndpointNumber,
+                                             const TDesC8& aEndpointDescriptor);
+
+    /** Copies the size of the class specific endpoint descriptor block for logical endpoint number
+        aEndpointNumber for the interface with alternate setting aSettingNumber, 0 for the main interface,
+        into aSize.
+
+        @param aSettingNumber Alternate setting number on the interface, 0 for the main interface.
+        @param aEndpointNumber Valid endpoint number on this interface.
+        @param aSize On return, contains the size of the class specific endpoint descriptor block.
+
+        @return KErrNone if successful.
+    */
+    inline TInt GetCSEndpointDescriptorBlockSize(TInt aSettingNumber, TInt aEndpointNumber, TInt& aSize);
+
+    /** Generates a Remote Wakeup bus condition.
+        The capability of the device to generate Remote Wakeup signalling is enquired in
+        RDevUsbcClient::DeviceCaps.
+
+        @return KErrNone if this signalling is possible and the signal has been generated.
+    */
+    inline TInt SignalRemoteWakeup();
+
+    /** Simulates a physical removal of the USB cable by disabling the D+/- pull-ups.The iConnect member of
+        TUsbDeviceCapsV01, returned by RDevUsbcClient::DeviceCaps(), indicates whether this functionality is
+        supported.
+
+        @return KErrNone if successful.
+    */
+    inline TInt DeviceDisconnectFromHost();
+
+    /** Simulates a physical insertion of the USB cable by enabling the D+/- pull-ups.The iConnect member
+        of TUsbDeviceCapsV01, returned by RDevUsbcClient::DeviceCaps(),  indicates whether this functionality
+        is supported.
+
+        @return KErrNone if successful.
+    */
+    inline TInt DeviceConnectToHost();
+
+    /** Powers up the UDC and connects it to the bus if one or more interfaces exist.
+
+        @return KErrNone if UDC successfully powered up, KErrNotReady if no
+        interfaces have been registered yet, KErrHardwareNotAvailable if UDC
+        couldn't be activated.
+    */
+    inline TInt PowerUpUdc();
+
+    /** Enquires about the current operating speed of the UDC.
+
+        @return ETrue if the UDC is currently operating at High speed, EFalse otherwise.
+    */
+    inline TBool CurrentlyUsingHighSpeed();
+
+    /** Allocates the use of aResource to aEndpoint. It will be used from when the current bus transfer    has been
+        completed.
+
+        @param aResource is typically some rationed hardware resource or possibly specifies a type of endpoint
+        behaviour. aResource is not a bitmap and TEndpointResource values should not be combined.
+        @param aEndpoint The endpoint number to which the resource is to be allocated.
+
+        @return KErrNone if successful, KErrInUse if the resource is already consumed and cannot be allocated,
+        KErrNotSupported if the endpoint does not support the resource requested.
+
+        @publishedPartner @deprecated
+    */
+    inline TInt AllocateEndpointResource(TInt aEndpoint, TUsbcEndpointResource aResource);
+
+    /** Deallocates the use of aResource aEndpoint or ends a specified endpoint behaviour.
+
+        @param aResource is typically some rationed hardware resource or possibly specifies a type of endpoint
+        behaviour. aResource is not a bitmap and TEndpointResource values should not be combined.
+        @param aEndpoint The endpoint number from which the resource is to be removed.
+
+        @return KErrNone if the resource has been successfully deallocated, KErrNotSupported if the endpoint
+        does not support the resource requested.
+
+        @publishedPartner @deprecated
+    */
+    inline TInt DeAllocateEndpointResource(TInt aEndpoint, TUsbcEndpointResource aResource);
+
+    /** Queries endpoint resource use.
+
+        @param aResource is typically some rationed hardware resource or possibly specifies a type of endpoint
+        behaviour. aResource is not a bitmap and TEndpointResource values should not be combined.
+        @param aEndpoint The endpoint number at which the resource is to be queried.
+
+        @return ETrue is the specified resource is in use at the endpoint and EFalse if not.
+    */
+    inline TBool QueryEndpointResourceUse(TInt aEndpoint, TUsbcEndpointResource aResource);
+
+    /** Request (i.e. claim for this channel) up to five endpoints and set the class type for this USB
+        interface. 'aInterfaceData' is a package buffer which describes the interface and all the endpoints
+        being requested by the driver for this interface.
+
+        @param aInterfaceNumber Distinguishes between alternate interfaces. If these are not be used then this
+        should always be zero. If this parameter is used, then its value must be one more than that of the
+        proceeding alternate interface.
+        @param aInterfaceData A package buffer which describes the interface and all the endpoints being
+        requested by the driver for this interface.
+
+
+        @return KErrInUse if any of the endpoints being requested have already been claimed by another channel.
+        KErrNotSupported if an endpoint with all of the specified properties is not supported on this
+        platform. KErrNoMemory if insufficient memory is available to complete the operation.
+    */
+    inline TInt SetInterface(TInt aInterfaceNumber, TUsbcScInterfaceInfoBuf& aInterfaceData);
+
+
+    /**
+        This method should be called after SetInterface has been called for all possible alternative settings.
+        Calling this invalidates further calls to SetInterface. On success, a chunk handle is created and
+        passed back though aChunk.   This is needed for the user side to access the shared chunk where the
+        data is stored.  Note that if you are using the BIL (described later), then FinalizeInterface (...)
+        should be used instead, which will call this method.
+        
+        @return KErrNone on successful completion, or one of the system wide error codes.
+    */
+    inline TInt RealizeInterface(RChunk& aChunk);
+
+
+    /** Release an interface previously claimed by this channel. Alternate interfaces need to be released
+        in strict descending order, starting with the last (i.e. highest numbered) one.
+        It is not necessary to release an interface that wasn't successfully requested.
+
+        @param aInterfaceNumber Specifies the alternate setting number 'aInterfaceNum' of the interface to be
+        released.
+
+        @return KErrNone if successful. KErrArgument if the alternate setting doesn't exist or is released out
+        of order.
+    */
+    inline TInt ReleaseInterface(TInt aInterfaceNumber);
+
+    /** Copies the current string descriptor language ID (LANGID) code into the aLangId argument. Even though
+        the USB spec allows for the existence of a whole array of LANGID codes, we only support one.
+
+        @param aLangId Receives the LANGID code.
+
+        @return KErrNone if successful, KErrArgument if problem with argument (memory cannot be written to, etc.).
+    */
+    inline TInt GetStringDescriptorLangId(TUint16& aLangId);
+
+    /** Sets the string descriptor language ID (LANGID). Even though the USB spec allows for the existence of
+        a whole array of LANGID codes, we only support one.
+
+        @param aLangId The LANGID code to be set.
+
+        @return KErrNone if successful.
+    */
+    inline TInt SetStringDescriptorLangId(TUint16 aLangId);
+
+    /** Copies the string descriptor identified by the iManufacturer index field of the Standard Device
+        Descriptor into the aString argument.
+
+        @param aString Receives manufacturer string.
+
+        @return KErrNone if successful, KErrArgument if MaxLength of aString is too small to hold the entire
+        descriptor, KErrNotFound if the string descriptor couldn't be found.
+    */
+    inline TInt GetManufacturerStringDescriptor(TDes16& aString);
+
+    /** Sets the string descriptor identified by the iManufacturer index field of the Standard Device
+        Descriptor to the aString argument.
+
+        @param aString Contains the new manufacturer string descriptor.
+
+        @return KErrNone if successful, KErrNoMemory if no memory is available to store the new string from
+        aString (in which case the old string descriptor will be preserved).
+    */
+    inline TInt SetManufacturerStringDescriptor(const TDesC16& aString);
+
+    /** Removes (deletes) the string descriptor identified by the iManufacturer index field of the Standard
+        Device Descriptor and sets that field to zero.
+
+        @return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found.
+    */
+    inline TInt RemoveManufacturerStringDescriptor();
+
+    /** Retrieves the string descriptor identified by the iProduct index field of the Standard Device
+        Descriptor into the aString argument.
+
+        @param aString Receives product string.
+
+        @return KErrNone if successful, KErrArgument if MaxLength of aString is too small to hold the entire
+        descriptor, KErrNotFound if the string descriptor couldn't be found.
+    */
+    inline TInt GetProductStringDescriptor(TDes16& aString);
+
+    /** Sets the string descriptor identified by the iProduct index field of the Standard Device Descriptor to
+        the aString argument.
+
+        @param aString Contains the new product string descriptor.
+
+        @return KErrNone if successful, KErrNoMemory if no memory is available to store the new string from
+        aString (in which case the old string descriptor will be preserved).
+    */
+    inline TInt SetProductStringDescriptor(const TDesC16& aString);
+
+    /** Removes (deletes) the string descriptor identified by the iProduct index field of the Standard Device
+        Descriptor and sets that field to zero.
+
+        @return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found.
+    */
+    inline TInt RemoveProductStringDescriptor();
+
+    /** Retrieves the string descriptor identified by the iSerialNumber index field of the Standard Device
+        Descriptor into the aString argument.
+
+        @param aString Receives product string.
+
+        @return KErrNone if successful, KErrArgument if MaxLength of aString is too small to hold the entire
+        descriptor, KErrNotFound if the string descriptor couldn't be found.
+    */
+    inline TInt GetSerialNumberStringDescriptor(TDes16& aString);
+
+    /** Sets the string descriptor identified by the iSerialNumber index field of the Standard Device
+        Descriptor to the aString argument.
+
+        @param aString Contains the new serial number string descriptor.
+
+        @return KErrNone if successful, KErrNoMemory if no memory is available to store the new string from
+        aString (in which case the old string descriptor will be preserved).
+    */
+    inline TInt SetSerialNumberStringDescriptor(const TDesC16& aString);
+
+    /** Removes (deletes) the string descriptor identified by the iSerialNumber index field of the Standard
+        Device Descriptor and sets that field to zero.
+
+        @return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found.
+    */
+    inline TInt RemoveSerialNumberStringDescriptor();
+
+    /** Retrieves the string descriptor identified by the iConfiguration index field of the (first) Standard
+        Configuration Descriptor into the aString argument.
+
+        @param aString Receives configuration string.
+
+        @return KErrNone if successful, KErrArgument if MaxLength of aString is too small to hold the entire
+        descriptor, KErrNotFound if the string descriptor couldn't be found.
+    */
+    inline TInt GetConfigurationStringDescriptor(TDes16& aString);
+
+    /** Sets the string descriptor identified by the iConfiguration index field of the Standard Configuration
+        Descriptor to the aString argument.
+
+        @param aString Contains the new serial number string descriptor.
+
+        @return KErrNone if successful, KErrNoMemory if no memory is available to store the new string from
+        aString (in which case the old string descriptor will be preserved).
+    */
+    inline TInt SetConfigurationStringDescriptor(const TDesC16& aString);
+
+    /** Removes (deletes) the string descriptor identified by the iConfiguration index field of the Standard
+        Configuration Descriptor and sets that field to zero.
+
+        @return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found.
+    */
+    inline TInt RemoveConfigurationStringDescriptor();
+
+    /** Copies the string of the USB string descriptor at the specified index in the string descriptor array
+        into the aString argument.
+
+        Although this function can also be used for it, for querying most standard string descriptors
+        there exists a set of dedicated access functions.
+
+        @see RDevUsbcClient::GetStringDescriptorLangId
+        @see RDevUsbcClient::GetManufacturerStringDescriptor
+        @see RDevUsbcClient::GetProductStringDescriptor
+        @see RDevUsbcClient::GetSerialNumberStringDescriptor
+        @see RDevUsbcClient::GetConfigurationStringDescriptor
+
+        @param aIndex The position of the string descriptor in the string descriptor array.
+        @param aString The target location for the string descriptor copy.
+
+        @return KErrNone if successful, KErrNotFound if no string descriptor exists at the specified index,
+        KErrArgument if MaxLength() of aString is too small to hold the entire descriptor.
+    */
+    inline TInt GetStringDescriptor(TUint8 aIndex, TDes16& aString);
+
+    /** Sets the aString argument to be the string of a USB string descriptor at the specified index in the
+        string descriptor array. If a string descriptor already exists at that position then its string will
+        be replaced.
+
+        Care should be taken, when choosing aIndex, not to inadvertently overwrite one of the standard
+        string descriptors.    For their manipulation there exists a set of dedicated access functions.
+
+        @see RDevUsbcClient::SetStringDescriptorLangId
+        @see RDevUsbcClient::SetManufacturerStringDescriptor
+        @see RDevUsbcClient::SetProductStringDescriptor
+        @see RDevUsbcClient::SetSerialNumberStringDescriptor
+        @see RDevUsbcClient::SetConfigurationStringDescriptor
+
+        @param aIndex The position of the string descriptor in the string descriptor array.
+        @param aString Contains the string descriptor to be set.
+
+        @return KErrNone if successful, KErrArgument if aIndex is invalid, KErrNoMemory if no memory
+        is available to store the new string (an existing descriptor at that index will be preserved).
+    */
+    inline TInt SetStringDescriptor(TUint8 aIndex, const TDesC16& aString);
+
+    /** Removes (deletes) the USB string descriptor at the specified index in the string descriptor array.
+        The position in the array of other string descriptors is not affected.
+
+        Care should be taken, when choosing aIndex, not to inadvertently delete a standard string descriptor
+        (also because index references from non-string descriptors would be invalidated). For the deletion
+        of most standard string descriptors there exists a set of dedicated functions.
+
+        @see RDevUsbcClient::RemoveManufacturerStringDescriptor
+        @see RDevUsbcClient::RemoveProductStringDescriptor
+        @see RDevUsbcClient::RemoveSerialNumberStringDescriptor
+        @see RDevUsbcClient::RemoveConfigurationStringDescriptor
+
+        @param aIndex The position of the string descriptor in the string descriptor array.
+
+        @return KErrNone if successful, KErrNotFound if no string descriptor exists at the specified index.
+    */
+    inline TInt RemoveStringDescriptor(TUint8 aIndex);
+
+
+
+    /**  Requests notification for when there is data available on the buffer indicated.  If the buffer
+         already has data in it, it will return immediately, otherwise it will block until there is.
+
+    If the BIL methods are being used (recommended), then this method should not be called directly,
+    using TEndpointBuffer::GetBuffer instead.
+
+    @param aBufferNumber Indicates the buffer for which the caller wishes to know about data 
+    additions.  The buffer needed of any given endpoint can be found by inspecting the alternative
+    setting table, in the chunk header.  The location of the buffer can be found by looking at the
+    buffer offset table, also in the chunk header. 
+
+    @param aStatus The request status where notification of completion is directed. KErrCancel is
+    returned if the asynchronous operation was cancelled.
+
+    @param aLength A preference for the quantity of data to be read.  This value is only a 
+    suggestion and my be ignored.  The default value of 0 indicates no preference.
+
+    @return KErrNone on success, or KErrArgument if the buffer number is invalid.    
+    */
+    inline TInt ReadDataNotify(TInt aBufferNumber, TRequestStatus& aStatus, TInt aLength=0);
+
+
+    /**  Requests the LDD to write the contents of the given buffer to the USB hardware.  Notification is
+    given when this is complete.  More then one write request can be queued on any one endpoint, to allow
+    for less Hardware idling between buffers.
+
+    If the BIL methods are being used (recommended), then this method should not be called directly,
+    using TEndpointBuffer::WriteBuffer instead.
+
+    @param aBufferNumber represents the buffer number of the buffer of which the caller has placed the
+    data. As described with ReadDataNotify(...), details of the buffers can be found in the chunk header.
+
+    @param aStart Represents the start offset of the data within the chunk.  This start location must be
+    aligned to a multiple of the maximum packet size for the endpoint, so that the data can be DMAed
+    straight out of the buffer.
+
+    @param aLength Represents the amount of data to be sent to the host in bytes.
+
+    @param aFlags Is a bitfield, where bit 0 should be set if a ZLP is to be sent to the host after the
+    current transaction.  All other bits are reserved for future use.
+*/
+    inline void WriteData(TInt aBufferNumber, TUint aStart, TUint aLength, TUint aFlags, TRequestStatus& aStatus);
+
+
+
+    /** Cancels an outstanding read request on endpoint buffer aBufferNumber.
+
+        @param aBufferNumber The endpoint buffer number whose read is to be cancelled.
+    */
+    inline void ReadCancel(TInt aBufferNumber);
+
+
+    /** Cancels an outstanding write request on endpoint buffer aBufferNumber.
+
+        @param aBufferNumber The endpoint buffer number whose write is to be cancelled.
+    */
+    inline void WriteCancel(TInt aBufferNumber);
+
+    /** Cancels any transfer on any endpoint buffer specified in aBufferMask.
+
+        @code
+        // Cancel transfer requests on buffers 1, 2, 3 & 4
+        usbPort.EndpointTransferCancel(1 | 2 | 4 | 8);
+        @endcode
+
+        @param aBufferMask bitmap of the endpoint buffer numbers.
+    */
+    inline void EndpointTransferCancel(TUint aBufferMask);
+
+    /**    Register for notification when a change of the Interface alternate setting or the USB Controller's
+        current state occurs. When the alternate setting or the Controller state changes, then the
+        asynchronous function completes and the current alternate setting number or Controller state is
+        written back to aValue. If the KUsbAlternateSetting bit is set then the remaining bits are the
+        alternate setting number. Otherwise aValue is interpreted as a TUsbcDeviceState.
+
+        @see TUsbcDeviceState
+
+        @param aStatus The request status.
+        @param aValue Receives the alternate setting number or Controller state.
+    */
+    inline void AlternateDeviceStatusNotify(TRequestStatus& aStatus, TUint& aValue);
+
+    /** Completes an AlternateDeviceStatusNotify request. If a request has previously been made then the
+        status variable is updated with the current device state.
+    */
+    inline void AlternateDeviceStatusNotifyCancel();
+
+    /** If the channel has changed the grouping of endpoints between interfaces or changed the interface class
+        type from the defaults then it is necessary to force a re-enumeration. This will typically involve the
+        Symbian OS device initiating a disconnection and re-connection. This is an asynchronous operation
+        which will complete when the Controller is successfully configured by the host, i.e. has achieved
+        UsbShai::EUsbPeripheralStateConfigured.  Since it is not known if the operation has failed, at the same time that
+        a ReEnumerate request is made, a timer should be set up to complete after approximately 5 seconds. It
+        can be assumed that if the operation has not completed after this time interval then it will not
+        complete.
+
+        @param aStatus The request status.
+    */
+    inline void ReEnumerate(TRequestStatus& aStatus);
+
+    /** Cancels an outstanding ReEnumerate() request.
+    */
+    inline void ReEnumerateCancel();
+
+    /**    Register for notification when a change in stall status of any of the interface's endpoints occurs,
+        but not ep0. When a change in stall status occurs, then the asynchronous function completes and the
+        current stall state is written back to 'aEndpointStatus' as a bit map: Only stall state changes caused
+        by SET_FEATURE and CLEAR_FEATURE standard commands on ep0 will be notified when this function
+        completes. After this request completes the request should be re-issued to obtain future
+        notifications.
+
+        @param aStatus The request status.
+        @param aEndpointMask A bitmap of the endpoints' stall status. This is filled in when the call completes.
+        bit 1 represents the interface's virtual endpoint 1, (KUsbcEndpoint1Bit)
+        bit 2 represents the interface's virtual endpoint 2, (KUsbcEndpoint2Bit) etc.
+        bit value 0 - not stalled,
+        bit value 1 - stalled.
+    */
+    inline void EndpointStatusNotify(TRequestStatus& aStatus, TUint& aEndpointMask);
+
+    /** Completes an endpoint status notify request.
+    */
+     inline void EndpointStatusNotifyCancel();
+
+    /** Get current on-the-go features relating to the ability of device/host pair to
+        perform OTG role swap.
+
+        @param aFeatures On return it contains features the device currently has.
+                bit 2 represents b_hnp_enable,       (KUsbOtgAttr_B_HnpEnable)
+                bit 3 represents a_hnp_support,      (KUsbOtgAttr_A_HnpSupport)
+                bit 4 represents a_alt_hnp_support,  (KUsbOtgAttr_A_AltHnpSupport)
+        @return KErrNone if successful, KErrNotSupported if OTG is not supported by
+                this device, otherwise system-wide error returns.
+    */
+    inline TInt GetOtgFeatures(TUint8& aFeatures);
+
+    /** Register for notification on USB on-the-go features' change. If any OTG feature
+        is changed, request completes and current feature value is filled in aValue.
+
+        @param aStatus Request status object.
+        @param aValue On request completion, contains current OTG feature value.
+    */
+    inline void OtgFeaturesNotify(TRequestStatus& aStatus, TUint8& aValue);
+
+    /** Cancel pending OTG feature request.
+    */
+    inline void OtgFeaturesNotifyCancel();
+
+    /**    This function retrieves the alternate setting that the WriteData function can
+        write to.  After a host sets the alternate setting, writes to the IN endpoint
+        are not permitted by the LDD until this method has been called.
+        This function is not asynchronous nor blocking, and should not be used to
+        detect that an alternate setting has happened.
+
+        If the BIL methods are being used (recommended), then this method should not be called directly. 
+
+        @return The alternative setting number or KErrInUse if the current alternative
+         setting is already in use, that is to say that the alternative setting has not changed.
+    */
+    inline TInt StartNextInAlternateSetting();
+
+
+    /*******************************\
+    *  Buffer Interface Layer (BIL) *
+    \*******************************/
+
+    // This following functions, as well as the ones in TEndpointBuffer (below), 
+    // can be considered the BIL.
+
+
+    /**
+    Finalize the interface, creating a chunk for use with reading/writing to endpoints.
+    FinalizeInterface should be called after all alternate interfaces have been set up with SetInteface.
+    Any attempt to call SetInterface after this stage will fail.
+
+    @return        KErrNone if operation is successfull
+                System wide error codes if chunk creation failed
+    */
+    IMPORT_C TInt FinalizeInterface();
+
+    /**
+    Finalize the interface, creating a chunk for use with reading/writing to endpoints. This 
+    version of the method provides a handle to the chunk, which is needed if the
+    buffer is to be passed and used by other processes. 
+    FinalizeInterface should be called after all alternate interfaces have been set up with SetInteface.
+    Any attempt to call SetInterface after this stage will fail.
+
+    @param    aChunk    On success aChunk points to the created chunk.
+    @return            KErrNone if operation is successfull
+                    System wide error codes if chunk creation failed
+    */
+    IMPORT_C TInt FinalizeInterface(RChunk*& aChunk);
+
+    /**
+    Opens an endpoint, an endpoint should be opened before any operations are attempted on it.
+
+    @param    aEpB    On success aEpB will be filled with the relevant details for that endpoint    
+    @param    aEpI    endpoint number to be opened
+    @return            KErrNone if operation is successfull
+                    KErrNotFound if endpoint number is not valid for current alternate setting
+                    KErrInUse if endpoint is already opened
+                    KErrArgument if endpoint buffer argument passed is already in existence and being used
+    */
+    IMPORT_C TInt OpenEndpoint(TEndpointBuffer & aEpB, TInt aEpI);
+
+    /**
+    Switches to processing from one Alternate setting to the next. All open endpoints (except EP0) must
+    be close before this can be called.
+
+    @param    aFlush    If ETrue, the method will purge the buffers of any data unread for the old setting.
+                    If each endpoint was not read up until KErrEof was reached, then this should be set.
+                     
+    @return        the alternate Setting if operation is successful
+                KErrInUse if any endpoints in present alternate setting is still open (except Ep0)
+                KErrNotReady if there is no change in alternate setting
+                KErrInUse if StartNextInAlternateSetting detects no change in alternate setting.
+                KErrCorrupt if the buffer structure becomes corrupt.
+    */
+    IMPORT_C TInt StartNextOutAlternateSetting(TBool aFlush);
+
+    /**
+    Sets aChunk to RChunk currently in use by BIL.
+
+    @param    aChunk    aChunk will point to RChunk currently in use by BIL
+    @return KErrNone on success otherwise a system wide error code, if an error has occurred.
+    */
+    IMPORT_C TInt GetDataTransferChunk(RChunk*& aChunk);
+
+private:
+    /** @internalTechnology */
+    TInt Drain(TUint aBuffer);
+    /** @internalTechnology */ 
+    TInt Peek(TUint aBuffer);
+    /** @internalTechnology */ 
+    TInt FindNextAlternateSetting();
+
+private:
+    TUint8 iEndpointStatus;    /** @internalTechnology Each bit corresponds to each endpoint's open/close status. */
+    RChunk iSharedChunk;     /** @internalTechnology The shared chunk in use. */
+    TInt iAltSettingSeq;    /** @internalTechnology Used to track alternate setting changes. */
+    TInt iAlternateSetting; /** @internalTechnology The alternate setting used by OUT endpoints, which may lag that of IN endpoints. */
+    TInt iNewAltSetting;     /** @internalTechnology Used to track the next alternate setting change on OUT endpoints,
+                                during transition from one to the next. */ 
+    TInt iInAltSetting;     /** @internalTechnology The alternate setting used by IN endpoints, which may be ahead of OUT endpoints. */
+
+
+    friend class TEndpointBuffer;    
+#endif // #ifndef __KERNEL_MODE__
+    };
+
+#ifndef __KERNEL_MODE__
+
+
+/**
+ This class forms part of the Buffer Interface Layer (BIL), which forms the 
+ user side component of the USB Shared Chunk Client.  Objects of this type
+ represent the shared chunk buffer, for a given endpoint.
+ The method RDevUsbcScClient::OpenEndpoint() should be used to initialise
+ objects of this type.
+*/
+class TEndpointBuffer
+    {
+public:
+ 
+    /**
+    This return value used by GetBuffer indicates that the item pointed to by 
+    aBuffer/aOffset represents a state change, instead of endpoint data.
+    */
+    const static TInt KStateChange = 0x01;
+
+public:
+    IMPORT_C TEndpointBuffer();
+
+    /**
+    Read the next block of data from the Shared chunk buffer. This method should be used if the user wishes to process one block of data at a time. 
+    This method also expires the previously read block, meaning that the memory used by the block of data may be re-used by the system, overwriting it
+    with new data.
+    @param    aBuffer    aBuffer will point to data location in shared chunk    
+    @param    aSize    aSize will hold the number of valid bytes that can be read
+    @param    aZLP    aZLP will indicate whether its a short packet or not
+    @param    aStatus    In case of no data available to be read, aStatus will be passed on to LDD, and user side should wait for 
+                    asynchronous call ReadDataNotify to return
+    @param    aLength    Not used at the moment
+    @return            KErrCompletion if operation is successfull and data is available in the buffer
+                    KErrNone if no data is available to be read
+                    KErrEof if alternate setting has changed
+                    KErrAccessDenied if endpoint is not opened
+                    KErrNotSupported if its an IN endpoint
+                    TEndpointBuffer::KStateChange if the returned data represents a state change (Ep0 only)
+    */
+    IMPORT_C TInt GetBuffer(TAny*& aBuffer,TUint& aSize,TBool& aZLP,TRequestStatus& aStatus,TUint aLength=0);
+
+    /**
+    Read the next block of data from the Shared chunk buffer. This method should be used if the user wishes to process one block of data at a time. 
+    This method also expires the previously read block, meaning that the memory used by the block of data may be re-used by the system, overwriting it
+    with new data. 
+    @param    aOffset    aOffset will point to data offset in shared chunk    
+    @param    aSize    aSize will hold the number of valid bytes that can be read
+    @param    aZLP    aZLP will indicate whether its a short packet or not
+    @param    aStatus    In case of no data available to be read, aStatus will be passed on to LDD, and user side should wait for 
+            asynchronous call ReadDataNotify to return
+    @param    aLength    Not used at the moment
+    @return    KErrCompletion if operation is successfull and data is available in the buffer
+            KErrNone if no data is available to be read
+            KErrEof if alternate setting has changed
+            KErrAccessDenied if endpoint is not opened
+            KErrNotSupported if its an IN endpoint
+            TEndpointBuffer::KStateChange if the returned data represents a state change (Ep0 only)
+    */
+    inline   TInt GetBuffer(TUint& aOffset,TUint& aSize,TBool& aZLP,TRequestStatus& aStatus,TUint aLength=0);
+
+    /**
+    Read the next block of data from the Shared chunk buffer. This method should be used if the user wishes to process more than one block of data
+    simultaneously. The user must call one of the Expire() methods to free the memory used by the block of data, and make it available for new data.
+    @param    aBuffer    aBuffer will point to data location in shared chunk    
+    @param    aSize    aSize will hold the number of valid bytes that can be read
+    @param    aZLP    aZLP will indicate whether its a short packet or not
+    @param    aStatus    In case of no data available to be read, aStatus will be passed on to LDD, and user side should wait for 
+                    asynchronous call ReadDataNotify to return
+    @param    aLength    Not used at the moment
+    @return            KErrCompletion if operation is successfull and data is available in the buffer
+                    KErrNone if no data is available to be read
+                    KErrEof if alternate setting has changed
+                    KErrAccessDenied if endpoint is not opened
+                    KErrNotSupported if its an IN endpoint
+                    TEndpointBuffer::KStateChange if the returned data represents a state change (Ep0 only)
+    */
+    IMPORT_C TInt TakeBuffer(TAny*& aBuffer,TUint& aSize,TBool& aZLP,TRequestStatus& aStatus,TUint aLength=0);
+
+    /**
+    Used in conjunction with TakeBuffer method. This will make the 'oldest' block of data previously read out using the TakeBuffer method, but not
+    already    expired, to be released back to the system. This block can then be overwritten with new data, when it becomes available.
+    @return         KErrNotSupported if its an IN endpoint
+                    KErrNone if iTail is successfully bumped to the next transfer to be read
+    */
+
+    IMPORT_C TInt Expire();
+
+    /**
+    Used in conjunction with TakeBuffer method. This function allows blocks to be expired in a different order from which the user read the data out
+    of the buffer. Note that the system will only reuse blocks up to the point of the oldest non-expired block read. This means that the user must
+    ensure to expire all blocks in a timely manner to prevent the system from running out of usable memory.
+    @param    aAddress aAddress is the start address of the block of data previously read by the user which can be overwritten.    
+    @return            KErrNotSupported if its an IN endpoint
+                    KErrNone if iTail  is successfully bumped to the next transfer to be read
+                    KErrNotFound if a 'transfer' with start address of the data block is aAddress is not found
+    */
+
+    IMPORT_C TInt Expire(TAny* aAddress);
+
+    /**
+    Initiates write operation.
+    @param    aBuffer    aBuffer will point to data in shared chunk to be written out. aBuffer should be aligned    
+    @param    aSize    aSize will hold the number of valid bytes to be written out
+    @param    aZLP    aZLP will indicate whether a ZLP should be transmitted after writing the data out
+    @param    aStatus    This is an asynchronous function and user side should wait on status to know the end of write operation
+    @return            KErrNone if a write is successfully queued
+                    KErrEof if an alternate setting change has occurred, ending this endpoint.
+                    KErrNotSupported if its an OUT endpoint
+                    KErrAccessDenied if endpoint is not opened, or if buffer is out of range
+    */
+    IMPORT_C TInt WriteBuffer(TAny* aBuffer,TUint aSize,TBool aZLP,TRequestStatus& aStatus);
+
+    /**
+    Initiates write operation.
+    @param    aOffset    aOffset will point to offset of data in shared chunk to be written out.     
+    @param    aSize    aSize will hold the number of valid bytes to be written out
+    @param    aZLP    aZLP will indicate whether a ZLP should be transmitted after writing the data out
+    @param    aStatus    This is an asynchronous function and user side should wait on status to know the end of write operation
+    @return            KErrNone if a write is successfully queued
+                    KErrEof if an alternate setting change has occurred, ending this endpoint.
+                    KErrNotSupported if its an OUT endpoint
+                    KErrAccessDenied if endpoint is not opened, or if buffer is out of range
+    */
+    IMPORT_C TInt WriteBuffer(TUint aOffset,TUint aSize,TBool aZLP,TRequestStatus& aStatus);
+    /**
+    For IN endpoints, this method retrieves the geometry for the buffer, for which the
+    caller should stay within, when using the WriteBuffer method.
+
+    @param aStart A pointer, which is set to point to the start of the buffer.
+    @param aSize An TUint for which the size (in bytes) of buffer, is written into.
+
+    @returns KErrNotSupported if the object is on an open IN endpoint, 
+            otherwise it KErrNone is returned on success.
+    */
+    IMPORT_C TInt GetInBufferRange(TAny*& aStart, TUint& aSize);
+
+    /**
+    For IN endpoints, this method retrieves the geometry for the buffer, for which the
+    caller should stay within, when using the WriteBuffer method.
+
+    @param aStart A TUint for which the buffer's start offset from the start of the chunk,
+                    in written into.
+    @param aSize An TUint for which the size (in bytes) of buffer, is written into.
+
+    @returns KErrNotSupported if the object is on an open IN endpoint, 
+            otherwise it KErrNone is returned on success.
+    */
+    IMPORT_C TInt GetInBufferRange(TUint& aStart, TUint& aSize);
+
+    /**
+    This method closes the endpoint, after it was opened with 
+    RDevUsbcScClient::OpenEndpoint(...).
+    No method of this object can be used after this    call, until
+    RDevUsbcScClient::OpenEndpoint(...) is called on it again.
+
+    @return    KErrNone on success, otherwise KErrNotFound, if the current object is not open.
+    */
+    IMPORT_C TInt Close();
+
+    IMPORT_C void Dump();
+
+    /**
+    Used to retrieve the endpoint number for which this object was open on.
+
+    @returns the endpoint number opened by this object.
+    */
+    inline TInt GetEndpointNumber();
+
+private:
+    /** @internalTechnology */
+    void Construct(RDevUsbcScClient* aClient, TUint8* aBaseAddr, const TUsbcScHdrEndpointRecord* aEpType,
+                         TInt aEndpointNumber, SUsbcScBufferHeader* aEndpointHdr=NULL);
+
+private:
+    enum TDir {EValid = KErrNone, ENotValid = KErrNotSupported, EEOF = KErrEof};
+    TDir iInState;                        /** @internalTechnology describes state of endpoint, KErrNone if IN endpoint and ready to use, KErrNotSupportd if not an IN endpoint, KErrEof on alternate setting change */
+    TDir iOutState;                        /** @internalTechnology describes state of endpoint, KErrNone if OUT endpoint and ready to use, KErrNotSupportd if not an OUT endpoint, KErrEoF on alternate setting change */
+    TInt iEndpointNumber;                /** @internalTechnology associated endpoint number */
+    TInt iBufferNum;                    /** @internalTechnology buffer number within shared chunk */
+    RDevUsbcScClient *iClient;            /** @internalTechnology Parent RDevUsbcScClient object */
+    TUint iBaseAddr;                    /** @internalTechnology The address of the beginning of the Ldd's chunk */
+
+    SUsbcScBufferHeader* iEndpointHdr;  /** @internalTechnology Pointer to the buffer Header for OUT/BI endpoints */
+    TUint8* iBufferStartAddr;             /** @internalTechnology IN/BI endpoint buffer start address within shared chunk */
+    TUint iSize;                        /** @internalTechnology IN/BI endpoint buffer size within shared chunk */
+    friend class RDevUsbcScClient;
+    };
+
+/**
+This class can be used to retrieve the geometry of the structures 
+within a shared chunk, as used by RDevUsbcScClient.
+
+@see RDevUsbcScClient
+*/
+
+class TUsbcScChunkHeader
+    {
+public:
+/**
+The constructor for the TUsbcScChunkHeader class takes a RChunk object, 
+containing USBcSc data structures, and initialises itself, so that
+GetNumberOfEndpoints & GetBuffer can be used to interpret the chunk structures.
+
+@param    An RChunk object, which represents an shared chunk, containing the
+        USBcSc data structures to be retrieved.
+*/
+    IMPORT_C TUsbcScChunkHeader(RChunk aChunk);
+/**
+Retrieves the available information in the chunk, about the given endpoint, 
+on the given alternate setting.  The returned TUsbcScBufferRecord, 
+represents the buffer geometry, used for for the endpoint, while
+the filled in TUsbcScHdrEndpointRecord represents additional endpoint
+information.
+
+@param aAltSetting The alternate setting, for which the provided endpoint number, is a member of.
+@param aEndpoint    The endpoint, who's buffer geometry is required.
+@param aEndpointInf    The provided record is filled in with details of the endpoint, who's number was given.
+*/
+    IMPORT_C TUsbcScBufferRecord* GetBuffer(TInt aAltSetting, TInt aEndpoint, TUsbcScHdrEndpointRecord*& aEndpointInf);
+/**
+Retrieves the number of endpoints found in a given alternate setting.
+@param aAltSetting The alternate setting number, for which the number of endpoints contained within, is needed.
+*/
+    IMPORT_C TInt GetNumberOfEndpoints(TInt aAltSetting);
+
+public:
+    TUsbcScChunkBuffersHeader*    iBuffers;        /** A pointer to the TUsbcScChunkBuffersHeader object, within the chunk header */
+    TUsbcScChunkAltSettingHeader* iAltSettings;    /** A pointer to the TUsbcScChunkAltSettingHeader object, within the chunk header */
+private:
+    RChunk iChunk;
+    };
+
+#endif
+
+#include <usb/d32usbcsc.inl>
+
+#endif // __D32USBCSC_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/public/d32usbcsc.inl	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,735 @@
+// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\include\d32usbcsc.inl
+// User side class definitions for USB Device support (inline header).
+// 
+//
+
+/** @file d32usbcsc.inl
+	@publishedPartner
+	@released
+*/
+
+#ifndef __D32USBCSC_INL__
+#define __D32USBCSC_INL__
+
+
+/** @internalTechnology
+*/
+struct TUsbcScIfcInfo
+	{
+	TUsbcScInterfaceInfoBuf* iInterfaceData;
+	TPtr8* iString;
+	TUint32 iBandwidthPriority;
+	};
+
+
+inline TUsbcScHdrEndpointRecord::TUsbcScHdrEndpointRecord(TInt aBufferNo, TUint8 aType)
+:	iBufferNo((TUint8)aBufferNo),
+ 	iType(aType)
+ 	{
+	};
+
+
+inline TUint TUsbcScHdrEndpointRecord::Type() const
+	{
+		return (TUint) (iType>>2);
+	};
+
+inline TUint TUsbcScHdrEndpointRecord::Direction() const
+	{
+		return (TUint) (iType&3);
+	};
+
+
+inline void TUsbcScBufferRecord::Set(TUint aOffset, TUint aEndOffset)
+	{
+	iOffset = aOffset;
+	iSize = aEndOffset-aOffset;
+	};
+
+inline TUint TUsbcScBufferRecord::Offset() const
+	{
+	return iOffset;
+	};
+
+inline TUint TUsbcScBufferRecord::Size() const
+	{
+	return iSize;
+	};
+
+
+inline TEndpointPairInfo::TEndpointPairInfo(TUint8 aType, TUint16 aPair, TUint8 aSpare)
+	: iType(aType), iSpare(aSpare), iPair(aPair)
+	{}
+
+
+inline TUsbcScEndpointInfo::TUsbcScEndpointInfo(TUint aType, TUint aDir, TInt aInterval, TInt aExtra,
+												TUint aBufferSize, TUint aReadSize
+)
+	: TUsbcEndpointInfo(aType, aDir, 0, aInterval, aExtra),
+ 	  iBufferSize(aBufferSize),  iReadSize(aReadSize), iPairing(), iAlignment(0), iFlags(0)
+	{}
+
+
+
+
+inline TUsbcScInterfaceInfo::TUsbcScInterfaceInfo(TInt aClass, TInt aSubClass,
+											  TInt aProtocol, TDesC16* aString,
+											  TUint aTotalEndpoints)
+	: iClass(aClass, aSubClass, aProtocol), iString(aString),
+	  iTotalEndpointsUsed(aTotalEndpoints), iFeatureWord(0)
+	{}
+
+
+inline TUsbcScBufferRecord* TUsbcScChunkBuffersHeader::Ep0Out() const
+	{
+	return (TUsbcScBufferRecord*) &iBufferOffset[0];
+	};
+inline TUsbcScBufferRecord* TUsbcScChunkBuffersHeader::Ep0In() const
+	{
+	return (TUsbcScBufferRecord*) &iBufferOffset[iRecordSize];
+	};
+inline TUsbcScBufferRecord* TUsbcScChunkBuffersHeader::Buffers(TInt aBuffer) const
+	{
+	return (TUsbcScBufferRecord*) &iBufferOffset[(aBuffer+2)*iRecordSize];
+	};
+
+inline TInt TUsbcScChunkBuffersHeader::NumberOfBuffers() const
+	{
+	return iNumOfBufs;
+	};
+
+
+#ifndef __KERNEL_MODE__
+
+
+
+/** @capability CommDD
+*/
+inline TInt RDevUsbcScClient::Open(TInt aUnit)
+	{
+	_LIT(KUsbDevName, "usbcsc");
+	return (DoCreate(KUsbDevName, VersionRequired(), aUnit, NULL, NULL, EOwnerThread));
+	}
+
+
+inline TVersion RDevUsbcScClient::VersionRequired() const
+	{
+	return (TVersion(EMajorVersionNumber, EMinorVersionNumber, EBuildVersionNumber));
+	}
+
+
+inline TInt RDevUsbcScClient::EndpointZeroRequestError()
+	{
+	return DoControl(EControlEndpointZeroRequestError);
+	}
+
+
+inline TInt RDevUsbcScClient::EndpointCaps(TDes8& aCapsBuf)
+	{
+	return DoControl(EControlEndpointCaps, &aCapsBuf);
+	}
+
+
+inline TInt RDevUsbcScClient::DeviceCaps(TUsbDeviceCaps& aCapsBuf)
+	{
+	return DoControl(EControlDeviceCaps, &aCapsBuf);
+	}
+
+
+inline TInt RDevUsbcScClient::GetAlternateSetting(TInt &aInterfaceNumber)
+	{
+	return DoControl(EControlGetAlternateSetting, &aInterfaceNumber);
+	}
+
+
+inline TInt RDevUsbcScClient::DeviceStatus(TUsbcDeviceState &aDeviceStatus)
+	{
+	return DoControl(EControlDeviceStatus, &aDeviceStatus);
+	}
+
+
+inline TInt RDevUsbcScClient::EndpointStatus(TInt aEndpoint,TEndpointState &aEndpointStatus)
+	{
+	return DoControl(EControlEndpointStatus,(TAny*) aEndpoint, &aEndpointStatus);
+	}
+
+/*
+inline TInt RDevUsbcScClient::QueryReceiveBuffer(TInt aEndpoint,TInt& aNumberOfBytes)
+	{
+	return DoControl(EControlQueryReceiveBuffer, (TAny*) aEndpoint, &aNumberOfBytes);
+	}
+
+*/
+inline TInt RDevUsbcScClient::SendEp0StatusPacket()
+	{
+	return DoControl(EControlSendEp0StatusPacket);
+	}
+
+
+inline TInt RDevUsbcScClient::HaltEndpoint(TInt aEndpoint)
+	{
+	return DoControl(EControlHaltEndpoint, (TAny*) aEndpoint);
+	}
+
+
+inline TInt RDevUsbcScClient::ClearHaltEndpoint(TInt aEndpoint)
+	{
+	return DoControl(EControlClearHaltEndpoint, (TAny*) aEndpoint);
+	}
+
+
+inline TUint RDevUsbcScClient::EndpointZeroMaxPacketSizes()
+	{
+	return DoControl(EControlEndpointZeroMaxPacketSizes);
+	}
+
+
+inline TInt RDevUsbcScClient::SetEndpointZeroMaxPacketSize(TInt aMaxPacketSize)
+	{
+	return DoControl(EControlSetEndpointZeroMaxPacketSize, (TAny*) aMaxPacketSize);
+	}
+
+
+inline TInt RDevUsbcScClient::GetEndpointZeroMaxPacketSize()
+	{
+	return DoControl(EControlGetEndpointZeroMaxPacketSize);
+	}
+
+
+inline TInt RDevUsbcScClient::GetDeviceDescriptor(TDes8& aDeviceDescriptor)
+	{
+	return DoControl(EControlGetDeviceDescriptor, &aDeviceDescriptor);
+	}
+
+
+inline TInt RDevUsbcScClient::SetDeviceDescriptor(const TDesC8& aDeviceDescriptor)
+	{
+	return DoControl(EControlSetDeviceDescriptor, const_cast<TDesC8*>(&aDeviceDescriptor));
+	}
+
+
+inline TInt RDevUsbcScClient::GetDeviceDescriptorSize(TInt& aSize)
+	{
+	TPckgBuf<TInt> p;
+	TInt r = DoControl(EControlGetDeviceDescriptorSize, &p);
+	if (r == KErrNone)
+		aSize = p();
+	return r;
+	}
+
+
+inline TInt RDevUsbcScClient::GetConfigurationDescriptor(TDes8& aConfigurationDescriptor)
+	{
+	return DoControl(EControlGetConfigurationDescriptor, &aConfigurationDescriptor);
+	}
+
+
+inline TInt RDevUsbcScClient::SetConfigurationDescriptor(const TDesC8& aConfigurationDescriptor)
+	{
+	return DoControl(EControlSetConfigurationDescriptor, const_cast<TDesC8*> (&aConfigurationDescriptor));
+	}
+
+
+inline TInt RDevUsbcScClient::GetConfigurationDescriptorSize(TInt& aSize)
+	{
+	TPckgBuf<TInt> p;
+	TInt r=DoControl(EControlGetConfigurationDescriptorSize, &p);
+	if (r == KErrNone)
+		aSize = p();
+	return r;
+	}
+
+
+inline TInt RDevUsbcScClient::GetInterfaceDescriptor(TInt aSettingNumber, TDes8& aInterfaceDescriptor)
+	{
+	return DoControl(EControlGetInterfaceDescriptor,(TAny*) aSettingNumber, &aInterfaceDescriptor);
+	}
+
+
+inline TInt RDevUsbcScClient::SetInterfaceDescriptor(TInt aSettingNumber, const TDesC8& aInterfaceDescriptor)
+	{
+	return DoControl(EControlSetInterfaceDescriptor,(TAny*) aSettingNumber,
+					 const_cast<TDesC8*>(&aInterfaceDescriptor));
+	}
+
+
+inline TInt RDevUsbcScClient::GetInterfaceDescriptorSize(TInt aSettingNumber, TInt& aSize)
+	{
+	TPckgBuf<TInt> p;
+	TInt r = DoControl(EControlGetInterfaceDescriptorSize,(TAny*) aSettingNumber, &p);
+	if (r == KErrNone)
+		aSize = p();
+	return r;
+	}
+
+
+inline TInt RDevUsbcScClient::GetEndpointDescriptor(TInt aSettingNumber, TInt aEndpointNumber,
+												  TDes8& aEndpointDescriptor)
+	{
+	TEndpointDescriptorInfo info = {aSettingNumber, aEndpointNumber, &aEndpointDescriptor};
+	return DoControl(EControlGetEndpointDescriptor, &info, NULL);
+	}
+
+
+inline TInt RDevUsbcScClient::SetEndpointDescriptor(TInt aSettingNumber, TInt aEndpointNumber,
+												  const TDesC8& aEndpointDescriptor)
+	{
+	TEndpointDescriptorInfo info = {aSettingNumber, aEndpointNumber, const_cast<TDesC8*>(&aEndpointDescriptor)};
+	return DoControl(EControlSetEndpointDescriptor, &info, NULL);
+	}
+
+
+inline TInt RDevUsbcScClient::GetEndpointDescriptorSize(TInt aSettingNumber, TInt aEndpointNumber, TInt& aSize)
+	{
+	TPckgBuf<TInt> p;
+	TEndpointDescriptorInfo info = {aSettingNumber, aEndpointNumber, &p};
+	TInt r = DoControl(EControlGetEndpointDescriptorSize, &info, NULL);
+	if (r == KErrNone)
+		aSize = p();
+	return r;
+	}
+
+
+inline void RDevUsbcScClient::GetOtgDescriptorSize(TInt& aSize)
+	{
+	aSize = KUsbDescSize_Otg;
+	}
+
+
+inline TInt RDevUsbcScClient::GetOtgDescriptor(TDes8& aOtgDesc)
+	{
+	return DoControl(EControlGetOtgDescriptor, (TAny*)&aOtgDesc);
+	}
+
+
+inline TInt RDevUsbcScClient::SetOtgDescriptor(const TDesC8& aOtgDesc)
+	{
+	return DoControl(EControlSetOtgDescriptor, (TAny*)&aOtgDesc);
+	}
+
+
+inline TInt RDevUsbcScClient::GetDeviceQualifierDescriptor(TDes8& aDescriptor)
+	{
+	return DoControl(EControlGetDeviceQualifierDescriptor, &aDescriptor);
+	}
+
+
+inline TInt RDevUsbcScClient::SetDeviceQualifierDescriptor(const TDesC8& aDescriptor)
+	{
+	return DoControl(EControlSetDeviceQualifierDescriptor, const_cast<TDesC8*>(&aDescriptor));
+	}
+
+
+inline TInt RDevUsbcScClient::GetOtherSpeedConfigurationDescriptor(TDes8& aDescriptor)
+	{
+	return DoControl(EControlGetOtherSpeedConfigurationDescriptor, &aDescriptor);
+	}
+
+
+inline TInt RDevUsbcScClient::SetOtherSpeedConfigurationDescriptor(const TDesC8& aDescriptor)
+	{
+	return DoControl(EControlSetOtherSpeedConfigurationDescriptor, const_cast<TDesC8*> (&aDescriptor));
+	}
+
+
+inline TInt RDevUsbcScClient::GetCSInterfaceDescriptorBlock(TInt aSettingNumber, TDes8& aInterfaceDescriptor)
+	{
+	return DoControl(EControlGetCSInterfaceDescriptor,(TAny*) aSettingNumber, &aInterfaceDescriptor);
+	}
+
+
+inline TInt RDevUsbcScClient::GetCSInterfaceDescriptorBlockSize(TInt aSettingNumber, TInt& aSize)
+	{
+	TPckgBuf<TInt> p;
+	TInt r = DoControl(EControlGetCSInterfaceDescriptorSize,(TAny*) aSettingNumber, &p);
+	if (r == KErrNone)
+		aSize = p();
+	return r;
+	}
+
+
+inline TInt RDevUsbcScClient::GetCSEndpointDescriptorBlock(TInt aSettingNumber, TInt aEndpointNumber,
+														 TDes8& aEndpointDescriptor)
+	{
+	TEndpointDescriptorInfo info={aSettingNumber, aEndpointNumber, &aEndpointDescriptor};
+	return DoControl(EControlGetCSEndpointDescriptor,&info,NULL);
+	}
+
+
+inline TInt RDevUsbcScClient::GetCSEndpointDescriptorBlockSize(TInt aSettingNumber, TInt aEndpointNumber,
+															 TInt& aSize)
+	{
+	TPckgBuf<TInt> p;
+	TEndpointDescriptorInfo info = {aSettingNumber, aEndpointNumber, &p};
+	TInt r = DoControl(EControlGetCSEndpointDescriptorSize, &info, NULL);
+	if (r == KErrNone)
+		aSize = p();
+	return r;
+	}
+
+
+inline TInt RDevUsbcScClient::SignalRemoteWakeup()
+	{
+	return DoControl(EControlSignalRemoteWakeup);
+	}
+
+
+inline TInt RDevUsbcScClient::DeviceDisconnectFromHost()
+	{
+	return DoControl(EControlDeviceDisconnectFromHost);
+	}
+
+
+inline TInt RDevUsbcScClient::DeviceConnectToHost()
+	{
+	return DoControl(EControlDeviceConnectToHost);
+	}
+
+
+inline TInt RDevUsbcScClient::PowerUpUdc()
+	{
+	return DoControl(EControlDevicePowerUpUdc);
+	}
+
+
+inline TBool RDevUsbcScClient::CurrentlyUsingHighSpeed()
+	{
+	return DoControl(EControlCurrentlyUsingHighSpeed);
+	}
+
+
+inline TInt RDevUsbcScClient::SetInterface(TInt aInterfaceNumber, TUsbcScInterfaceInfoBuf& aInterfaceData)
+	{
+	TPtr8 name_8(NULL,0);
+	TUsbcScIfcInfo ifcinfo;
+	ifcinfo.iInterfaceData = const_cast<TUsbcScInterfaceInfoBuf*>(&aInterfaceData);
+	if (!aInterfaceData().iString)
+		{
+		ifcinfo.iString = NULL;
+		}
+	else
+		{
+		name_8.Set(const_cast<TUint8*>(reinterpret_cast<const TUint8*>(aInterfaceData().iString->Ptr())),
+				   aInterfaceData().iString->Size(), aInterfaceData().iString->Size());
+		ifcinfo.iString = &name_8;
+		}
+	return DoControl(EControlSetInterface, (TAny*)aInterfaceNumber, &ifcinfo);
+	}
+
+inline TInt RDevUsbcScClient::RealizeInterface(RChunk& aChunk)
+	{
+	return aChunk.SetReturnedHandle(DoControl(EControlRealizeInterface));
+	}
+
+
+inline TInt RDevUsbcScClient::ReleaseInterface(TInt aInterfaceNumber)
+	{
+	return DoControl(EControlReleaseInterface, (TAny*)aInterfaceNumber);
+	}
+
+
+inline TInt RDevUsbcScClient::SetCSInterfaceDescriptorBlock(TInt aSettingNumber, const TDesC8& aInterfaceDescriptor)
+	{
+	TCSDescriptorInfo info = {aSettingNumber, 0, const_cast<TDesC8*>(&aInterfaceDescriptor),
+							  aInterfaceDescriptor.Size()};
+	return DoControl(EControlSetCSInterfaceDescriptor, &info, NULL);
+	}
+
+
+inline TInt RDevUsbcScClient::SetCSEndpointDescriptorBlock(TInt aSettingNumber, TInt aEndpointNumber,
+														 const TDesC8& aEndpointDescriptor)
+	{
+	TCSDescriptorInfo info = {aSettingNumber, aEndpointNumber, const_cast<TDesC8*>(&aEndpointDescriptor),
+							  aEndpointDescriptor.Size()};
+	return DoControl(EControlSetCSEndpointDescriptor, &info, NULL);
+	}
+
+
+inline TInt RDevUsbcScClient::SetDeviceControl()
+	{
+	return DoControl(EControlSetDeviceControl);
+	}
+
+
+inline TInt RDevUsbcScClient::ReleaseDeviceControl()
+	{
+	return DoControl(EControlReleaseDeviceControl);
+	}
+
+
+inline TInt RDevUsbcScClient::GetStringDescriptorLangId(TUint16& aLangId)
+	{
+	TPckgBuf<TUint16> p;
+	const TInt r = DoControl(EControlGetStringDescriptorLangId, &p);
+	if (r == KErrNone)
+		aLangId = p();
+	return r;
+	}
+
+
+inline TInt RDevUsbcScClient::SetStringDescriptorLangId(TUint16 aLangId)
+	{
+	return DoControl(EControlSetStringDescriptorLangId, (TAny*)(TUint)aLangId);
+	}
+
+
+inline TInt RDevUsbcScClient::GetManufacturerStringDescriptor(TDes16& aString)
+	{
+	TPtr8 name_8(const_cast<TUint8*>(reinterpret_cast<const TUint8*>(aString.Ptr())), aString.MaxSize());
+	const TInt r = DoControl(EControlGetManufacturerStringDescriptor, &name_8);
+	aString.SetLength(name_8.Size()/2);
+	return r;
+	}
+
+
+inline TInt RDevUsbcScClient::SetManufacturerStringDescriptor(const TDesC16& aString)
+	{
+	TPtrC8 name_8(reinterpret_cast<const TUint8*>(aString.Ptr()), aString.Size());
+	return DoControl(EControlSetManufacturerStringDescriptor, &name_8);
+	}
+
+
+inline TInt RDevUsbcScClient::RemoveManufacturerStringDescriptor()
+	{
+	return DoControl(EControlRemoveManufacturerStringDescriptor);
+	}
+
+
+inline TInt RDevUsbcScClient::GetProductStringDescriptor(TDes16& aString)
+	{
+	TPtr8 name_8(const_cast<TUint8*>(reinterpret_cast<const TUint8*>(aString.Ptr())), aString.MaxSize());
+	const TInt r = DoControl(EControlGetProductStringDescriptor, &name_8);
+	aString.SetLength(name_8.Size()/2);
+	return r;
+	}
+
+
+inline TInt RDevUsbcScClient::SetProductStringDescriptor(const TDesC16& aString)
+	{
+	TPtrC8 name_8(reinterpret_cast<const TUint8*>(aString.Ptr()), aString.Size());
+	return DoControl(EControlSetProductStringDescriptor, &name_8);
+	}
+
+
+inline TInt RDevUsbcScClient::RemoveProductStringDescriptor()
+	{
+	return DoControl(EControlRemoveProductStringDescriptor);
+	}
+
+
+inline TInt RDevUsbcScClient::GetSerialNumberStringDescriptor(TDes16& aString)
+	{
+	TPtr8 name_8(const_cast<TUint8*>(reinterpret_cast<const TUint8*>(aString.Ptr())), aString.MaxSize());
+	const TInt r = DoControl(EControlGetSerialNumberStringDescriptor, &name_8);
+	aString.SetLength(name_8.Size()/2);
+	return r;
+	}
+
+
+inline TInt RDevUsbcScClient::SetSerialNumberStringDescriptor(const TDesC16& aString)
+	{
+	TPtrC8 name_8(reinterpret_cast<const TUint8*>(aString.Ptr()), aString.Size());
+	return DoControl(EControlSetSerialNumberStringDescriptor, &name_8);
+	}
+
+
+inline TInt RDevUsbcScClient::RemoveSerialNumberStringDescriptor()
+	{
+	return DoControl(EControlRemoveSerialNumberStringDescriptor);
+	}
+
+
+inline TInt RDevUsbcScClient::GetConfigurationStringDescriptor(TDes16& aString)
+	{
+	TPtr8 name_8(const_cast<TUint8*>(reinterpret_cast<const TUint8*>(aString.Ptr())), aString.MaxSize());
+	const TInt r = DoControl(EControlGetConfigurationStringDescriptor, &name_8);
+	aString.SetLength(name_8.Size() / 2);
+	return r;
+	}
+
+
+inline TInt RDevUsbcScClient::SetConfigurationStringDescriptor(const TDesC16& aString)
+	{
+	TPtrC8 name_8(reinterpret_cast<const TUint8*>(aString.Ptr()), aString.Size());
+	return DoControl(EControlSetConfigurationStringDescriptor, &name_8);
+	}
+
+
+inline TInt RDevUsbcScClient::RemoveConfigurationStringDescriptor()
+	{
+	return DoControl(EControlRemoveConfigurationStringDescriptor);
+	}
+
+
+inline TInt RDevUsbcScClient::GetStringDescriptor(TUint8 aIndex, TDes16& aString)
+	{
+	TPtr8 name_8(const_cast<TUint8*>(reinterpret_cast<const TUint8*>(aString.Ptr())), aString.MaxSize());
+	const TInt r = DoControl(EControlGetStringDescriptor, (TAny*)(TUint)aIndex, &name_8);
+	aString.SetLength(name_8.Size() / 2);
+	return r;
+	}
+
+
+inline TInt RDevUsbcScClient::SetStringDescriptor(TUint8 aIndex, const TDesC16& aString)
+	{
+	TPtrC8 name_8(reinterpret_cast<const TUint8*>(aString.Ptr()), aString.Size());
+	return DoControl(EControlSetStringDescriptor, (TAny*)(TUint)aIndex, &name_8);
+	}
+
+
+inline TInt RDevUsbcScClient::RemoveStringDescriptor(TUint8 aIndex)
+	{
+	return DoControl(EControlRemoveStringDescriptor, (TAny*)(TUint)aIndex);
+	}
+
+
+inline TInt RDevUsbcScClient::AllocateEndpointResource(TInt aEndpoint, TUsbcEndpointResource aResource)
+	{
+	return DoControl(EControlAllocateEndpointResource, (TAny*)aEndpoint, (TAny*)aResource);
+	}
+
+
+inline TInt RDevUsbcScClient::DeAllocateEndpointResource(TInt aEndpoint, TUsbcEndpointResource aResource)
+	{
+	return DoControl(EControlDeAllocateEndpointResource, (TAny*)aEndpoint, (TAny*)aResource);
+	}
+
+
+inline TBool RDevUsbcScClient::QueryEndpointResourceUse(TInt aEndpoint, TUsbcEndpointResource aResource)
+	{
+	return DoControl(EControlQueryEndpointResourceUse, (TAny*)aEndpoint, (TAny*)aResource);
+	}
+
+
+inline TInt RDevUsbcScClient::ReadDataNotify(TInt aBufferNumber, TRequestStatus& aStatus, TInt aLength)
+	{
+	TAny *a[2];
+	a[0]=(TAny*) aBufferNumber;
+	a[1]=(TAny*) aLength;
+	aStatus=KRequestPending;
+	TInt r = DoControl(~ERequestReadDataNotify, &aStatus, &a[0]);
+	if (r)
+		aStatus=r;
+	return r;
+	}
+
+
+
+inline void RDevUsbcScClient::WriteData(TInt aBufferNumber, TUint aStart, TUint aLength, TUint aFlags, TRequestStatus& aStatus)
+	{
+	DoRequest( ERequestWriteData | ((aBufferNumber&KFieldBuffMask) << KFieldBuffPos) | ((aFlags&KFieldFlagsMask) << KFieldFlagsPos),
+			   aStatus, (TAny*) aStart, (TAny*) aLength);
+	}
+
+
+
+inline void RDevUsbcScClient::AlternateDeviceStatusNotify(TRequestStatus& aStatus, TUint& aValue)
+	{
+	DoRequest(ERequestAlternateDeviceStatusNotify, aStatus, &aValue);
+	}
+
+
+inline void RDevUsbcScClient::ReEnumerate(TRequestStatus& aStatus)
+	{
+	DoRequest(ERequestReEnumerate, aStatus);
+	}
+
+
+inline void RDevUsbcScClient::EndpointStatusNotify(TRequestStatus& aStatus, TUint& aEndpointMask)
+	{
+	DoRequest(ERequestEndpointStatusNotify, aStatus, &aEndpointMask);
+	}
+
+
+inline void RDevUsbcScClient::ReadCancel(TInt aBuffer)
+	{
+	DoControl(ERequestReadDataNotifyCancel, (TAny*) aBuffer);
+	}
+
+
+inline void RDevUsbcScClient::WriteCancel(TInt aBuffer)
+	{
+	DoControl(ERequestWriteDataCancel, (TAny*) aBuffer);
+	}
+
+
+inline void RDevUsbcScClient::EndpointTransferCancel(TUint aBufferMask)
+	{
+	DoControl(ERequestCancel, (TAny*) aBufferMask);
+	}
+
+
+inline void RDevUsbcScClient::AlternateDeviceStatusNotifyCancel()
+	{
+	DoControl(ERequestAlternateDeviceStatusNotifyCancel);
+	}
+
+
+inline void RDevUsbcScClient::ReEnumerateCancel()
+	{
+	DoControl(ERequestReEnumerateCancel);
+	}
+
+
+inline void RDevUsbcScClient::EndpointStatusNotifyCancel()
+	{
+	DoControl(ERequestEndpointStatusNotifyCancel);
+	}
+
+inline TInt RDevUsbcScClient::GetOtgFeatures(TUint8& aFeatures)
+	{
+	TPckgBuf<TUint8> p;
+	TInt r = DoControl(EControlGetOtgFeatures, &p);
+	if (r == KErrNone)
+		aFeatures = p();
+	return r;
+	}
+	
+
+inline void RDevUsbcScClient::OtgFeaturesNotify(TRequestStatus& aStatus, TUint8& aValue)
+	{
+	DoRequest(ERequestOtgFeaturesNotify, aStatus, &aValue);
+	}
+
+inline void RDevUsbcScClient::OtgFeaturesNotifyCancel()
+	{
+	DoControl(ERequestOtgFeaturesNotifyCancel);
+	}
+
+inline TInt RDevUsbcScClient::StartNextInAlternateSetting()
+	{
+	return DoControl(EControlStartNextInAlternateSetting);
+	}
+
+//Buffer Interface Layer (BIL) inline functions
+
+
+inline TInt TEndpointBuffer::GetBuffer(TUint& aOffset,TUint& aSize,TBool& aZLP,TRequestStatus& aStatus,TUint aLength)
+	{
+	TInt r = GetBuffer(aOffset,aSize,aZLP,aStatus,aLength);
+	aOffset -= iBaseAddr;
+	return r;
+	};
+
+
+inline TInt TEndpointBuffer::GetEndpointNumber()
+	{
+	return iEndpointNumber;
+	}
+
+#endif // #ifndef __KERNEL_MODE__
+
+#endif // #ifndef __D32USBCSC_INL__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/public/d32usbcshared.h	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,338 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32/include/d32usbcshared.h
+// User side class definitions for USB Device support.
+// 
+//
+
+/**
+ @file d32usbcshared.h
+ @publishedPartner
+ @released
+*/
+
+#ifndef __D32USBCSHARED_H__
+#define __D32USBCSHARED_H__
+
+#include <usb/usb_peripheral_shai_shared.h>
+
+// FIXME: for dummy dcd compitible, move this line to usbcshared.h
+// used by shared chunk version LDD's user app interface
+typedef TInt TUsbcDeviceState;
+
+// USB driver error codes
+
+/** USB driver specific error codes start from here
+*/
+const TInt KErrUsbDriverBase = -6701;
+
+/**	Attempt at data transfer, or something interface related,
+	when neither an Interface has been set up nor Device Control is owned by
+	the channel
+*/
+const TInt KErrUsbInterfaceNotReady = -6702;
+
+/**	Attempt at data transfer on an endpoint that does not belong to the active interface
+*/
+const TInt KErrUsbEpNotInInterface = -6703;
+
+/**	Attempt at data transfer in a direction not supported by the endpoint
+*/
+const TInt KErrUsbEpBadDirection = -6704;
+
+/**	The data transfer size specified exceeds that of the source or
+	destination buffer descriptor
+*/
+const TInt KErrUsbTransferSize = -6705;
+
+/**	This has multiple uses:
+	1) User request completed because device is no longer in configured state
+	2) Something endpoint related, stall, unstall, status enquiry etc,
+	   that requires the device to be configured
+*/
+const TInt KErrUsbDeviceNotConfigured = -6706;
+
+/**	Requested endpoint properties inconsistent during Interface setup
+*/
+const TInt KErrUsbBadEndpoint = -6707;
+
+/**	User data request completed because channel is closing (channel destructor called)
+*/
+const TInt KErrUsbDeviceClosing = -6708;
+
+/**	User data request completed because current endpoint set is being
+	replaced since alternate setting is changing
+*/
+const TInt KErrUsbInterfaceChange = -6709;
+
+/**	User data request completed because cable has been detached (or equivalent)
+*/
+const TInt KErrUsbCableDetached = -6710;
+
+/**	User data request completed because cable has been detached (or equivalent)
+*/
+const TInt KErrUsbDeviceBusReset = -6711;
+
+/**	This means that read data is still available when a write request is made.
+	Relates to bidirectional eps only (ep0).
+	A bidirectional ep must consume all of its read data before attempting to write.
+*/
+const TInt KErrUsbEpNotReady = -6712;
+
+// FIXME: REMOVE THIS GUY, ONCE DUMMY DCD is modified according to new SHAI.
+const TInt EUsbcDeviceStateUndefined = UsbShai::EUsbPeripheralStateUndefined; // 0
+const TInt EUsbcDeviceStateAttached = UsbShai::EUsbPeripheralStateAttached; // 1
+const TInt EUsbcDeviceStatePowered = UsbShai::EUsbPeripheralStatePowered;// 2
+const TInt EUsbcDeviceStateDefault = UsbShai::EUsbPeripheralStateDefault;// 3
+const TInt EUsbcDeviceStateAddress = UsbShai::EUsbPeripheralStateAddress; // 4
+const TInt EUsbcDeviceStateConfigured = UsbShai::EUsbPeripheralStateConfigured;// 5
+const TInt EUsbcDeviceStateSuspended = UsbShai::EUsbPeripheralStateSuspended;// 6
+const TInt EUsbcNoState = UsbShai::EUsbPeripheralNoState; // 255 (used as a place holder)
+
+/** The endpoint states.
+
+	@see RDevUsbcClient::EndpointStatus()
+	@see RDevUsbcClient::EndpointStatusNotify()
+*/
+enum TEndpointState
+	{
+	EEndpointStateNotStalled,
+	EEndpointStateStalled,
+	EEndpointStateUnknown
+	};
+
+class TUsbcEndpointCaps : public UsbShai::TUsbPeripheralEndpointCaps
+    {
+    public:
+	/** Returns the greatest available packet size for this endpoint. */
+	TInt MaxPacketSize() const;
+	/** Returns the smallest available packet size for this endpoint. */
+	TInt MinPacketSize() const;    
+    };
+
+/** Endpoint resources/behaviours.
+
+	@see AllocateEndpointResource()
+	@see DeAllocateEndpointResource()
+	@see QueryEndpointResourceUse()
+*/
+enum TUsbcEndpointResource
+	{
+	/** Requests the use of DMA. */
+	EUsbcEndpointResourceDMA = 0,
+	/** Requests the use of double FIFO buffering. */
+	EUsbcEndpointResourceDoubleBuffering = 1
+	};
+
+const TUint KUsbcEndpointInfoFeatureWord1_DMA = UsbShai::KUsbEndpointInfoFeatureWord1_DMA;
+const TUint KUsbcEndpointInfoFeatureWord1_DoubleBuffering = UsbShai::KUsbEndpointInfoFeatureWord1_DoubleBuffering;
+    
+/** The USB client device capability class.
+*/
+class TCapsDevUsbc
+	{
+    public:
+	/** The device version. */
+	TVersion version;
+	};
+
+/** The maximum number of endpoints supported by the device, excluding ep0.
+*/
+const TInt KUsbcMaxEndpoints = 30;
+
+/** The maximum number of endpoints per interface, excluding ep0.
+*/
+const TInt KMaxEndpointsPerClient = 5;
+
+/** @internalComponent
+*/
+const TInt KInvalidEndpointNumber = 31;
+
+/** The alternate setting flag; when this bit is set the state change notified by
+	RDevUsbcClient::AlternateDeviceStatusNotify() is an alternate setting number.
+*/
+const TUint KUsbAlternateSetting = 0x80000000;
+
+/** The USB cable detection feature flag; used by TUsbDeviceCapsV01::iFeatureWord1.
+	When this bit is set then the USB controller hardware (UDC) supports detection
+	of a plugged-in USB cable even when not powered.
+
+	@see TUsbDeviceCapsV01
+*/
+const TUint KUsbDevCapsFeatureWord1_CableDetectWithoutPower = 0x00000001;
+
+/** If this flag is set then the driver supports the new endpoint resource
+	allocation scheme for DMA and Double-buffering via
+	TUsbcEndpointInfo::iFeatureWord1.
+
+	@see TUsbDeviceCapsV01
+*/
+const TUint KUsbDevCapsFeatureWord1_EndpointResourceAllocV2 = 0x00000002;
+
+
+/** Device USB capabilities.
+*/
+class TUsbDeviceCapsV01
+	{
+public:
+	/** The total number of endpoints on the device. */
+	TInt iTotalEndpoints;
+	/** Indicates whether the device supports software connect/disconnect. */
+	TBool iConnect;
+	/** Indicates whether the device is self powered. */
+	TBool iSelfPowered;
+	/** Indicates whether the device can send Remote Wakeup. */
+	TBool iRemoteWakeup;
+	/** Indicates whether the device supports High-speed mode. */
+	TBool iHighSpeed;
+	/** 32 flag bits indicating miscellaneous UDC/device features.
+		Currently defined are:
+		- KUsbDevCapsFeatureWord1_CableDetectWithoutPower = 0x00000001
+		- KUsbDevCapsFeatureWord1_EndpointResourceAllocV2 = 0x00000002
+	*/
+	TUint32 iFeatureWord1;
+	/** Reserved for future use. */
+	TUint32 iReserved;
+	};
+
+/** Package buffer for a TUsbDeviceCapsV01 object.
+
+	@see TUsbDeviceCapsV01
+*/
+typedef TPckgBuf<TUsbDeviceCapsV01> TUsbDeviceCaps;
+
+/** Bitmaps for TUsbcEndpointCaps.iSizes.
+
+	This endpoint is not available (= no size).
+*/
+const TUint KUsbEpNotAvailable = 0x00000000;
+/**	Max packet size is continuously variable up to some size specified.
+	(Interrupt and Isochronous endpoints only.)
+*/
+const TUint KUsbEpSizeCont     = 0x00000001;
+/** Max packet size 8 bytes is supported
+*/
+const TUint KUsbEpSize8        = 0x00000008;
+/** Max packet size 16 bytes is supported
+*/
+const TUint KUsbEpSize16       = 0x00000010;
+/** Max packet size 32 bytes is supported
+*/
+const TUint KUsbEpSize32       = 0x00000020;
+/** Max packet size 64 bytes is supported
+*/
+const TUint KUsbEpSize64       = 0x00000040;
+/** Max packet size 128 bytes is supported
+*/
+const TUint KUsbEpSize128      = 0x00000080;
+/** Max packet size 256 bytes is supported
+*/
+const TUint KUsbEpSize256      = 0x00000100;
+/** Max packet size 512 bytes is supported
+*/
+const TUint KUsbEpSize512      = 0x00000200;
+/** Max packet size 1023 bytes is supported
+*/
+const TUint KUsbEpSize1023     = 0x00000400;
+/** Max packet size 1024 bytes is supported
+*/
+const TUint KUsbEpSize1024     = 0x00000800;
+
+/** Bitmaps for TUsbcEndpointCaps.iSupportedTypesAndDir.
+
+	Endpoint supports Control transfer type.
+*/
+const TUint KUsbEpTypeControl     = UsbShai::KUsbEpTypeControl;
+/** Endpoint supports Isochronous transfer type.
+*/
+const TUint KUsbEpTypeIsochronous = UsbShai::KUsbEpTypeIsochronous;
+/** Endpoint supports Bulk transfer type.
+*/
+const TUint KUsbEpTypeBulk        = UsbShai::KUsbEpTypeBulk;
+/** Endpoint supports Interrupt transfer type.
+*/
+const TUint KUsbEpTypeInterrupt   = UsbShai::KUsbEpTypeInterrupt;
+/** Endpoint supports IN transfers.
+*/
+const TUint KUsbEpDirIn           = UsbShai::KUsbEpDirIn;
+/** Endpoint supports OUT transfers.
+*/
+const TUint KUsbEpDirOut          = UsbShai::KUsbEpDirOut;
+/** Endpoint supports bidirectional (Control) transfers only.
+*/
+const TUint KUsbEpDirBidirect     = UsbShai::KUsbEpDirBidirect;
+
+
+/** Converts an absolute size value into a KUsbEpSize... mask.
+*/
+static inline TUint PacketSize2Mask(TInt aSize);
+
+/** Converts an endpoint type mask KUsbEpType...  into an endpoint attribute
+	value KUsbEpAttr_....
+*/
+static inline TUint EpTypeMask2Value(TInt aType);
+
+
+/** Endpoint capabilities as returned by RDevUsbcClient::EndpointCaps().
+*/
+class TUsbcEndpointData
+	{
+public:
+	/** Detail of endpoint capabilities. */
+	TUsbcEndpointCaps iCaps;
+	/** Indicates whether this endpoint is already claimed. */
+	TBool iInUse;
+	};
+
+class TUsbcEndpointInfo : public UsbShai::TUsbPeripheralEndpointInfo 
+    {
+    public:
+	TUsbcEndpointInfo(TUint aType=UsbShai::KUsbEpTypeBulk, TUint aDir=UsbShai::KUsbEpDirOut,
+					  TInt aSize=0, TInt aInterval=0, TInt aExtra=0);
+	
+	TInt AdjustEpSizes(TInt& aEpSize_Fs, TInt& aEpSize_Hs) const;
+	
+    TInt AdjustPollInterval();
+    };
+    
+/** USB Class information used in RDevUsbcClient::SetInterface().
+*/
+class TUsbcClassInfo
+	{
+public:
+	TUsbcClassInfo(TInt aClass=0, TInt aSubClass=0, TInt aProtocol=0);
+public:
+	/** The class type number. */
+	TInt iClassNum;
+	/** The sub-class type number. */
+	TInt iSubClassNum;
+	/** The protocol number. */
+	TInt iProtocolNum;
+	/** Reserved for future use. */
+	TUint32 iReserved;
+	};
+
+
+/** The Ep0 Setup request 'unsubscribe' flag; used by
+	TUsbcInterfaceInfo::iFeatureWord. When this bit is set then valid vendor-
+	or class-specific Ep0 requests addressed to this interface or any of its
+	endpoints will be stalled by the USB PDD PIL.
+
+	@see TUsbcInterfaceInfo
+*/
+const TUint KUsbcInterfaceInfo_NoEp0RequestsPlease = 0x00000001;
+
+#include <usb/d32usbcshared.inl>
+
+#endif 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/public/d32usbcshared.inl	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,145 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32/include/d32usbcshared.inl
+// User side class definitions for USB Device support.
+// 
+//
+
+/**
+ @file d32usbcshared.inl
+ @publishedPartner
+ @released
+*/
+
+#ifndef __D32USBCSHARED_INL__
+#define __D32USBCSHARED_INL__
+
+inline TInt MaxEndpointPacketSize(TInt aSizes)
+	{
+	return (aSizes & KUsbEpSize1024) ? 1024 :
+		((aSizes & KUsbEpSize1023) ? 1023 :
+		 ((aSizes & KUsbEpSize512) ? 512 :
+		  ((aSizes & KUsbEpSize256) ? 256 :
+		   ((aSizes & KUsbEpSize128) ? 128 :
+			((aSizes & KUsbEpSize64) ? 64 :
+			 ((aSizes & KUsbEpSize32) ? 32 :
+			  ((aSizes & KUsbEpSize16) ? 16 :
+			   ((aSizes & KUsbEpSize8) ? 8 : 0))))))));
+	}
+
+
+inline TInt MinEndpointPacketSize(TInt aSizes)
+	{
+	return (aSizes & KUsbEpSize8) ? 8 :
+		((aSizes & KUsbEpSize16) ? 16 :
+		 ((aSizes & KUsbEpSize32) ? 32 :
+		  ((aSizes & KUsbEpSize64) ? 64 :
+		   ((aSizes & KUsbEpSize128) ? 128 :
+			((aSizes & KUsbEpSize256) ? 256 :
+			 ((aSizes & KUsbEpSize512) ? 512 :
+			  ((aSizes & KUsbEpSize1023) ? 1023 :
+			   ((aSizes & KUsbEpSize1024) ? 1024 : 0))))))));
+	}
+
+inline TInt TUsbcEndpointCaps::MaxPacketSize() const
+	{
+	return (iSizes & KUsbEpSize1024) ? 1024 :
+		((iSizes & KUsbEpSize1023) ? 1023 :
+		 ((iSizes & KUsbEpSize512) ? 512 :
+		  ((iSizes & KUsbEpSize256) ? 256 :
+		   ((iSizes & KUsbEpSize128) ? 128 :
+			((iSizes & KUsbEpSize64) ? 64 :
+			 ((iSizes & KUsbEpSize32) ? 32 :
+			  ((iSizes & KUsbEpSize16) ? 16 :
+			   ((iSizes & KUsbEpSize8) ? 8 : 0))))))));
+	}
+
+
+inline TInt TUsbcEndpointCaps::MinPacketSize() const
+	{
+	return (iSizes & KUsbEpSize8) ? 8 :
+		((iSizes & KUsbEpSize16) ? 16 :
+		 ((iSizes & KUsbEpSize32) ? 32 :
+		  ((iSizes & KUsbEpSize64) ? 64 :
+		   ((iSizes & KUsbEpSize128) ? 128 :
+			((iSizes & KUsbEpSize256) ? 256 :
+			 ((iSizes & KUsbEpSize512) ? 512 :
+			  ((iSizes & KUsbEpSize1023) ? 1023 :
+			   ((iSizes & KUsbEpSize1024) ? 1024 : 0))))))));
+	}
+    
+static inline TUint PacketSize2Mask(TInt aSize)
+	{
+	return (aSize == 8) ? KUsbEpSize8 :
+		((aSize == 16) ? KUsbEpSize16 :
+		 ((aSize == 32) ? KUsbEpSize32 :
+		  ((aSize == 64) ? KUsbEpSize64 :
+		   ((aSize == 128) ? KUsbEpSize128 :
+			((aSize == 256) ? KUsbEpSize256 :
+			 ((aSize == 512) ? KUsbEpSize512 :
+			  ((aSize == 1023) ? KUsbEpSize1023 :
+			   ((aSize == 1024) ? KUsbEpSize1024 : 0))))))));
+	}
+
+
+static inline TUint EpTypeMask2Value(TInt aType)
+	{
+	return (aType & UsbShai::KUsbEpTypeControl) ? KUsbEpAttr_TransferTypeControl :
+		((aType & UsbShai::KUsbEpTypeIsochronous) ? KUsbEpAttr_TransferTypeIsochronous :
+		 ((aType & UsbShai::KUsbEpTypeBulk) ? KUsbEpAttr_TransferTypeBulk :
+		  ((aType & UsbShai::KUsbEpTypeInterrupt) ? KUsbEpAttr_TransferTypeInterrupt : -1)));
+	}
+
+
+/** @internalTechnology
+*/
+struct TEndpointDescriptorInfo
+	{
+	TInt iSetting;											// alternate setting
+	TInt iEndpoint;											// excludes ep0
+	TAny* iArg;												// address of data
+	};
+
+
+/** @internalTechnology
+*/
+struct TCSDescriptorInfo
+	{
+	TInt iSetting;											// alternate setting
+	TInt iEndpoint;											// excludes ep0, not used for CS ifc desc
+	TAny* iArg;												// address of data
+	TInt iSize;												// size of data (descriptor block)
+	};
+
+inline TUsbcEndpointInfo::TUsbcEndpointInfo(TUint aType, TUint aDir, TInt aSize,
+											TInt aInterval, TInt aExtra)
+	{
+    iType = aType; 
+    iDir = aDir; 
+    iSize = aSize; 
+    iInterval = aInterval;
+	iInterval_Hs = -1; 
+    iTransactions = 0; 
+    iExtra = aExtra; 
+    iFeatureWord1 = 0;
+	iReserved = 0;
+    }
+    
+inline TUsbcClassInfo::TUsbcClassInfo(TInt aClass, TInt aSubClass, TInt aProtocol)
+	: iClassNum(aClass), iSubClassNum(aSubClass), iProtocolNum(aProtocol), iReserved(0)
+	{}
+    
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/public/d32usbdescriptors.h	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,548 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#ifndef D32USBDESCRIPTORS_H
+#define D32USBDESCRIPTORS_H
+
+#include <e32base.h>
+
+
+/*****************************************************************************/
+/*                                                                           */
+/* USB descriptors parser framework                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+class TUsbGenericDescriptor;
+
+/**
+The Symbian USB Descriptor Parsing Framework class.
+
+This class is to aid users of USBDI by providing the facilities to parse the
+raw descriptor data into wrapper classes that allow access to the fields in 
+the descriptor bodies, and pointers to map the serial data blob into the tree 
+structure that descriptors logically have.
+
+@publishedPartner Intended to be available to 3rd parties later
+@prototype
+*/
+NONSHARABLE_CLASS(UsbDescriptorParser)
+	{
+public:
+	typedef TUsbGenericDescriptor* (*TUsbDescriptorParserL)(TPtrC8& aUsbDes, TUsbGenericDescriptor* aPreviousDesc);
+
+public:
+	// Main parse function.
+	IMPORT_C static TInt Parse(const TDesC8& aUsbDes, TUsbGenericDescriptor*& aDesc);
+
+	// Custom parsing framework.
+	IMPORT_C static void RegisterCustomParserL(TUsbDescriptorParserL aParserFunc);
+	IMPORT_C static void UnregisterCustomParser(TUsbDescriptorParserL aParserFunc);
+
+private:
+	static TUsbGenericDescriptor* FindParserAndParseAndCheckL(TPtrC8& aUsbDes, TUsbGenericDescriptor* aPreviousDesc);
+	static TUsbGenericDescriptor* FindParserAndParseL(TPtrC8& aUsbDes, TUsbGenericDescriptor* aPreviousDesc);
+	static void ParseDescriptorTreeL(TPtrC8& aUsbDes, TUsbGenericDescriptor& aPreviousDesc);
+	static void BuildTreeL(TUsbGenericDescriptor& aNewDesc, TUsbGenericDescriptor& aPreviousDesc);
+	static TUsbGenericDescriptor& FindSuitableParentL(TUsbGenericDescriptor& aNewDesc, TUsbGenericDescriptor& aTopParent);
+	static TUsbGenericDescriptor* UnknownUsbDescriptorParserL(TPtrC8& aUsbDes, TUsbGenericDescriptor* aPreviousDesc);
+	};
+
+
+/*****************************************************************************/
+/*                                                                           */
+/* USB standard descriptors                                                  */
+/*                                                                           */
+/*****************************************************************************/
+
+
+/**
+Base class for USB descriptors.
+All USB descriptors contain type and length, and may have peers and children.
+
+@publishedPartner Intended to be available to 3rd parties later
+@prototype
+*/
+class TUsbGenericDescriptor
+	{
+public:
+	IMPORT_C TUsbGenericDescriptor();
+	
+	IMPORT_C void DestroyTree();
+
+	IMPORT_C TUint8 TUint8At(TInt aOffset) const;
+	IMPORT_C TUint16 TUint16At(TInt aOffset) const;
+	IMPORT_C TUint32 TUint32At(TInt aOffset) const;
+
+	IMPORT_C TUsbGenericDescriptor& operator=(const TUsbGenericDescriptor& aDescriptor);
+
+	/**
+	Helper function to allow TUsbGenericDescriptor types to be placed on the cleanup stack.
+	*/
+	inline operator TCleanupItem() { return TCleanupItem(Cleanup,this); }
+
+public:
+	virtual TBool IsParent(TUsbGenericDescriptor& aPotentialParent);
+	virtual TBool IsPeer(TUsbGenericDescriptor& aPotentialPeer);
+	virtual TBool IsChild(TUsbGenericDescriptor& aPotentialChild);
+
+private:
+	IMPORT_C static void Cleanup(TAny* aPtr);
+	static void WalkAndDelete(TUsbGenericDescriptor* aDesc);
+
+public:		// USB standard fields
+	/**
+	The offset in a standard USB descriptor to the bLength field.
+	*/
+	static const TInt KbLengthOffset = 0;
+
+	/**
+	The offset in a standard USB descriptor to the bDescriptorType field.
+	*/
+	static const TInt KbDescriptorTypeOffset = 1;
+
+	/**
+	Standard Length field.
+	*/
+	TUint8	ibLength;
+	
+	/**
+	Standard Type field.
+	*/
+	TUint8	ibDescriptorType;
+	
+public:
+	/**
+	The flag to indicate whether the USB descriptor has been recognised
+	and parsed.
+	*/
+	enum TUsbGenericDescriptorFlags
+		{
+		EUnrecognised = 0x00,
+		ERecognised = 0x01,
+		};
+	
+public:		// Symbian generated fields
+	/**
+	Flag to show if the descriptor has been recognised and parsed, or if its data can only be represented as a
+	binary blob.  This field should particularly be checked if writing code which may run on older versions of
+	the operating system, where a (now) known descriptor may not have been parsed, or before parsing a new
+	descriptor from a blob, where later versions of the operating system may have already extracted the fields.
+	*/
+	TUint8	iRecognisedAndParsed;
+
+	/**
+	A pointer to the next peer of this descriptor, or NULL.
+	As an example, an endpoint descriptor will contain pointers to any other endpoint descriptors on the same
+	interface.
+	*/
+	TUsbGenericDescriptor* iNextPeer;
+
+	/**
+	A pointer to the first child of this descriptor, or NULL.
+	As an example, an interface descriptor will contain a pointer to the first endpoint descriptor on the
+	interface. The iNextPeer member can then be used to examine other endpoints on the interface.
+	*/
+	TUsbGenericDescriptor* iFirstChild;
+	
+	/**
+	A pointer to the parent to this descriptor, or NULL.
+	As an example an endpoint descriptor from a configuration bundle will have the interface that it
+	is a member of as it's parent.
+	*/
+	TUsbGenericDescriptor* iParent;
+
+	/**
+	The binary blob that contains this descriptor
+	*/
+	TPtrC8			iBlob;
+	};
+
+enum TUsbDescriptorType
+	{
+	EDevice						= 1,
+	EConfiguration				= 2,
+	EString						= 3,
+	EInterface					= 4,
+	EEndpoint					= 5,
+	EDeviceQualifier			= 6,
+	EOtherSpeedConfiguration	= 7,
+	EInterfacePower				= 8,
+	EOTG						= 9,
+	EDebug						= 10,
+	EInterfaceAssociation		= 11,
+	};
+
+/**
+Device descriptor.
+
+See section 9.6.1 of the USB 2.0 specification.
+
+@publishedPartner Intended to be available to 3rd parties later
+@prototype
+*/
+NONSHARABLE_CLASS(TUsbDeviceDescriptor) : public TUsbGenericDescriptor
+	{
+public:
+	IMPORT_C TUsbDeviceDescriptor();
+	IMPORT_C static TUsbDeviceDescriptor* Cast(TUsbGenericDescriptor* aOriginal);
+
+public:
+	static const TInt KSizeInOctets = 18;
+	enum TFieldOffsets
+		{
+		EbcdUSB				= 2,
+		EbDeviceClass		= 4,
+		EbDeviceSubClass	= 5,
+		EbDeviceProtocol	= 6,
+		EbMaxPacketSize0	= 7,
+		EidVendor			= 8,
+		EidProduct			= 10,
+		EbcdDevice			= 12,
+		EiManufacturer		= 14,
+		EiProduct			= 15,
+		EiSerialNumber		= 16,
+		EbNumConfigurations	= 17
+		};
+
+public:
+	IMPORT_C TUint16 USBBcd() const;
+	IMPORT_C TUint8 DeviceClass() const;
+	IMPORT_C TUint8 DeviceSubClass() const;
+	IMPORT_C TUint8 DeviceProtocol() const;
+	IMPORT_C TUint8 MaxPacketSize0() const;
+	IMPORT_C TUint16 VendorId() const;
+	IMPORT_C TUint16 ProductId() const;
+	IMPORT_C TUint16 DeviceBcd() const;
+	IMPORT_C TUint8 ManufacturerIndex() const;
+	IMPORT_C TUint8 ProductIndex() const;
+	IMPORT_C TUint8 SerialNumberIndex() const;
+	IMPORT_C TUint8 NumConfigurations() const;
+
+public:
+	static TUsbDeviceDescriptor* ParseL(TPtrC8& aUsbDes, TUsbGenericDescriptor* aPreviousDesc);
+	virtual TBool IsParent(TUsbGenericDescriptor& aPotentialParent);
+	virtual TBool IsPeer(TUsbGenericDescriptor& aPotentialPeer);
+	};
+
+
+/**
+Device Qualifier descriptor.
+
+See section 9.6.2 of the USB 2.0 specification.
+
+@publishedPartner Intended to be available to 3rd parties later
+@prototype
+*/
+NONSHARABLE_CLASS(TUsbDeviceQualifierDescriptor) : public TUsbGenericDescriptor
+	{
+public:
+	IMPORT_C TUsbDeviceQualifierDescriptor();
+	IMPORT_C static TUsbDeviceQualifierDescriptor* Cast(TUsbGenericDescriptor* aOriginal);
+	
+public:
+	static const TInt KSizeInOctets = 10;
+	enum TFieldOffsets
+		{
+		EbcdUSB				= 2,
+		EbDeviceClass		= 4,
+		EbDeviceSubClass	= 5,
+		EbDeviceProtocol	= 6,
+		EbMaxPacketSize0	= 7,
+		EbNumConfigurations	= 8,
+		EbReserved			= 9
+		};
+
+public:
+	IMPORT_C TUint16 USBBcd() const;
+	IMPORT_C TUint8 DeviceClass() const;
+	IMPORT_C TUint8 DeviceSubClass() const;
+	IMPORT_C TUint8 DeviceProtocol() const;
+	IMPORT_C TUint8 MaxPacketSize0() const;
+	IMPORT_C TUint8 NumConfigurations() const;
+	IMPORT_C TUint8 Reserved() const;
+	
+public:
+	static TUsbDeviceQualifierDescriptor* ParseL(TPtrC8& aUsbDes, TUsbGenericDescriptor* aPreviousDesc);
+	virtual TBool IsParent(TUsbGenericDescriptor& aPotentialParent);
+	virtual TBool IsPeer(TUsbGenericDescriptor& aPotentialPeer);
+	};
+
+
+/**
+Configuration descriptor.
+
+See section 9.6.3 of the USB 2.0 specification.
+
+@publishedPartner Intended to be available to 3rd parties later
+@prototype
+*/
+NONSHARABLE_CLASS(TUsbConfigurationDescriptor) : public TUsbGenericDescriptor
+	{
+public:
+	IMPORT_C TUsbConfigurationDescriptor();
+	IMPORT_C static TUsbConfigurationDescriptor* Cast(TUsbGenericDescriptor* aOriginal);
+
+public:
+	static const TInt KSizeInOctets = 9;
+	enum TFieldOffsets
+		{
+		EwTotalLength			= 2,
+		EbNumInterfaces			= 4,
+		EbConfigurationValue	= 5,
+		EiConfiguration			= 6,
+		EbmAttributes			= 7,
+		EbMaxPower				= 8
+		};
+
+public:
+	IMPORT_C TUint16 TotalLength() const;
+	IMPORT_C TUint8 NumInterfaces() const;
+	IMPORT_C TUint8 ConfigurationValue() const;
+	IMPORT_C TUint8 ConfigurationIndex() const;
+	IMPORT_C TUint8 Attributes() const;
+	IMPORT_C TUint8 MaxPower() const;
+
+public:
+	static TUsbConfigurationDescriptor* ParseL(TPtrC8& aUsbDes, TUsbGenericDescriptor* aPreviousDesc);
+	virtual TBool IsParent(TUsbGenericDescriptor& aPotentialParent);
+	virtual TBool IsPeer(TUsbGenericDescriptor& aPotentialPeer);
+	};
+
+
+/**
+Other Speed descriptor.
+
+See section 9.6.4 of the USB 2.0 specification.
+
+@publishedPartner Intended to be available to 3rd parties later
+@prototype
+*/
+NONSHARABLE_CLASS(TUsbOtherSpeedDescriptor) : public TUsbGenericDescriptor
+	{
+public:
+	IMPORT_C TUsbOtherSpeedDescriptor();
+	IMPORT_C static TUsbOtherSpeedDescriptor* Cast(TUsbGenericDescriptor* aOriginal);
+
+public:
+	static const TInt KSizeInOctets = 9;
+	enum TFieldOffsets
+		{
+		EwTotalLength 			= 2,
+		EbNumInterfaces			= 4,
+		EbConfigurationValue	= 5,
+		EiConfiguration			= 6,
+		EbmAttributes			= 7,
+		EbMaxPower				= 8
+		};
+
+public:
+	IMPORT_C TUint16 TotalLength() const;
+	IMPORT_C TUint8 NumInterfaces() const;
+	IMPORT_C TUint8 ConfigurationValue() const;
+	IMPORT_C TUint8 ConfigurationIndex() const;
+	IMPORT_C TUint8 Attributes() const;
+	IMPORT_C TUint8 MaxPower() const;
+	
+public:
+	static TUsbOtherSpeedDescriptor* ParseL(TPtrC8& aUsbDes, TUsbGenericDescriptor* aPreviousDesc);
+	virtual TBool IsParent(TUsbGenericDescriptor& aPotentialParent);
+	virtual TBool IsPeer(TUsbGenericDescriptor& aPotentialPeer);
+	};
+
+
+/**
+Interface Association Descriptor
+
+See the USB IAD ECN.
+
+@publishedPartner Intended to be available to 3rd parties later
+@prototype
+*/
+NONSHARABLE_CLASS(TUsbInterfaceAssociationDescriptor) : public TUsbGenericDescriptor
+	{
+public:
+	IMPORT_C TUsbInterfaceAssociationDescriptor();
+	IMPORT_C static TUsbInterfaceAssociationDescriptor* Cast(TUsbGenericDescriptor* aOriginal);
+
+public:
+	static const TInt KSizeInOctets = 8;
+	enum TFieldOffsets
+		{
+		EbFirstInterface	= 2,
+		EbInterfaceCount	= 3,
+		EbFunctionClass		= 4,
+		EbFunctionSubClass	= 5,
+		EbFunctionProtocol	= 6,
+		EiFunction			= 7
+		};
+	
+public:
+	IMPORT_C TUint8 FirstInterface() const;
+	IMPORT_C TUint8 InterfaceCount() const;
+	IMPORT_C TUint8 FunctionClass() const;
+	IMPORT_C TUint8 FunctionSubClass() const;
+	IMPORT_C TUint8 FunctionProtocol() const;
+	IMPORT_C TUint8 FunctionIndex() const;
+	
+public:
+	static TUsbInterfaceAssociationDescriptor* ParseL(TPtrC8& aUsbDes, TUsbGenericDescriptor* aPreviousDesc);
+	virtual TBool IsParent(TUsbGenericDescriptor& aPotentialParent);
+	virtual TBool IsPeer(TUsbGenericDescriptor& aPotentialPeer);
+	virtual TBool IsChild(TUsbGenericDescriptor& aPotentialChild);
+	};
+
+/**
+Interface descriptor.
+
+See section 9.6.5 of the USB 2.0 specification.
+
+@publishedPartner Intended to be available to 3rd parties later
+@prototype
+*/
+NONSHARABLE_CLASS(TUsbInterfaceDescriptor) : public TUsbGenericDescriptor
+	{
+public:
+	IMPORT_C TUsbInterfaceDescriptor();
+	IMPORT_C static TUsbInterfaceDescriptor* Cast(TUsbGenericDescriptor* aOriginal);
+
+public:
+	static const TInt KSizeInOctets = 9;
+	enum TFieldOffsets
+		{
+		EbInterfaceNumber	= 2,
+		EbAlternateSetting	= 3,
+		EbNumEndpoints		= 4,
+		EbInterfaceClass	= 5,
+		EbInterfaceSubClass	= 6,
+		EbInterfaceProtocol	= 7,
+		EiInterface			= 8
+		};
+	
+public:
+	IMPORT_C TUint8 InterfaceNumber() const;
+	IMPORT_C TUint8 AlternateSetting() const;
+	IMPORT_C TUint8 NumEndpoints() const;
+	IMPORT_C TUint8 InterfaceClass() const;
+	IMPORT_C TUint8 InterfaceSubClass() const;
+	IMPORT_C TUint8 InterfaceProtocol() const;
+	IMPORT_C TUint8 Interface() const;
+	
+public:
+	static TUsbInterfaceDescriptor* ParseL(TPtrC8& aUsbDes, TUsbGenericDescriptor* aPreviousDesc);
+	virtual TBool IsParent(TUsbGenericDescriptor& aPotentialParent);
+	virtual TBool IsPeer(TUsbGenericDescriptor& aPotentialPeer);
+	};
+
+/**
+Endpoint descriptor.
+
+See section 9.6.6 of the USB 2.0 specification.
+Note these exclude support support for:
+'Standard AC Interrupt Endpoint Descriptor'
+'Standard AS Isochronous Synch Endpoint Descriptor'
+'Standard AS Isochronous Audio Data Endpoint Descriptor'
+as defined in USB Audio Device Class Spec v1.0 which are all 9 bytes in size.
+To support these custom descriptors may be registered with the
+parser.
+
+@publishedPartner Intended to be available to 3rd parties later
+@prototype
+*/
+NONSHARABLE_CLASS(TUsbEndpointDescriptor) : public TUsbGenericDescriptor
+	{
+public:
+	IMPORT_C TUsbEndpointDescriptor();
+	IMPORT_C static TUsbEndpointDescriptor* Cast(TUsbGenericDescriptor* aOriginal);
+
+public:
+	static const TInt KSizeInOctets = 7;
+	enum TFieldOffsets
+		{
+		EbEndpointAddress	= 2,
+		EbmAttributes		= 3,
+		EwMaxPacketSize		= 4,
+		EbInterval			= 6
+		};
+
+public:
+	IMPORT_C TUint8 EndpointAddress() const;
+	IMPORT_C TUint8 Attributes() const;
+	IMPORT_C TUint16 MaxPacketSize() const;
+	IMPORT_C TUint8 Interval() const;
+	
+public:
+	static TUsbEndpointDescriptor* ParseL(TPtrC8& aUsbDes, TUsbGenericDescriptor* aPreviousDesc);
+	virtual TBool IsParent(TUsbGenericDescriptor& aPotentialParent);
+	virtual TBool IsPeer(TUsbGenericDescriptor& aPotentialPeer);
+	};
+
+/**
+String descriptor
+
+See section 9.6.7 of the USB 2.0 specification.
+
+@publishedPartner Intended to be available to 3rd parties later
+@prototype
+*/
+NONSHARABLE_CLASS(TUsbStringDescriptor) : public TUsbGenericDescriptor
+	{
+public:
+	IMPORT_C TUsbStringDescriptor();
+	IMPORT_C static TUsbStringDescriptor* Cast(TUsbGenericDescriptor* aOriginal);
+
+public:
+	IMPORT_C TInt GetLangId(TInt aIndex) const;
+	IMPORT_C void StringData(TDes16& aString) const;
+
+public:
+	static TUsbStringDescriptor* ParseL(TPtrC8& aUsbDes, TUsbGenericDescriptor* aPreviousDesc);
+	virtual TBool IsParent(TUsbGenericDescriptor& aPotentialParent);
+	virtual TBool IsPeer(TUsbGenericDescriptor& aPotentialPeer);
+	};
+
+/**
+OTG descriptor.
+
+See section 6.4 of the USB 2.0 On-The-Go Supplement Revision 1.3
+
+@publishedPartner Intended to be available to 3rd parties later
+@prototype
+*/
+NONSHARABLE_CLASS(TUsbOTGDescriptor) : public TUsbGenericDescriptor
+	{
+public:
+	IMPORT_C TUsbOTGDescriptor();
+	IMPORT_C static TUsbOTGDescriptor* Cast(TUsbGenericDescriptor* aOriginal);
+
+public:
+	static const TInt KSizeInOctets = 3;
+	enum TFieldOffsets
+		{
+		EbmAttributes		= 2
+		};
+
+public:
+	IMPORT_C TUint8 Attributes() const;
+    IMPORT_C TBool HNPSupported() const;
+    IMPORT_C TBool SRPSupported() const;
+public:
+	static TUsbOTGDescriptor* ParseL(TPtrC8& aUsbDes, TUsbGenericDescriptor* aPreviousDesc);
+	virtual TBool IsParent(TUsbGenericDescriptor& aPotentialParent);
+	virtual TBool IsPeer(TUsbGenericDescriptor& aPotentialPeer);
+	};
+
+
+#endif	// D32USBDESCRIPTORS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/public/d32usbtransfers.h	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,239 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#ifndef __D32USBTRANSFERS_H
+#define __D32USBTRANSFERS_H
+
+#ifdef __KERNEL_MODE__
+#include <kernel/klib.h>
+#else
+#include <e32base.h>
+#endif
+#include <d32usbdi.h>
+
+
+class RUsbTransferStrategy;
+
+/**
+Base class for all transfer descriptors.
+
+@publishedPartner Intended to be available to 3rd parties later
+@prototype
+*/
+NONSHARABLE_CLASS(RUsbTransferDescriptor)
+	{
+public:
+	enum TTransferType
+		{
+		EBulk,
+		EIsochronous,
+		EInterrupt
+		};
+
+	enum TZlpStatus
+		{
+		ESuppressZlp,
+		ESendZlpIfRequired, // Default
+		EAlwaysSendZlp
+		};
+
+#ifndef __KERNEL_MODE__
+friend class RUsbPipe;
+friend class RUsbTransferStrategy;
+
+public:
+	virtual void Close();
+
+protected:
+	RUsbTransferDescriptor(TTransferType aType, TInt aMaxSize, TInt aMaxNumPackets);
+	
+protected:
+	static const TInt KInvalidHandle = -1;
+
+protected:
+	/**
+	A pointer to the transfer strategy the descriptor is registered in.
+	*/
+	RUsbTransferStrategy* iTransferStrategy;
+
+	/**
+	Handle into the transfer strategy for the descriptor.
+	*/
+	TInt iHandle;
+
+public:
+	/**
+	The type of transfer descriptor this instance represents.
+	*/
+	const TTransferType iType;
+
+	/**
+	For isochronous transfers this refers to the maximum packet size packets
+	in this descriptor may be.
+	For other transfers this refers to the maximum size of the transfer.
+	*/
+	const TInt iMaxSize;
+
+	/**
+	Used to specify the maximum number of packets the descriptor will hold.
+	*/
+	const TInt iMaxNumPackets;
+#endif // __KERNEL_MODE__
+	};
+
+
+#ifndef __KERNEL_MODE__
+
+/**
+A class that refers to the list of packet lengths for a isochronous transfer
+descriptor.
+
+@publishedPartner
+@prototype
+*/
+NONSHARABLE_CLASS(TPacketLengths)
+	{
+public:
+	NONSHARABLE_CLASS(TLength)
+		{
+	public:
+		IMPORT_C TUint16 operator=(TUint16 aValue);
+		IMPORT_C operator TUint16() const;
+	public:
+		TLength(TUint16& aRecv, TUint16& aReq);
+	private:
+		TUint16& iRecv;
+		TUint16& iReq;
+		};
+public:
+	IMPORT_C TLength At(TInt aIndex);
+	IMPORT_C const TLength At(TInt aIndex) const;
+	IMPORT_C TLength operator[](TInt aIndex);
+	IMPORT_C const TLength operator[](TInt aIndex) const;
+	IMPORT_C TInt MaxNumPackets();
+
+public:
+	TPacketLengths(TUint16* aRecvPtr, TUint16* aReqPtr, TInt& aMaxNumPackets);
+
+private:
+	TUint16* iRecvPtr;
+	TUint16* iReqPtr;
+	TInt& iMaxNumPackets;
+	};
+
+/**
+A class that refers to the list of packet results for a isochronous transfer
+descriptor.
+
+@publishedPartner
+@prototype
+*/
+NONSHARABLE_CLASS(TPacketResults)
+	{
+public:
+	IMPORT_C TInt At(TInt aIndex) const;
+	IMPORT_C TInt operator[](TInt aIndex) const;
+	IMPORT_C TInt MaxNumPackets();
+
+public:
+	TPacketResults(TInt* aResPtr, TInt& aMaxNumPackets);
+	
+private:
+	TInt* iResPtr;
+	TInt& iMaxNumPackets;
+	};
+
+
+/**
+Provides *SEQUENTIAL* access to the packet slots in an isochronous transfer descriptor.
+As some HCs may pack the buffer space tightly, with one packet starting immediately after the preceeding one,
+random access is not possible -- in this implementation, even replacing the content of a slot with another packet
+of the same size is not 'intentionally' possible.
+Note that reading data is possible in a random access manner -- the sequential constraint only applies to writing.
+@publishedPartner Intended to be available to 3rd parties later
+@prototype
+*/
+NONSHARABLE_CLASS(RUsbIsocTransferDescriptor) : public RUsbTransferDescriptor
+	{
+friend class RUsbTransferStrategy;
+
+public:
+    IMPORT_C RUsbIsocTransferDescriptor(TInt aMaxPacketSize, TInt aMaxNumPackets);
+
+public:
+	IMPORT_C void Reset();
+	IMPORT_C TPacketLengths Lengths();
+	IMPORT_C TPacketResults Results();
+	IMPORT_C TInt MaxPacketSize();
+
+public:		// Sending
+	IMPORT_C TPtr8 WritablePackets(TInt aNumPacketsRequested, TInt& aMaxNumOfPacketsAbleToWrite);
+	IMPORT_C void SaveMultiple(TInt aNumOfPackets);
+
+public:		// Receiving
+	IMPORT_C TPtrC8 Packets(TInt aFirstPacketIndex, TInt aNumPacketsRequested, TInt& aNumOfPacketsReturned) const;
+	IMPORT_C void ReceivePackets(TInt aNumOfPackets);
+
+private:
+	/**
+	The handle to represent the current point in writing an isoc. transfer.
+	*/
+	TInt iWriteHandle;
+	};
+
+
+/**
+Provides buffer management for Bulk transfers
+@publishedPartner Intended to be available to 3rd parties later
+@prototype
+*/
+NONSHARABLE_CLASS(RUsbBulkTransferDescriptor) : public RUsbTransferDescriptor
+	{
+public:
+	IMPORT_C RUsbBulkTransferDescriptor(TInt aMaxSize);
+
+public:		// Setters
+	IMPORT_C TPtr8 WritableBuffer();
+	IMPORT_C void SaveData(TInt aLength);
+	IMPORT_C void SetZlpStatus(TZlpStatus aZlpStatus);
+
+public:		// Getters
+	IMPORT_C TPtrC8 Buffer() const;
+	};
+
+
+
+/**
+Provides buffer management for Interrupt transfers
+@publishedPartner Intended to be available to 3rd parties later
+@prototype
+*/
+NONSHARABLE_CLASS(RUsbIntrTransferDescriptor) : public RUsbTransferDescriptor
+	{
+public:
+	IMPORT_C RUsbIntrTransferDescriptor(TInt aMaxSize);
+
+public:		// Setters
+	IMPORT_C TPtr8 WritableBuffer();
+	IMPORT_C void SaveData(TInt aLength);
+	IMPORT_C void SetZlpStatus(TZlpStatus aZlpStatus);
+
+public:		// Getters
+	IMPORT_C TPtrC8 Buffer() const;
+	};
+
+#endif // __KERNEL_MODE__
+
+#endif	// __D32USBTRANSFERS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/public/usb.h	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,246 @@
+// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\include\usb.h
+// Definitions of USB-specific constants and macros.
+// 
+//
+
+/**
+ @file usb.h
+ @publishedPartner
+ @released
+*/
+
+#ifndef __USB_H__
+#define __USB_H__
+
+//
+// 'Chapter 9' Request Types (bmRequestType)
+//
+const TUint8 KUsbRequestType_DirShift   = 7;
+const TUint8 KUsbRequestType_DirMask    = (1 << KUsbRequestType_DirShift);
+
+const TUint8 KUsbRequestType_DirToDev   = (0 << KUsbRequestType_DirShift);
+const TUint8 KUsbRequestType_DirToHost  = (1 << KUsbRequestType_DirShift);
+
+const TUint8 KUsbRequestType_TypeShift  = 5;
+const TUint8 KUsbRequestType_TypeMask   = (3 << KUsbRequestType_TypeShift);
+const TUint8 KUsbRequestType_TypeStd    = (0 << KUsbRequestType_TypeShift);
+const TUint8 KUsbRequestType_TypeClass  = (1 << KUsbRequestType_TypeShift);
+const TUint8 KUsbRequestType_TypeVendor = (2 << KUsbRequestType_TypeShift);
+
+const TUint8 KUsbRequestType_DestShift  = 0;
+const TUint8 KUsbRequestType_DestMask   = (0x1f << KUsbRequestType_DestShift);
+const TUint8 KUsbRequestType_DestDevice = (0x00 << KUsbRequestType_DestShift);
+const TUint8 KUsbRequestType_DestIfc    = (0x01 << KUsbRequestType_DestShift);
+const TUint8 KUsbRequestType_DestEp     = (0x02 << KUsbRequestType_DestShift);
+const TUint8 KUsbRequestType_DestOther  = (0x03 << KUsbRequestType_DestShift);
+
+//
+// 'Chapter 9' Endpoint Zero Requests (bRequest)
+//
+const TUint8 KUsbRequest_GetStatus     = 0;
+const TUint8 KUsbRequest_ClearFeature  = 1;
+const TUint8 KUsbRequest_SetFeature    = 3;
+const TUint8 KUsbRequest_SetAddress    = 5;
+const TUint8 KUsbRequest_GetDescriptor = 6;
+const TUint8 KUsbRequest_SetDescriptor = 7;
+const TUint8 KUsbRequest_GetConfig     = 8;
+const TUint8 KUsbRequest_SetConfig     = 9;
+const TUint8 KUsbRequest_GetInterface  = 10;
+const TUint8 KUsbRequest_SetInterface  = 11;
+const TUint8 KUsbRequest_SynchFrame    = 12;
+
+//
+// Descriptor Types
+//
+const TUint8 KUsbDescType_Device               = 1;
+const TUint8 KUsbDescType_Config               = 2;
+const TUint8 KUsbDescType_String               = 3;
+const TUint8 KUsbDescType_Interface            = 4;
+const TUint8 KUsbDescType_Endpoint             = 5;
+const TUint8 KUsbDescType_DeviceQualifier      = 6;
+const TUint8 KUsbDescType_OtherSpeedConfig     = 7;
+const TUint8 KUsbDescType_InterfacePower       = 8;
+const TUint8 KUsbDescType_Otg                  = 9;
+const TUint8 KUsbDescType_Debug                = 10;
+const TUint8 KUsbDescType_InterfaceAssociation = 11;
+
+//
+// Descriptor Sizes
+//
+const TUint KUsbDescSize_Device               = 18;
+const TUint KUsbDescSize_Config               = 9;
+const TUint KUsbDescSize_Interface            = 9;
+const TUint KUsbDescSize_Endpoint             = 7;
+const TUint KUsbDescSize_Otg                  = 3;
+const TUint KUsbDescSize_DeviceQualifier      = 10;
+const TUint KUsbDescSize_OtherSpeedConfig     = 9;
+const TUint KUsbDescSize_InterfaceAssociation = 8;
+const TUint KUsbDescMaxSize_String            = 255;
+const TUint KUsbStringDescStringMaxSize       = 252;		// it's actually 253, but that's awkward
+
+//
+// Configuration Characteristics (Configuration Descriptor)
+//
+const TUint8 KUsbDevAttr_SelfPowered  = (0x01 << 6);
+const TUint8 KUsbDevAttr_RemoteWakeup = (0x01 << 5);
+
+//
+// Descriptor Indices for String Descriptors
+//
+const TUint KUsbDescStringIndex_Manufact = 14;
+const TUint KUsbDescStringIndex_Product  = 15;
+const TUint KUsbDescStringIndex_Serial   = 16;
+const TUint KUsbDescStringIndex_Config   = 6;
+
+//
+// Endpoint Attributes
+//
+const TUint8 KUsbEpAttr_TransferTypeShift       = 0;
+const TUint8 KUsbEpAttr_TransferTypeMask        = (0x03 << KUsbEpAttr_TransferTypeShift);
+const TUint8 KUsbEpAttr_TransferTypeControl     = (0x00 << KUsbEpAttr_TransferTypeShift);
+const TUint8 KUsbEpAttr_TransferTypeIsochronous = (0x01 << KUsbEpAttr_TransferTypeShift);
+const TUint8 KUsbEpAttr_TransferTypeBulk        = (0x02 << KUsbEpAttr_TransferTypeShift);
+const TUint8 KUsbEpAttr_TransferTypeInterrupt   = (0x03 << KUsbEpAttr_TransferTypeShift);
+
+const TUint8 KUsbEpAttr_SyncTypeShift           = 2;
+const TUint8 KUsbEpAttr_SyncTypeMask            = (0x03 << KUsbEpAttr_SyncTypeShift);
+const TUint8 KUsbEpAttr_SyncTypeNoSync          = (0x00 << KUsbEpAttr_SyncTypeShift);
+const TUint8 KUsbEpAttr_SyncTypeAsync           = (0x01 << KUsbEpAttr_SyncTypeShift);
+const TUint8 KUsbEpAttr_SyncTypeAdaptive        = (0x02 << KUsbEpAttr_SyncTypeShift);
+const TUint8 KUsbEpAttr_SyncTypeSync            = (0x03 << KUsbEpAttr_SyncTypeShift);
+
+const TUint8 KUsbEpAttr_UsageTypeShift          = 4;
+const TUint8 KUsbEpAttr_UsageTypeMask           = (0x03 << KUsbEpAttr_UsageTypeShift);
+const TUint8 KUsbEpAttr_UsageTypeDataEp         = (0x00 << KUsbEpAttr_UsageTypeShift);
+const TUint8 KUsbEpAttr_UsageTypeFeedbackEp     = (0x01 << KUsbEpAttr_UsageTypeShift);
+const TUint8 KUsbEpAttr_UsageTypeImplFbDataEp   = (0x02 << KUsbEpAttr_UsageTypeShift);
+const TUint8 KUsbEpAttr_UsageTypeReserved       = (0x03 << KUsbEpAttr_UsageTypeShift);
+
+//
+// OTG Feature Indicators
+//
+const TUint8 KUsbOtgAttr_SrpSupp         = 0x01;
+const TUint8 KUsbOtgAttr_HnpSupp         = 0x02;
+const TUint8 KUsbOtgAttr_B_HnpEnable     = 0x04;
+const TUint8 KUsbOtgAttr_A_HnpSupport    = 0x08;
+const TUint8 KUsbOtgAttr_A_AltHnpSupport = 0x10;
+
+//
+// Feature Settings
+//
+const TUint KUsbFeature_EndpointHalt    = 0;
+const TUint KUsbFeature_RemoteWakeup    = 1;
+const TUint KUsbFeature_TestMode        = 2;
+const TUint KUsbFeature_B_HnpEnable     = 3;
+const TUint KUsbFeature_A_HnpSupport    = 4;
+const TUint KUsbFeature_A_AltHnpSupport = 5;
+
+//
+// Test Mode Selectors (Set/ClearFeature)
+//
+const TUint KUsbTestSelector_Test_J            = 0x01;
+const TUint KUsbTestSelector_Test_K            = 0x02;
+const TUint KUsbTestSelector_Test_SE0_NAK      = 0x03;
+const TUint KUsbTestSelector_Test_Packet       = 0x04;
+const TUint KUsbTestSelector_Test_Force_Enable = 0x05;
+
+//
+// Address Masks
+//
+const TUint8 KUsbEpAddress_In       = 0x80;
+const TUint8 KUsbEpAddress_Portmask = 0x0f;
+
+//
+// Device Status Values (GET_STATUS)
+//
+const TUint16 KUsbDevStat_SelfPowered  = (1 << 0);
+const TUint16 KUsbDevStat_RemoteWakeup = (1 << 1);
+
+//
+// Endpoint Status Values (GET_STATUS)
+//
+const TUint16 KUsbEpStat_Halt = (1 << 0);
+
+
+//
+// USB Descriptor Handling
+//
+/*------------------------------------------------
+  USB transfers data in little-endian fashion.
+  The following macros swap the byte order in
+  words (16 bit) and longwords (32 bit), such that
+  they are in little-endian order afterwards.
+  ------------------------------------------------*/
+#if defined(__BIG_ENDIAN__)		  // Hitachi SuperH, Motorola 68k
+#define SWAP_BYTES_16(x) \
+  ((((x) >> 8) & 0x00ff) | \
+   (((x) << 8) & 0xff00))
+#define SWAP_BYTES_32(x) \
+  ((((x) >> 24) & 0x000000ff) | \
+   (((x) >> 8)  & 0x0000ff00) | \
+   (((x) << 24) & 0xff000000) | \
+   (((x) << 8)  & 0x00ff0000))
+#else							  // ARM, Intel
+#define SWAP_BYTES_16(x)  (x)
+#define SWAP_BYTES_32(x)  (x)
+#endif // defined(__BIG_ENDIAN__)
+
+
+static inline TUint8 LowByte(TUint16 aWord)
+	{
+	return static_cast<TUint8>(aWord & 0x00ff);
+	}
+
+static inline TUint8 HighByte(TUint16 aWord)
+	{
+	return static_cast<TUint8>((aWord >> 8) & 0x00ff);
+	}
+
+
+//
+// Class-specific Values
+//
+
+// These are from the CDC (valid also for Audio Class)
+const TUint8 KUsbDescType_CS_Interface = 0x24;
+const TUint8 KUsbDescType_CS_Endpoint  = 0x25;
+
+// Audio Device Class
+const TUint KUsbDescSize_AudioEndpoint = KUsbDescSize_Endpoint + 2;
+const TUint KUsbAudioInterfaceClassCode                          = 0x01;
+const TUint KUsbAudioInterfaceSubclassCode_Subclass_Undefined    = 0x00;
+const TUint KUsbAudioInterfaceSubclassCode_Audiocontrol          = 0x01;
+const TUint KUsbAudioInterfaceSubclassCode_Audiostreaming        = 0x02;
+const TUint KUsbAudioInterfaceSubclassCode_Midistreaming         = 0x03;
+const TUint KUsbAudioInterfaceProtocolCode_Pr_Protocol_Undefined = 0x00;
+
+
+//
+// These are defined just for convenience:
+//
+const TUint8 KEp0_Out = 0;
+const TUint8 KEp0_In  = 1;
+const TUint8 KEp0_Rx  = KEp0_Out;
+const TUint8 KEp0_Tx  = KEp0_In;
+
+
+//
+// USB Implementers Forum, Inc (USB-IF) assigned Vendor IDs:
+//
+const TUint16 KUsbVendorId_Symbian = 0x0E22;				// Symbian Ltd. (dec. 3618)
+
+
+#endif // __USB_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/public/usbc.h	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,359 @@
+// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32/include/drivers/usbc.h
+// Kernel side definitions for the USB Device driver stack (PIL + LDD).
+// 
+//
+
+/**
+ @file usbc.h
+ @internalTechnology
+*/
+
+#ifndef __USBC_H__
+#define __USBC_H__
+
+#include <kernel/kernel.h>
+#include <kernel/kern_priv.h>
+#include <kernel/kpower.h>
+#include <platform.h>
+
+#include <usb/d32usbc.h>
+
+//#include <drivers/usbcshared.h>
+#include <usb/usbcshared.h>
+
+
+
+/** LDD Major version, This should agree with the information in RDevUsbcClient::TVer.
+*/
+const TInt KUsbcMajorVersion = 0;
+
+/** LDD Minor version, This should agree with the information in RDevUsbcClient::TVer.
+*/
+const TInt KUsbcMinorVersion = 1;
+
+/** LDD Build version, This should agree with the information in RDevUsbcClient::TVer.
+*/
+const TInt KUsbcBuildVersion = KE32BuildVersionNumber;
+
+/** Must correspond to the max enum of TRequest + 1;
+    currently this is ERequestOtgFeaturesNotify = 10.
+*/
+const TInt KUsbcMaxRequests = 11;
+
+//
+//########################### Logical Device Driver (LDD) #############################
+//
+
+/** USB LDD factory class.
+*/
+class DUsbcLogDevice : public DLogicalDevice
+    {
+public:
+    DUsbcLogDevice();
+    virtual TInt Install();
+    virtual void GetCaps(TDes8& aDes) const;
+    virtual TInt Create(DLogicalChannelBase*& aChannel);
+    };
+
+
+/** OUT buffering is a collection of flat buffers. Each is either fillable or drainable.
+    When one buffer becomes full (notified by the PIL) it is marked as not-fillable and the next
+    fillable buffer is used. When the buffer has finished draining it is marked as fillable.
+*/
+class TDmaBuf
+    {
+public:
+    TDmaBuf();
+     TDmaBuf(TUsbcEndpointInfo* aEndpointInfo, TInt aBandwidthPriority);
+    ~TDmaBuf();
+    TInt Construct(TUsbcEndpointInfo* aEndpointInfo);
+    TInt BufferTotalSize() const;
+    TInt BufferSize() const;
+    TInt SetBufferAddr(TInt aBufInd, TUint8* aBufAddr);
+    TInt BufferNumber() const;
+    void SetMaxPacketSize(TInt aSize);
+    void Flush();
+    // Rx (OUT) variants
+    void RxSetActive();
+    void RxSetInActive();
+    TBool RxIsActive();
+    TBool IsReaderEmpty();
+    void ReadXferComplete(TInt aNoBytesRx, TInt aNoPacketsRx, TInt aErrorCode);
+    TInt RxCopyDataToClient(DThread* aThread, TClientBuffer *aTcb, TInt aLength, TUint32& aDestOffset,
+                            TBool aRUS, TBool& aCompleteNow);
+    TInt RxCopyPacketToClient(DThread* aThread,TClientBuffer *aTcb, TInt aLength);
+    TInt RxGetNextXfer(TUint8*& aBufferAddr, TUsbcPacketArray*& aIndexArray, TUsbcPacketArray*& aSizeArray,
+                       TInt& aLength, TPhysAddr& aBufferPhys);
+    TBool RxIsEnoughSpace(TInt aSize);
+    inline TInt RxBytesAvailable() const;
+    inline void IncrementBufferIndex(TInt& aIndex);
+    inline TInt NoRxPackets() const;
+    TInt SetDrainable(TInt aBufferNum);
+    // Tx (IN) variants
+    void TxSetActive();
+    void TxSetInActive();
+    TBool TxIsActive();
+    TInt TxStoreData(DThread* aThread,TClientBuffer *aTcb, TInt aTxLength, TUint32 aBufferOffset);
+    TInt TxGetNextXfer(TUint8*& aBufferAddr, TInt& aTxLength, TPhysAddr& aBufferPhys);
+    TBool ShortPacketExists();
+
+#if defined(USBC_LDD_BUFFER_TRACE)
+    TInt NoRxPacketsAlt() const;
+    TInt NoRxBytesAlt() const;
+#endif
+
+private:
+    TBool AdvancePacket();
+    inline TInt GetCurrentError();
+    TBool NextDrainableBuffer();
+    TBool NextFillableBuffer();
+    void FreeDrainedBuffers();
+    TInt PeekNextPacketSize();
+    TInt PeekNextDrainableBuffer();
+    void ModifyTotalRxBytesAvail(TInt aVal);
+    void ModifyTotalRxPacketsAvail(TInt aVal);
+    void AddToDrainQueue(TInt aBufferIndex);
+    inline TInt CopyToUser(DThread* aThread, const TUint8* aSourceAddr, TInt aLength,
+                           TClientBuffer *aTcb, TUint32& aDestOffset);
+private:
+    TInt iExtractOffset;                                    // offset into current packet for data read
+    TInt iMaxPacketSize;
+    TInt iNumberofBuffers;
+    TInt iBufSz;
+    TBool iRxActive;
+    TBool iTxActive;
+    TInt iTotalRxBytesAvail;
+    TInt iTotalRxPacketsAvail;
+    //
+    TUint8* iBufBasePtr;
+    TUint8* iCurrentDrainingBuffer;
+    TInt iCurrentDrainingBufferIndex;
+    TInt iCurrentFillingBufferIndex;
+    TUint iCurrentPacket;
+    TUsbcPacketArray* iCurrentPacketIndexArray;
+    TUsbcPacketArray* iCurrentPacketSizeArray;
+    TUint8* iBuffers[KUsbcDmaBufNumMax];
+    TBool iDrainable[KUsbcDmaBufNumMax];
+    TUsbcPacketArray iPacketInfoStorage[KUsbcDmaBufNumMax * KUsbcDmaBufNumArrays * KUsbcDmaBufMaxPkts];
+    TUsbcPacketArray* iPacketIndex[KUsbcDmaBufNumMax];
+    TUsbcPacketArray* iPacketSize[KUsbcDmaBufNumMax];
+    TUint iNumberofBytesRx[KUsbcDmaBufNumMax];
+    TUint iNumberofPacketsRx[KUsbcDmaBufNumMax];
+    TInt iError[KUsbcDmaBufNumMax];
+    TPhysAddr iBufferPhys[KUsbcDmaBufNumMax];
+    TBool iCanBeFreed[KUsbcDmaBufNumMax];
+    TInt iDrainQueue[KUsbcDmaBufNumMax + 1];
+    TInt iDrainQueueIndex;
+    TUint iEndpointType;
+
+#if defined(USBC_LDD_BUFFER_TRACE)
+    TInt iFillingOrder;
+    TInt iFillingOrderArray[KUsbcDmaBufNumMax];
+    TInt iDrainingOrder;
+     TUint iNumberofBytesRxRemain[KUsbcDmaBufNumMax];
+     TUint iNumberofPacketsRxRemain[KUsbcDmaBufNumMax];
+#endif
+    };
+
+
+class DLddUsbcChannel;
+
+/** Endpoint tracking for the LDD buffering etc.
+*/
+class TUsbcEndpoint
+    {
+public:
+    TUsbcEndpoint();
+    TUsbcEndpoint(DLddUsbcChannel* aLDD, DUsbClientController* aController,
+                  const TUsbcEndpointInfo* aEndpointInfo, TInt aEndpointNum,
+                  TInt aBandwidthPriority);
+    ~TUsbcEndpoint();
+    TInt Construct();
+    TInt TryToStartRead(TBool aReEntrant);
+    TInt TryToStartWrite(TEndpointTransferInfo* pTfr);
+    TInt CopyToClient(DThread* aThread, TClientBuffer *aTcb);
+    TInt CopyToClient(DThread* aClient, TBool& aCompleteNow, TClientBuffer *aTcb);
+    TInt ContinueWrite();
+    void SetMaxPacketSize(TInt aSize);
+    void CancelTransfer(DThread* aThread, TClientBuffer *aTcb);
+    void AbortTransfer();
+    inline TUsbcEndpointInfo* EndpointInfo();
+    inline TInt RxBytesAvailable() const;
+
+    inline TInt BufferSize() const;
+    inline TInt SetBufferAddr( TInt aBufInd, TUint8* aAddr);
+    inline TInt BufferNumber() const;
+
+    inline void SetTransferInfo(TEndpointTransferInfo* aTransferInfo);
+    inline void ResetTransferInfo();
+    inline void SetClientReadPending(TBool aVal);
+    inline void SetClientWritePending(TBool aVal);
+    inline TBool ClientWritePending();
+    inline TBool ClientReadPending();
+    inline void SetRealEpNumber(TInt aRealEpNumber);
+    inline TInt RealEpNumber() const;
+
+public:
+    TDmaBuf* iDmaBuffers;
+
+private:
+    static void RequestCallback(TAny* aTUsbcEndpoint);
+    void TxComplete();
+    TInt RxComplete(TBool aReEntrant);
+    void RxCompleteNow();
+    TInt EndpointComplete();
+
+private:
+    DUsbClientController* iController;
+    TUsbcEndpointInfo iEndpointInfo;
+    TEndpointTransferInfo iTransferInfo;
+    TBool iClientReadPending;
+    TBool iClientWritePending;
+    TInt iEndpointNumber;
+    TInt iRealEpNumber;
+    DLddUsbcChannel* iLdd;
+    TInt iError;
+    TUsbcRequestCallback* iRequestCallbackInfo;
+    TUint32 iBytesTransferred;
+    TInt iBandwidthPriority;
+    };
+
+
+/** Linked list of 'alternate setting' info for use by the LDD.
+*/
+class TUsbcAlternateSettingList
+    {
+public:
+    TUsbcAlternateSettingList();
+    ~TUsbcAlternateSettingList();
+
+public:
+    TUsbcAlternateSettingList* iNext;
+    TInt iNumberOfEndpoints;
+    TUint iSetting;
+    TInt iEpNumDeOrderedByBufSize[KMaxEndpointsPerClient + 1];
+    TUsbcEndpoint* iEndpoint[KMaxEndpointsPerClient + 1];
+    };
+
+
+struct TClientAsynchNotify
+    {
+        TClientBufferRequest *iBufferRequest;
+        TClientBuffer *iClientBuffer;
+        void Reset();
+    };
+/** The channel class - the actual USB LDD.
+*/
+class DLddUsbcChannel : public DLogicalChannel
+    {
+public:
+    DLddUsbcChannel();
+    ~DLddUsbcChannel();
+    virtual TInt SendMsg(TMessageBase * aMsg);
+    TInt PreSendRequest(TMessageBase * aMsg,TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2);
+    TInt SendControl(TMessageBase* aMsg);
+    virtual void HandleMsg(TMessageBase* aMsg);
+    virtual TInt DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer);
+    virtual TInt RequestUserHandle(DThread* aThread, TOwnerType aType);
+    TInt DoRxComplete(TUsbcEndpoint* aTUsbcEndpoint, TInt aEndpoint, TBool aReentrant);
+    void DoRxCompleteNow(TUsbcEndpoint* aTUsbcEndpoint, TInt aEndpoint);
+    void DoTxComplete(TUsbcEndpoint* aTUsbcEndpoint, TInt aEndpoint, TInt aError);
+    inline DThread* Client() const {return iClient;}
+    inline TBool ChannelClosing() const {return iChannelClosing;}
+    inline TUint AlternateSetting() const {return iAlternateSetting;}
+    TClientBuffer *GetClientBuffer(TInt aEndpoint);
+
+private:
+    TInt DoCancel(TInt aReqNo);
+    void DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2);
+    TInt DoControl(TInt aFunction, TAny* a1, TAny* a2);
+    TInt DoTransferAsyncReq(TInt aEndpointNum, TAny* a1, TAny* a2, TBool& aNeedsCompletion);
+    TInt DoOtherAsyncReq(TInt aReqNo, TAny* a1, TAny* a2, TBool& aNeedsCompletion);
+    TBool AlternateDeviceStateTestComplete();
+    TInt SetInterface(TInt aInterfaceNum, TUsbcIfcInfo* aUserInterfaceInfoBuf);
+    void StartEpReads();
+    void DestroyAllInterfaces();
+    void DestroyInterface(TUint aInterface);
+    void DestroyEp0();
+    inline TBool ValidEndpoint(TInt aEndpoint);
+    TInt DoEmergencyComplete();
+    void ReadDes8(const TAny* aPtr, TDes8& aDes);
+    TInt SetupEp0();
+    DPlatChunkHw* ReAllocate(TInt aBuffersize, DPlatChunkHw* aHwChunk, TUint32 aCacheAttribs);
+    DPlatChunkHw* Allocate(TInt aBuffersize, TUint32 aCacheAttribs);
+    void ClosePhysicalChunk(DPlatChunkHw* &aHwChunk);
+    void CancelNotifyEndpointStatus();
+    void CancelNotifyOtgFeatures();
+    static void StatusChangeCallback(TAny* aDLddUsbcChannel);
+    static void EndpointStatusChangeCallback(TAny* aDLddUsbcChannel);
+    static void OtgFeatureChangeCallback(TAny* aDLddUsbcChannel);
+    static void EmergencyCompleteDfc(TAny* aDLddUsbcChannel);
+    void DeConfigure(TInt aErrorCode);
+    TInt SelectAlternateSetting(TUint aAlternateSetting);
+    TInt EpFromAlternateSetting(TUint aAlternateSetting, TInt aEndpoint);
+    TInt ProcessAlternateSetting(TUint aAlternateSetting);
+    TInt ProcessDeviceState(TUsbcDeviceState aDeviceState);
+    void ResetInterface(TInt aErrorCode);
+    void AbortInterface();
+    // Set buffer address of the interface
+    void ReSetInterfaceMemory(TUsbcAlternateSettingList* aAlternateSettingListRec,
+            RArray<DPlatChunkHw*> &aHwChunks );
+    void UpdateEndpointSizes();
+    // Check and alloc memory for the interface
+    TInt SetupInterfaceMemory(RArray<DPlatChunkHw*> &aHwChunks, 
+            TUint32 aCacheAttribs );
+    void PanicClientThread(TInt aReason);
+    TInt PinMemory(TDesC8 *aDes, TVirtualPinObject *iPinObj); //Descriptor pinning helper.
+    void CompleteBufferRequest(DThread* aThread, TInt aReqNo, TInt aReason);
+private:
+    DUsbClientController* iController;
+    DThread* iClient;
+    TBool iValidInterface;
+    TUsbcAlternateSettingList* iAlternateSettingList;
+    TUsbcEndpoint* iEndpoint[KMaxEndpointsPerClient + 1];    // include ep0
+    TRequestStatus* iRequestStatus[KUsbcMaxRequests];
+    TClientAsynchNotify* iClientAsynchNotify[KUsbcMaxRequests];
+    TUsbcClientCallback iCompleteAllCallbackInfo;
+    TAny* iStatusChangePtr;
+    TUsbcStatusCallback iStatusCallbackInfo;
+    TAny* iEndpointStatusChangePtr;
+    TUsbcEndpointStatusCallback iEndpointStatusCallbackInfo;
+    TAny* iOtgFeatureChangePtr;
+    TUsbcOtgFeatureCallback iOtgFeatureCallbackInfo;
+    TInt iNumberOfEndpoints;
+    RArray<DPlatChunkHw*> iHwChunksEp0;
+    RArray<DPlatChunkHw*> iHwChunks;
+
+    TUsbcDeviceState iDeviceState;
+    TUsbcDeviceState iOldDeviceState;
+    TBool iOwnsDeviceControl;
+    TUint iAlternateSetting;
+    TBool iDeviceStatusNeeded;
+    TUsbcDeviceStatusQueue* iStatusFifo;
+    TBool iChannelClosing;
+    TVirtualPinObject *iPinObj1;
+    TVirtualPinObject *iPinObj2;
+    TVirtualPinObject *iPinObj3;
+    TClientDataRequest<TUint> *iStatusChangeReq;
+    TClientDataRequest<TUint> *iEndpointStatusChangeReq;
+    TClientDataRequest<TUint> *iOtgFeatureChangeReq;
+    TEndpointTransferInfo iTfrInfo;
+    };
+
+
+#include <usb/usbc.inl>
+
+#endif    // __USBC_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/public/usbc.inl	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,115 @@
+// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\include\drivers\usbc.inl
+// Kernel side inline header file for USB device driver.
+// 
+//
+
+/**
+ @file usbc.inl
+ @internalTechnology
+*/
+
+#ifndef __USBC_INL__
+#define __USBC_INL__
+
+
+// --- USB Logical Device Driver (LDD) ---
+//
+
+TInt TDmaBuf::RxBytesAvailable() const
+	{
+	return iTotalRxBytesAvail;
+	}
+
+
+TUsbcEndpointInfo* TUsbcEndpoint::EndpointInfo()
+	{
+	return &iEndpointInfo;
+	}
+
+
+TInt TUsbcEndpoint::RxBytesAvailable() const
+	{
+	return iDmaBuffers->RxBytesAvailable();
+	}
+
+TInt TUsbcEndpoint::BufferSize() const
+    {
+    return iDmaBuffers->BufferSize();
+    }
+TInt TUsbcEndpoint::SetBufferAddr( TInt aBufInd, TUint8* aBufAddr)
+    {
+    return iDmaBuffers->SetBufferAddr(aBufInd, aBufAddr);
+    }
+TInt TUsbcEndpoint::BufferNumber() const
+    {
+    return iDmaBuffers->BufferNumber();
+    }
+
+void TUsbcEndpoint::SetTransferInfo(TEndpointTransferInfo* aTransferInfo)
+	{
+	iTransferInfo = *aTransferInfo;
+	iBytesTransferred = 0;
+	}
+
+
+void TUsbcEndpoint::ResetTransferInfo()
+	{
+	iTransferInfo.iDes = NULL;
+	iTransferInfo.iTransferType = ETransferTypeNone;
+	iTransferInfo.iTransferSize = 0;
+	iTransferInfo.iZlpReqd = EFalse;
+	iBytesTransferred = 0;
+	}
+
+
+void TUsbcEndpoint::SetClientReadPending(TBool aVal)
+	{
+	iClientReadPending = aVal;
+	}
+
+
+TBool TUsbcEndpoint::ClientReadPending()
+	{
+	return iClientReadPending;
+	}
+
+
+void TUsbcEndpoint::SetClientWritePending(TBool aVal)
+	{
+	iClientWritePending = aVal;
+	}
+
+
+TBool TUsbcEndpoint::ClientWritePending()
+	{
+	return iClientWritePending;
+	}
+
+
+void TUsbcEndpoint::SetRealEpNumber(TInt aRealEpNumber)
+	{
+	iRealEpNumber = aRealEpNumber;
+	iRequestCallbackInfo->iRealEpNum = aRealEpNumber;
+	}
+
+
+TInt TUsbcEndpoint::RealEpNumber() const
+	{
+	return iRealEpNumber;
+	}
+
+
+#endif // __USBC_INL__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/public/usbcdesc.h	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,360 @@
+// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32/include/drivers/usbcdesc.h
+// USB descriptors and their management.
+// 
+//
+
+/**
+ @file usbcdesc.h
+ @internalTechnology
+*/
+
+#ifndef __USBCDESC_H__
+#define __USBCDESC_H__
+
+#include <kernel/kernel.h>
+
+
+// Hard-wired positions of some descriptors in iDescriptors array (whether present or not):
+static const TInt KDescPosition_Device           = 0;
+static const TInt KDescPosition_DeviceQualifier  = 1;
+static const TInt KDescPosition_OtherSpeedConfig = 2;
+static const TInt KDescPosition_Config           = 3;
+static const TInt KDescPosition_Otg              = 4;
+static const TInt KDescPosition_FirstAvailable   = 5;
+
+// Hard-wired positions of string descriptors in iStrings array (whether present or not):
+static const TInt KStringPosition_Langid           = 0;
+static const TInt KStringPosition_Manufact         = 1;
+static const TInt KStringPosition_Product          = 2;
+static const TInt KStringPosition_Serial           = 3;
+static const TInt KStringPosition_Config           = 4;
+static const TInt KStringPosition_OtherSpeedConfig = 5;
+static const TInt KStringPosition_FirstAvailable   = 6;
+
+
+NONSHARABLE_CLASS(TUsbcDescriptorBase)
+    {
+public:
+    virtual ~TUsbcDescriptorBase();
+    void SetByte(TInt aPosition, TUint8 aValue);
+    void SetWord(TInt aPosition, TUint16 aValue);
+    TUint8 Byte(TInt aPosition) const;
+    TUint16 Word(TInt aPosition) const;
+    void GetDescriptorData(TDes8& aBuffer) const;
+    TInt GetDescriptorData(TUint8* aBuffer) const;
+    TInt GetDescriptorData(TUint8* aBuffer, TUint aMaxSize) const;
+    const TDes8& DescriptorData() const;
+    TDes8& DescriptorData();
+    TUint Size() const;
+    TUint8 Type() const;
+    virtual void UpdateFs();
+    virtual void UpdateHs();
+protected:
+    TUsbcDescriptorBase();
+    void SetBufferPointer(const TDesC8& aDes);
+private:
+#ifdef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST
+    TUint8 iIndex;                                            // only needed for SET_DESCRIPTOR
+#endif
+    TPtr8 iBufPtr;
+    };
+
+
+NONSHARABLE_CLASS(TUsbcDeviceDescriptor) : public TUsbcDescriptorBase
+    {
+public:
+    /** aMaxPacketSize0 should be the Ep0 max packet size for FS operation (as the HS size
+        is fixed and known).
+    */
+    static TUsbcDeviceDescriptor* New(TUint8 aDeviceClass, TUint8 aDeviceSubClass,
+                                      TUint8 aDeviceProtocol, TUint8 aMaxPacketSize0,
+                                      TUint16 aVendorId, TUint16 aProductId,
+                                      TUint16 aDeviceRelease, TUint8 aNumConfigurations);
+    virtual void UpdateFs();
+    virtual void UpdateHs();
+private:
+    TUsbcDeviceDescriptor();
+    TInt Construct(TUint8 aDeviceClass, TUint8 aDeviceSubClass, TUint8 aDeviceProtocol,
+                   TUint8 aMaxPacketSize0, TUint16 aVendorId, TUint16 aProductId,
+                   TUint16 aDeviceRelease, TUint8 aNumConfigurations);
+    TBuf8<KUsbDescSize_Device> iBuf;
+    TUint8 iEp0Size_Fs;                                        // holds Ep0 size for FS (could be < 64)
+    };
+
+
+NONSHARABLE_CLASS(TUsbcDeviceQualifierDescriptor) : public TUsbcDescriptorBase
+    {
+public:
+    /** aMaxPacketSize0 should be the Ep0 max packet size for FS operation (as the HS size
+        is fixed and known).
+    */
+    static TUsbcDeviceQualifierDescriptor* New(TUint8 aDeviceClass, TUint8 aDeviceSubClass,
+                                               TUint8 aDeviceProtocol, TUint8 aMaxPacketSize0,
+                                               TUint8 aNumConfigurations, TUint8 aReserved=0);
+    virtual void UpdateFs();
+    virtual void UpdateHs();
+private:
+    TUsbcDeviceQualifierDescriptor();
+    TInt Construct(TUint8 aDeviceClass, TUint8 aDeviceSubClass, TUint8 aDeviceProtocol,
+                   TUint8 aMaxPacketSize0, TUint8 aNumConfigurations, TUint8 aReserved);
+    TBuf8<KUsbDescSize_DeviceQualifier> iBuf;
+    TUint8 iEp0Size_Fs;                                        // holds Ep0 size for FS (could be < 64)
+    };
+
+
+NONSHARABLE_CLASS(TUsbcConfigDescriptor) : public TUsbcDescriptorBase
+    {
+public:
+    /** aMaxPower should be given here in milliamps (not mA/2). */
+    static TUsbcConfigDescriptor* New(TUint8 aConfigurationValue, TBool aSelfPowered, TBool aRemoteWakeup,
+                                      TUint16 aMaxPower);
+private:
+    TUsbcConfigDescriptor();
+    TInt Construct(TUint8 aConfigurationValue, TBool aSelfPowered, TBool aRemoteWakeup, TUint16 aMaxPower);
+    TBuf8<KUsbDescSize_Config> iBuf;
+    };
+
+
+// The Other_Speed_Configuration descriptor has same size and layout as the
+// standard Configuration descriptor, therefore we don't need a new definition.
+typedef TUsbcConfigDescriptor TUsbcOtherSpeedConfigDescriptor;
+
+
+NONSHARABLE_CLASS(TUsbcInterfaceDescriptor) : public TUsbcDescriptorBase
+    {
+public:
+    static TUsbcInterfaceDescriptor* New(TUint8 aInterfaceNumber, TUint8 aAlternateSetting, TInt NumEndpoints,
+                                         const TUsbcClassInfo& aClassInfo);
+private:
+    TUsbcInterfaceDescriptor();
+    TInt Construct(TUint8 aInterfaceNumber, TUint8 aAlternateSetting, TInt aNumEndpoints,
+                   const TUsbcClassInfo& aClassInfo);
+    TBuf8<KUsbDescSize_Interface> iBuf;
+    };
+
+
+NONSHARABLE_CLASS(TUsbcEndpointDescriptorBase) : public TUsbcDescriptorBase
+    {
+public:
+    virtual void UpdateFs();
+    virtual void UpdateHs();
+protected:
+    TInt Construct(const TUsbcEndpointInfo& aEpInfo);
+    TUsbcEndpointDescriptorBase();
+protected:
+    /** Stores the endpoint size to be used for FS. */
+    TInt iEpSize_Fs;
+    /** Stores the endpoint size to be used for HS. */
+    TInt iEpSize_Hs;
+    /** Stores the endpoint polling interval to be used for FS. */
+    TInt iInterval_Fs;
+    /** Stores the endpoint polling interval to be used for HS. */
+    TInt iInterval_Hs;
+    };
+
+
+NONSHARABLE_CLASS(TUsbcEndpointDescriptor) : public TUsbcEndpointDescriptorBase
+    {
+public:
+    static TUsbcEndpointDescriptor* New(TUint8 aEndpointAddress, const TUsbcEndpointInfo& aEpInfo);
+private:
+    TUsbcEndpointDescriptor();
+    TInt Construct(TUint8 aEndpointAddress, const TUsbcEndpointInfo& aEpInfo);
+    TBuf8<KUsbDescSize_Endpoint> iBuf;
+    };
+
+
+class TUsbcAudioEndpointDescriptor : public TUsbcEndpointDescriptorBase
+    {
+public:
+    static TUsbcAudioEndpointDescriptor* New(TUint8 aEndpointAddress, const TUsbcEndpointInfo& aEpInfo);
+private:
+    TUsbcAudioEndpointDescriptor();
+    TInt Construct(TUint8 aEndpointAddress, const TUsbcEndpointInfo& aEpInfo);
+    TBuf8<KUsbDescSize_AudioEndpoint> iBuf;
+    };
+
+
+NONSHARABLE_CLASS(TUsbcOtgDescriptor) : public TUsbcDescriptorBase
+    {
+public:
+    static TUsbcOtgDescriptor* New(TBool aHnpSupport, TBool aSrpSupport);
+private:
+    TUsbcOtgDescriptor();
+    TInt Construct(TBool aHnpSupport, TBool aSrpSupport);
+    TBuf8<KUsbDescSize_Otg> iBuf;
+    };
+
+
+NONSHARABLE_CLASS(TUsbcClassSpecificDescriptor) : public TUsbcDescriptorBase
+    {
+public:
+    virtual ~TUsbcClassSpecificDescriptor();
+    static TUsbcClassSpecificDescriptor* New(TUint8 aType, TInt aSize);
+private:
+    TUsbcClassSpecificDescriptor();
+    TInt Construct(TUint8 aType, TInt aSize);
+    HBuf8* iBuf;
+    };
+
+
+NONSHARABLE_CLASS(TUsbcStringDescriptorBase)
+    {
+public:
+    virtual ~TUsbcStringDescriptorBase();
+    TUint16 Word(TInt aPosition) const;
+    void SetWord(TInt aPosition, TUint16 aValue);
+    TInt GetDescriptorData(TUint8* aBuffer) const;
+    TInt GetDescriptorData(TUint8* aBuffer, TUint aMaxSize) const;
+    const TDes8& StringData() const;
+    TDes8& StringData();
+    TUint Size() const;
+    void SetBufferPointer(const TDesC8& aDes);
+protected:
+    TUsbcStringDescriptorBase();
+    TBuf8<2> iSBuf;
+    TPtr8 iBufPtr;
+private:
+//    TUint8 iIndex;                                            // not needed in DescriptorPool: position == index
+    };
+
+
+NONSHARABLE_CLASS(TUsbcStringDescriptor) : public TUsbcStringDescriptorBase
+    {
+public:
+    virtual ~TUsbcStringDescriptor();
+    static TUsbcStringDescriptor* New(const TDesC8& aString);
+private:
+    TUsbcStringDescriptor();
+    TInt Construct(const TDesC8& aString);
+    HBuf8* iBuf;
+    };
+
+
+// Currently we support only one language, and thus there's no need to provide
+// a LangId string descriptor with more than one array element.
+NONSHARABLE_CLASS(TUsbcLangIdDescriptor) : public TUsbcStringDescriptorBase
+    {
+public:
+    virtual ~TUsbcLangIdDescriptor();
+    static TUsbcLangIdDescriptor* New(TUint16 aLangId);
+private:
+    TUsbcLangIdDescriptor();
+    TInt Construct(TUint16 aLangId);
+    TBuf8<2> iBuf;
+    };
+
+
+class TUsbcDescriptorPool
+    {
+public:
+    TUsbcDescriptorPool(TUint8* aEp0_TxBuf);
+    ~TUsbcDescriptorPool();
+    TInt Init(TUsbcDeviceDescriptor* aDeviceDesc, TUsbcConfigDescriptor* aConfigDesc,
+              TUsbcLangIdDescriptor* aLangId, TUsbcStringDescriptor* aManufacturer,
+              TUsbcStringDescriptor* aProduct, TUsbcStringDescriptor* aSerialNum,
+              TUsbcStringDescriptor* aConfig, TUsbcOtgDescriptor* aOtgDesc);
+    TInt InitHs();
+    TInt UpdateDescriptorsFs();
+    TInt UpdateDescriptorsHs();
+
+    // Descriptors
+    TInt FindDescriptor(TUint8 aType, TUint8 aIndex, TUint16 aLangid, TInt& aSize) const;
+    void InsertDescriptor(TUsbcDescriptorBase* aDesc);
+    void DeleteIfcDescriptor(TInt aNumber, TInt aSetting=0);
+    // The TC in many of the following functions stands for 'ThreadCopy' because that's what happens there.
+    TInt GetDeviceDescriptorTC(DThread* aThread, TDes8& aBuffer) const;
+    TInt SetDeviceDescriptorTC(DThread* aThread, const TDes8& aBuffer);
+    TInt GetConfigurationDescriptorTC(DThread* aThread, TDes8& aBuffer) const;
+    TInt SetConfigurationDescriptorTC(DThread* aThread, const TDes8& aBuffer);
+    TInt GetOtgDescriptorTC(DThread* aThread, TDes8& aBuffer) const;
+    TInt SetOtgDescriptor(const TDesC8& aBuffer);
+    TInt GetInterfaceDescriptorTC(DThread* aThread, TDes8& aBuffer, TInt aInterface, TInt aSetting) const;
+    TInt SetInterfaceDescriptor(const TDes8& aBuffer, TInt aInterface, TInt aSetting);
+    TInt GetEndpointDescriptorTC(DThread* aThread, TDes8& aBuffer, TInt aInterface, TInt aSetting,
+                                 TUint8 aEndpointAddress) const;
+    TInt SetEndpointDescriptorTC(DThread* aThread, const TDes8& aBuffer, TInt aInterface, TInt aSetting,
+                                 TUint8 aEndpointAddress);
+    TInt GetEndpointDescriptorSize(TInt aInterface, TInt aSetting, TUint8 aEndpointAddress, TInt& aSize) const;
+    TInt GetDeviceQualifierDescriptorTC(DThread* aThread, TDes8& aBuffer) const;
+    TInt SetDeviceQualifierDescriptorTC(DThread* aThread, const TDes8& aBuffer);
+    TInt GetOtherSpeedConfigurationDescriptorTC(DThread* aThread, TDes8& aBuffer) const;
+    TInt SetOtherSpeedConfigurationDescriptorTC(DThread* aThread, const TDes8& aBuffer);
+    TInt GetCSInterfaceDescriptorTC(DThread* aThread, TDes8& aBuffer, TInt aInterface, TInt aSetting) const;
+    TInt SetCSInterfaceDescriptorTC(DThread* aThread, const TDes8& aBuffer, TInt aInterface, TInt aSetting,
+                                    TInt aSize);
+    TInt GetCSInterfaceDescriptorSize(TInt aInterface, TInt aSetting, TInt& aSize) const;
+    TInt GetCSEndpointDescriptorTC(DThread* aThread, TDes8& aBuffer, TInt aInterface, TInt aSetting,
+                                   TUint8 aEndpointAddress) const;
+    TInt SetCSEndpointDescriptorTC(DThread* aThread, const TDes8& aBuffer, TInt aInterface, TInt aSetting,
+                                   TUint8 aEndpointAddress, TInt aSize);
+    TInt GetCSEndpointDescriptorSize(TInt aInterface, TInt aSetting, TUint8 aEndpointAddress, TInt& aSize) const;
+
+    // String descriptors
+    void SetIfcStringDescriptor(TUsbcStringDescriptor* aDesc, TInt aNumber, TInt aSetting=0);
+    TInt GetStringDescriptorLangIdTC(DThread* aThread, TDes8& aLangId) const;
+    TInt SetStringDescriptorLangId(TUint16 aLangId);
+    TInt GetManufacturerStringDescriptorTC(DThread* aThread, TDes8& aString) const;
+    TInt SetManufacturerStringDescriptorTC(DThread* aThread, const TDes8& aString);
+    TInt RemoveManufacturerStringDescriptor();
+    TInt GetProductStringDescriptorTC(DThread* aThread, TDes8& aString) const;
+    TInt SetProductStringDescriptorTC(DThread* aThread, const TDes8& aString);
+    TInt RemoveProductStringDescriptor();
+    TInt GetSerialNumberStringDescriptorTC(DThread* aThread, TDes8& aString) const;
+    TInt SetSerialNumberStringDescriptorTC(DThread* aThread, const TDes8& aString);
+    TInt RemoveSerialNumberStringDescriptor();
+    TInt GetConfigurationStringDescriptorTC(DThread* aThread, TDes8& aString) const;
+    TInt SetConfigurationStringDescriptorTC(DThread* aThread, const TDes8& aString);
+    TInt RemoveConfigurationStringDescriptor();
+    TInt GetStringDescriptorTC(DThread* aThread, TInt aIndex, TDes8& aString) const;
+    TInt SetStringDescriptorTC(DThread* aThread, TInt aIndex, const TDes8& aString);
+    TInt RemoveStringDescriptor(TInt aIndex);
+
+private:
+    // Descriptors
+    void InsertIfcDesc(TUsbcDescriptorBase* aDesc);
+    void InsertEpDesc(TUsbcDescriptorBase* aDesc);
+    TInt FindIfcDescriptor(TInt aIfcNumber, TInt aIfcSetting) const;
+    TInt FindEpDescriptor(TInt aIfcNumber, TInt aIfcSetting, TUint8 aEpAddress) const;
+    void DeleteDescriptors(TInt aIndex, TInt aCount = 1);
+    void UpdateConfigDescriptorLength(TInt aLength);
+    void UpdateConfigDescriptorNumIfcs(TInt aNumber);
+    void UpdateIfcNumbers(TInt aNumber);
+    TInt GetDeviceDescriptor(TInt aIndex) const;
+    TInt GetConfigurationDescriptor(TInt aIndex) const;
+    TInt GetOtgDescriptor() const;
+
+    // String descriptors
+    TInt GetStringDescriptor(TInt aIndex) const;
+    TInt GetDeviceStringDescriptorTC(DThread* aThread, TDes8& aString, TInt aIndex, TInt aPosition) const;
+    TInt SetDeviceStringDescriptorTC(DThread* aThread, const TDes8& aString, TInt aIndex, TInt aPosition);
+    TInt RemoveDeviceStringDescriptor(TInt aIndex, TInt aPosition);
+    void ExchangeStringDescriptor(TInt aIndex, const TUsbcStringDescriptor* aDesc);
+    TBool AnyStringDescriptors() const;
+    TBool StringDescriptorExists(TInt aIndex) const;
+    TInt FindAvailableStringPos() const;
+
+private:
+    // Data members
+    RPointerArray<TUsbcDescriptorBase> iDescriptors;
+    RPointerArray<TUsbcStringDescriptorBase> iStrings;
+    TInt iIfcIdx;
+    TUint8* const iEp0_TxBuf;                                // points to the controller's ep0 TX buffer
+    TBool iHighSpeed;                                        // true if currently operating at high-speed
+    };
+
+
+#endif    // __USBCDESC_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/public/usbcontrolxferif.h	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,60 @@
+/*
+  Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). 
+  All rights reserved.
+
+  This program and the accompanying materials are made available 
+  under the terms of the Eclipse Public License v1.0 which accompanies 
+  this distribution, and is available at 
+  http://www.eclipse.org/legal/epl-v10.html
+
+  Initial Contributors:
+  Nokia Corporation - initial contribution.
+
+  Contributors:
+*/
+
+#ifndef USBCONTROLXFERIF_H
+#define USBCONTROLXFERIF_H
+
+#include <e32def.h>                 // General types definition
+
+/** 
+ * Callback interfaces that used to process packet received from Host
+ * and interfaces through which that PIL or app can send request to PSL
+ */
+NONSHARABLE_CLASS(MControlTransferIf)
+    {
+    public:
+        // Interface for RX
+        // Transfer direction from Device to Host
+        // This two interface is saying PSL had finished
+        // sending those data to host.
+        virtual void ProcessDataInPacket(TInt aCount,TInt aErrCode) = 0;
+        virtual void ProcessStatusInPacket(TInt aErrCode) = 0;
+        
+        // Transfer direction from Host to Device
+        // they are saying that some data had been recieved from host
+        virtual void ProcessDataOutPacket(TInt aCount,TInt aErrCode) = 0;
+        virtual void ProcessStatusOutPacket(TInt aErrCode) = 0;
+        virtual void ProcessSetupPacket(TInt aCount,TInt aErrCode) = 0;
+        
+        // Interface for TX and Control
+        // Data/Status transfer function
+        virtual TInt ProcessSetupEndpointZeroRead() = 0;
+        virtual TInt ProcessSetupEndpointZeroWrite(const TUint8* aBuffer, TInt aLength, TBool aZlpReqd=EFalse) = 0;
+        virtual TInt ProcessSendEp0ZeroByteStatusPacket() = 0;
+        virtual TInt ProcessStallEndpoint(TInt aRealEndpoint) = 0;
+        
+        // Flow control interface
+        // In case of we can not deliver received packet(setup or data) to a registered client
+        // (because the request callback is not ready), we need PSL stop reporting more packet
+        // to PIL until the pending packet had been process.
+        // this 2 functions is used to notify PSL: you can continue, the pending packet is proceed.
+        virtual void ProcessEp0SetupPacketProceed() = 0;
+        virtual void ProcessEp0DataPacketProceed() = 0;
+    };
+
+#endif //USBCONTROLXFERIF_H
+
+// End of file
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/public/usbcque.h	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,147 @@
+// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\include\drivers\usbcque.h
+// Simple singly linked list + its iterator for the USB Device driver.
+// 
+//
+
+/**
+ @file usbcque.h
+ @internalTechnology
+*/
+
+#ifndef __USBCQUE_H__
+#define __USBCQUE_H__
+
+#include <kernel/kernel.h>
+
+
+//
+// --- Class definitions ---
+//
+
+class TSglQueLink
+	{
+private:
+	void Enque(TSglQueLink* aLink);
+public:
+	TSglQueLink* iNext;
+	friend class TSglQueBase;
+	};
+
+
+class TSglQueBase
+	{
+protected:
+	TSglQueBase(TInt aOffset);
+	void DoAddLast(TAny* aPtr);
+	void DoRemove(TAny* aPtr);
+protected:
+	TSglQueLink* iHead;
+	TSglQueLink* iLast;
+	TInt iOffset;
+	TInt iElements;
+private:
+	friend class TSglQueIterBase;
+	};
+
+
+template<class T>
+class TSglQue : public TSglQueBase
+	{
+public:
+	inline TSglQue(TInt aOffset);
+	inline void AddLast(T& aRef);
+	inline void Remove(T& aRef);
+	inline TInt Elements() const;
+	};
+
+
+class TSglQueIterBase
+	{
+public:
+	void SetToFirst();
+protected:
+	TSglQueIterBase(TSglQueBase& aQue);
+	TAny* DoPostInc();
+	TAny* DoCurrent();
+protected:
+	TInt iOffset;
+	TSglQueLink*& iHead;
+	TSglQueLink* iNext;
+	};
+
+
+template<class T>
+class TSglQueIter : public TSglQueIterBase
+	{
+public:
+	inline TSglQueIter(TSglQueBase& aQue);
+	inline operator T*();
+	inline T* operator++(TInt);
+	};
+
+//
+// --- Inline implementations ---
+//
+
+// Class TSglQue
+template<class T>
+inline TSglQue<T>::TSglQue(TInt aOffset)
+	: TSglQueBase(aOffset)
+	{}
+
+
+template<class T>
+inline void TSglQue<T>::AddLast(T& aRef)
+	{
+	DoAddLast(&aRef);
+	}
+
+
+template<class T>
+inline void TSglQue<T>::Remove(T& aRef)
+	{
+	DoRemove(&aRef);
+	}
+
+
+template<class T>
+inline TInt TSglQue<T>::Elements() const
+	{
+	return iElements;
+	}
+
+
+// Class TSglQueIter
+template<class T>
+inline TSglQueIter<T>::TSglQueIter(TSglQueBase& aQue)
+	: TSglQueIterBase(aQue)
+	{}
+
+
+template<class T>
+inline TSglQueIter<T>::operator T*()
+	{
+	return ((T*)DoCurrent());
+	}
+
+template<class T>
+inline T* TSglQueIter<T>::operator++(TInt)
+	{
+	return ((T*)DoPostInc());
+	}
+
+
+#endif	// __USBCQUE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/public/usbcsc.h	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,500 @@
+// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\include\drivers\usbcsc.h
+// Kernel side definitions for the USB Device driver stack (PIL + LDD).
+// 
+//
+
+/**
+ @file usbcsc.h
+ @internalTechnology
+*/
+
+#ifndef __USBCSC_H__
+#define __USBCSC_H__
+
+#include <kernel/kernel.h>
+#include <kernel/kern_priv.h>
+#include <kernel/kpower.h>
+#include <platform.h>
+
+#include <usb/d32usbcsc.h>
+
+// #include <drivers/usbcshared.h>
+#include <usb/usbcshared.h>
+
+/** LDD Major version, This should agree with the information in RDevUsbcClient::TVer.
+*/
+const TInt KUsbcScMajorVersion = 0;
+
+/** LDD Minor version, This should agree with the information in RDevUsbcClient::TVer.
+*/
+const TInt KUsbcScMinorVersion = 1;
+
+/** LDD Build version, This should agree with the information in RDevUsbcClient::TVer.
+*/
+const TInt KUsbcScBuildVersion = KE32BuildVersionNumber;
+
+/** Must correspond to the max enum of TRequest + 1;
+    currently this is ERequestOtgFeaturesNotify = 10.
+*/
+const TInt KUsbcScMaxRequests = 11;
+
+// Request queue sizes need to be power of 2.
+
+/** The number of requests that can be queued on any IN endpoint */
+const TInt KUsbcScInRequests = 4;
+/** The number of requests that can be queued on any OUT endpoint */
+const TInt KUsbcScOutRequests = 2;
+
+/** In TUsbcScBuffer.iDirection, this indicates that the endpoint is an IN endpoint */
+const TInt KUsbcScIn =  0;
+/** In TUsbcScBuffer.iDirection, this indicates that the endpoint is an OUT endpoint */
+const TInt KUsbcScOut = 1;
+
+
+/** In TUsbcScBuffer.iDirection, this indicates that the endpoint is an Bidirectional endpoint
+currently operating as an IN endpoint */
+const TInt KUsbcScBiIn = 2;
+/** In TUsbcScBuffer.iDirection, this indicates that the endpoint is an Bidirectional endpoint
+currently operating as an OUT endpoint */
+const TInt KUsbcScBiOut = 3;
+
+/** The number of directions supported for endpoints, other then EP0.  Currently 2, IN and OUT. */
+const TInt KUsbcScDirections = 2;
+
+/** In TUsbcScBuffer::iDirection, this indicates that the endpoint direction is Unknown. */
+const TInt KUsbcScUnknown = 4;
+
+const TInt KPageSize = 0x1000;
+
+/** The default buffer size requested for a endpoint, if the user app does not specify a size.*/
+const TInt KUsbcScDefaultBufferSize = 0x10000; // 64k
+
+/** The size of the unmapped region of memory between endpoint buffers.
+This serves as a guard region, making memory over/under runs more obviose.*/
+const TInt KGuardSize = KPageSize;
+
+/** The size put aside for the chunk header structre.*/
+const TInt KHeaderSize = KPageSize;
+
+/** For buffers of size >= KUsbScBigBuffIs, The smallest unit of continiouse memory that will be used.
+No read will be set up smaller then this, to avoid overly fragmenting the data.
+*/
+const TInt KUsbSc_BigBuff_MinimumRamRun = KPageSize;
+
+/** For buffers of size < KUsbScBigBuffIs, The smallest unit of continiouse memory that will be used.
+No read will be set up smaller then this, to avoid overly fragmenting the data.*/
+const TInt KUsbSc_SmallBuff_MinimumRamRun = 1024;
+
+/** The size a buffer request has to be to switch to using KUsbSc_BigBuff_MinimumRamRun.
+If the requested buffer is smaller, then the smallest memory allocated to a buffer is KPageSize*/
+const TInt KUsbScBigBuffIs = KPageSize*6;
+
+
+
+// EP0 is mapped manually, unlike the other endpoints.
+
+/** The position, within the chunk, that the EP0 IN buffer appears*/
+const TInt KUsbScEP0InBufPos = 0x800;
+/** The position, within the chunk, that the EP0 IN buffer ends*/
+const TInt KUsbScEP0InBufEnd = KUsbScEP0InBufPos + 0x400;
+
+// Its better for Out to go 2nd, so gaurd page after it.
+/** The position, within the chunk, that the EP0 OUT buffer appears*/
+const TInt KUsbScEP0OutBufPos = 0xc00;
+/** The position, within the chunk, that the EP0 OUT buffer ends*/
+const TInt KUsbScEP0OutBufEnd = KUsbScEP0OutBufPos + 0x400;
+
+/** The number of the entry within the chunk BufferRecord table, for the OUT ep0 buffer.*/
+const TInt KUsbcScEp0OutBuff = 0;
+/** The number of the entry within the chunk BufferRecord table, for the IN ep0 buffer.*/
+const TInt KUsbcScEp0InBuff = 1;
+
+
+//
+//########################### Logical Device Driver (LDD) #############################
+//
+
+/** USB LDD factory class.
+*/
+class DUsbcScLogDevice : public DLogicalDevice
+    {
+public:
+    DUsbcScLogDevice();
+    virtual TInt Install();
+    virtual void GetCaps(TDes8& aDes) const;
+    virtual TInt Create(DLogicalChannelBase*& aChannel);
+    };
+
+
+class DLddUsbcScChannel;
+class TUsbcScBuffer;
+/** Endpoint tracking for the LDD buffering etc.
+*/
+class TUsbcScEndpoint
+    {
+public:
+    TUsbcScEndpoint(DLddUsbcScChannel* aLDD, DUsbClientController* aController,
+                  const TUsbcScEndpointInfo* aEndpointInfo, TInt aEndpointNum
+                  );
+    ~TUsbcScEndpoint();
+    TInt Construct();
+    void CancelTransfer(DThread* aThread);
+    void AbortTransfer();
+    inline TUsbcScEndpointInfo* EndpointInfo();
+    inline TInt RxBytesAvailable() const;
+    inline void ResetTransferInfo();
+    inline void SetClientReadPending(TBool aVal);
+    inline void SetClientWritePending(TBool aVal);
+    inline TBool ClientWritePending();
+    inline TBool ClientReadPending();
+    inline void SetRealEpNumber(TInt aRealEpNumber);
+    inline TInt RealEpNumber() const;
+    inline TInt EpNumber() const;
+    inline void StartBuffer();
+    inline void SetBuffer(TUsbcScBuffer* aBuffer);
+    inline TUsbcScBuffer* GetBuffer();
+
+
+private:
+    static void RequestCallback(TAny* aTUsbcScEndpoint);
+    void TxComplete();
+    TInt RxComplete(TBool aReEntrant);
+    void RxCompleteNow();
+
+
+
+public:
+    TUsbcRequestCallback* iRequestCallbackInfo;
+
+private:
+    DUsbClientController* iController;
+    TUsbcScEndpointInfo iEndpointInfo;
+    TBool iClientReadPending;
+    TBool iClientWritePending;
+    TInt iEndpointNumber;
+    TInt iRealEpNumber;
+    DLddUsbcScChannel* iLdd;
+    TInt iError;
+    TUint32 iBytesTransferred;
+    TInt iBandwidthPriority;
+    TUsbcScBuffer* iBuffer;
+
+    };
+
+
+/** Linked list of 'alternate setting' info for use by the LDD.
+*/
+class TUsbcScAlternateSetting
+    {
+public:
+    TUsbcScAlternateSetting();
+    ~TUsbcScAlternateSetting();
+
+public:
+    TUsbcScAlternateSetting* iNext;
+    TUsbcScAlternateSetting* iPrevious;
+    TInt iNumberOfEndpoints;
+    TUint iSetting;
+    TUsbcScEndpoint* iEndpoint[KMaxEndpointsPerClient + 1];
+    };
+
+class TUsbcScAlternateSettingList
+    {
+public:
+    TUsbcScAlternateSettingList();
+    ~TUsbcScAlternateSettingList();
+
+public:
+    TUsbcScAlternateSetting* iHead;
+    TUsbcScAlternateSetting* iTail;
+    };
+
+class TUsbcScChunkInfo
+    {
+public:
+    TUsbcScChunkInfo(DLogicalDevice* aLdd);
+    TInt CreateChunk(TInt aTotalSize);
+    void Close();
+    TInt ChunkAlloc(TInt aOffset, TInt aSize);
+    void ChunkCleanup();
+    TInt GetPhysical(TInt aOffset, TPhysAddr* aPhysical);
+    static TInt New(TUsbcScChunkInfo*& aChunk, TInt aSize, DLogicalDevice* aLdd);
+private:
+    TUint* iPhysicalMap;
+public:
+    DChunk* iChunk;
+    TDfc iCleanup;
+
+    TInt8 iPageNtz; // Number of trailing zeros for a page. (Eg 4k page has 12 t.z.)
+    TInt iAllocatedSize;
+    TInt8* iChunkMem;
+    TUint32 iChunkMapAttr;
+    DLogicalDevice* iLdd;
+    };
+
+
+// Used to represent a matrix of endpoints with a column of sizes.
+// Used by TRealizeInfo
+
+class TEndpointSortBufs
+    {
+    public:
+        TUsbcScEndpoint** iEp;
+        TInt* iSizes;
+        TInt iEps;
+    };
+
+// This is used to calculate the layout of the shared chunk
+// based on a list of alternative settings / endpoints provided.
+ 
+class TRealizeInfo
+    {
+    public:
+        void Init(TUsbcScAlternateSettingList* aAlternateSettingList);
+        TInt CopyAndSortEndpoints();
+        void CalcBuffSizes();
+        void Free();
+
+        void LayoutChunkHeader(TUsbcScChunkInfo* aChunkInfo);
+    public:
+        TInt iMaxEndpoints;
+        TInt iTotalSize;
+        TInt iTotalBuffers;
+        TInt iAltSettings;
+        TEndpointSortBufs iBufs[KUsbcScDirections];
+        TUsbcScAlternateSettingList* iAlternateSettingList;
+
+        // Chunk layout info.
+        TUsbcScChunkBuffersHeader* iChunkStuct;
+        TUsbcScChunkAltSettingHeader* iAltSettingsTbl;
+    };
+
+
+
+/** The channel class - the actual USB LDD.
+*/
+class DLddUsbcScChannel : public DLogicalChannel
+    {
+public:
+    DLddUsbcScChannel();
+    ~DLddUsbcScChannel();
+    virtual void HandleMsg(TMessageBase* aMsg);
+    virtual TInt DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer);
+    virtual TInt RequestUserHandle(DThread* aThread, TOwnerType aType);
+    inline DThread* Client() const {return iClient;}
+    inline TBool ChannelClosing() const {return iChannelClosing;}
+    inline TUint AlternateSetting() const {return iAlternateSetting;}
+    
+    static void RequestCallbackEp0(TAny* aTUsbcScChannel);
+
+private:
+
+    TInt DoCancel(TInt aReqNo, TUint aMask, TUint a1);
+    TInt DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2);
+    TInt DoControl(TInt aFunction, TAny* a1, TAny* a2);
+    TInt DoReadDataNotify(TRequestStatus* aStatus, TInt aBufferNum, TInt aLength);
+    void StartDataRead(TInt aBufferNum);
+    TInt DoWriteData(TRequestStatus* aStatus,TInt aBufferNum, TUint aStart, TUint aLength, TUint aFlags);
+    TBool AlternateDeviceStateTestComplete();
+    TInt SetInterface(TInt aInterfaceNum, TUsbcScIfcInfo* aUserInterfaceInfoBuf);
+    void StartEpReads();
+    void DestroyAllInterfaces();
+    void DestroyInterface(TUint aInterface);
+    void DestroyEp0();
+    inline TBool ValidEndpoint(TInt aEndpoint);
+    TInt GetRealEpForEpResource(TInt aEndpoint, TInt& aRealEp);
+    inline TBool Configured();
+    TInt DoEmergencyComplete();
+    void ReadDes8(const TAny* aPtr, TDes8& aDes);
+    TInt SetupEp0();
+    void CancelNotifyEndpointStatus();
+    void CancelNotifyOtgFeatures();
+    static void StatusChangeCallback(TAny* aDLddUsbcChannel);
+    static void EndpointStatusChangeCallback(TAny* aDLddUsbcChannel);
+    static void OtgFeatureChangeCallback(TAny* aDLddUsbcChannel);
+    static void EmergencyCompleteDfc(TAny* aDLddUsbcChannel);
+    void DeConfigure(TInt aErrorCode);
+    TInt SelectAlternateSetting(TUint aAlternateSetting);
+    TInt EpFromAlternateSetting(TUint aAlternateSetting, TInt aEndpoint);
+    TInt ProcessAlternateSetting(TUint aAlternateSetting);
+    TInt32 StartNextInAlternateSetting();
+    TInt ProcessDeviceState(TUsbcDeviceState aDeviceState);
+    void ResetInterface(TInt aErrorCode);
+    void PanicClientThread(TInt aReason);
+
+    TInt RealizeInterface(void);
+
+private:
+    DUsbClientController* iController;
+    DThread* iClient;
+    TBool iValidInterface;
+    
+    TUsbcScAlternateSettingList* iAlternateSettingList;
+    TUsbcScEndpoint** iEndpoint;  // Pointer to the current endpoint set.
+
+    static const TInt KUsbcMaxRequests = RDevUsbcScClient::ERequestMaxRequests;
+    TRequestStatus* iRequestStatus[KUsbcMaxRequests];
+    TUsbcClientCallback iCompleteAllCallbackInfo;
+    TAny* iStatusChangePtr;
+    TUsbcStatusCallback iStatusCallbackInfo;
+    TAny* iEndpointStatusChangePtr;
+    TUsbcEndpointStatusCallback iEndpointStatusCallbackInfo;
+    TAny* iOtgFeatureChangePtr;
+    TUsbcOtgFeatureCallback iOtgFeatureCallbackInfo;
+    TUint8* iBufferBaseEp0;
+    TInt iBufferSizeEp0;
+    TInt iNumberOfEndpoints;
+    TUsbcDeviceState iDeviceState;
+    TUsbcDeviceState iOldDeviceState;
+    TBool iOwnsDeviceControl;
+    TUint16 iAlternateSetting;
+    TUint16 iAsSeq;
+
+    TUsbcDeviceStatusQueue* iStatusFifo;
+    TBool iUserKnowsAltSetting;
+    TBool iDeviceStatusNeeded;
+    TBool iChannelClosing;
+    TBool iRealizeCalled;
+
+    TUsbcScChunkInfo* iChunkInfo;
+    TInt iNumBuffers;
+    TUsbcScBuffer *iBuffers;
+
+    TUsbcScEndpoint* iEp0Endpoint;
+    TInt iEP0InBuff;
+    TInt iEP0OutBuff;
+
+    friend class TUsbcScBuffer;
+    friend void TUsbcScEndpoint::AbortTransfer();
+    };
+
+/**
+This class is used by TUsbcScStatusList to form a queue of status requests.
+These requests are on a buffer basis, so that all buffers can have at least two requests
+pending, at the same time. (i.e. buffer 1 could have two requests outstanding, as well as 2 on buffer 2.)
+*/
+
+class TUsbcScStatusElement
+{
+public:
+    TRequestStatus* iStatus;
+    TInt iLength;
+    TUint iStart;
+    TUint iFlags;    
+};
+
+enum TUsbcScStatusState
+{
+    ENotRunning,
+    EInProgress,
+    EReadingAhead,
+    EFramgementInProgress
+};
+
+class TUsbcScStatusList
+{
+public:
+    TInt Construct(TInt aSize, DThread* aThread);
+    void Destroy();
+
+    TUsbcScStatusElement* Next();
+    void Pop();
+    TInt Add(TRequestStatus* aStatus, TInt aLength, TUint aStart, TUint aFlags);
+    void CancelQueued(TInt aErrorCode=KErrCancel);
+    TInt Complete(TInt aError);
+    void Complete();
+public:
+    TUsbcScStatusState iState;
+
+private:
+    DThread* iClient;
+    TInt iHead;   // The element at the head of the queue, ie, the earliest added, and next to be removed.
+    TInt iLength; // Length of queue, ie number of elements within
+    TInt iSize;   // size of array, ie, max # of requests at a time.
+    TUsbcScStatusElement* iElements;
+
+};
+
+
+
+/**
+This class holds the kernel's copy of all the details related to a shared endpoint buffer,
+and provides methods for the LDD to manipulate it.
+*/
+class TUsbcScBuffer
+{
+public:
+    static const TInt8 KNoEpAssigned=0;
+    static const TInt8 KEpIsEnding=1;
+    static const TInt8 KEpIsStarting=2;
+
+public:
+    TInt Construct(TInt aDirection, DLddUsbcScChannel* aLdd, TInt aBufferOffset, TInt aBufferEndOffset, TInt aMinReadSize, TInt aMaxPacketSize, TInt aMaxReadSize);
+    void CreateChunkBufferHeader();
+    void StartEndpoint(TUsbcRequestCallback* iRequestInfo, TUint iFlags);
+
+    void Destroy();
+
+    TInt StartDataRead();
+    void CompleteRead(TBool aStartNextRead=ETrue);
+    void PopStall();
+    void StartDataWrite();
+    void CompleteWrite();
+    void Cancel(TInt aErrorCode);
+
+    void UpdateBufferList(TInt aByteCount,TUint aFlags, TBool aStartNextRead=ETrue);
+    void Ep0CancelLddRead();
+    void SendEp0StatusPacket(TInt aState);
+
+public:
+    
+    TInt8 iDirection;
+    TInt8 iMode;
+    TInt8 iNeedsPacket;
+    TInt8 iReserved;
+    DLddUsbcScChannel* iLdd;
+    TLinAddr iChunkAddr;
+    SUsbcScBufferHeader* iBufferStart;
+    TUint iBufferEnd; // One word on from the last word in the buffer.
+    TUint iAlignMask;
+    TUsbcScStatusList iStatusList;
+    TUsbcRequestCallback* iCallback;
+    union 
+    {
+        TInt iHead; // Out endpoints only;
+        TUint iSent; // In endpoints only
+    };
+    TUsbcScChunkInfo* iChunkInfo;
+    TInt iMinReadSize;
+    TInt iMaxReadSize;
+    TInt iMaxPacketSize;  // 0 indicates unconfiured.
+    TInt iFirstPacket;
+    TInt iStalled;
+
+    // needed for backwards compatibility
+    TUsbcPacketArray iIndexArray[KUsbcDmaBufNumMax]; // Has 2 elements
+    TUsbcPacketArray iSizeArray[KUsbcDmaBufNumMax];  // Has 2 elements
+#ifdef _DEBUG
+    TUint iSequence;
+#endif
+
+};
+
+
+
+#include <usb/usbcsc.inl>
+
+#endif    // __USBCSC_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/public/usbcsc.inl	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,107 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\include\drivers\usbcsc.inl
+// Kernel side inline header file for USB device driver.
+// 
+//
+
+/**
+ @file usbcsc.inl
+ @internalTechnology
+*/
+
+#ifndef __USBCSC_INL__
+#define __USBCSC_INL__
+ 
+
+//
+// --- USB Logical Device Driver (LDD) ---
+//
+
+TUsbcScEndpointInfo* TUsbcScEndpoint::EndpointInfo()
+	{
+	return &iEndpointInfo;
+	}
+
+
+void TUsbcScEndpoint::SetClientReadPending(TBool aVal)
+	{
+	iClientReadPending = aVal;
+	}
+
+
+TBool TUsbcScEndpoint::ClientReadPending()
+	{
+	return iClientReadPending;
+	}
+
+
+void TUsbcScEndpoint::SetClientWritePending(TBool aVal)
+	{
+	iClientWritePending = aVal;
+	}
+
+
+TBool TUsbcScEndpoint::ClientWritePending()
+	{
+	return iClientWritePending;
+	}
+
+
+void TUsbcScEndpoint::SetRealEpNumber(TInt aRealEpNumber)
+	{
+	iRealEpNumber = aRealEpNumber;
+	iRequestCallbackInfo->iRealEpNum = aRealEpNumber;
+	}
+
+
+TInt TUsbcScEndpoint::RealEpNumber() const
+	{
+	return iRealEpNumber;
+	}
+TInt TUsbcScEndpoint::EpNumber() const
+	{
+	return iEndpointNumber;
+	}
+void TUsbcScEndpoint::StartBuffer()
+	{
+	iBuffer->StartEndpoint(iRequestCallbackInfo, iEndpointInfo.iFlags);
+	}
+
+void TUsbcScEndpoint::SetBuffer(TUsbcScBuffer* aBuffer)
+	{
+		__ASSERT_ALWAYS(iBuffer==NULL, Kern::Fault("TUsbcScEndpoint::SetBuffer", __LINE__));
+		iBuffer = aBuffer;
+	}
+
+TUsbcScBuffer* TUsbcScEndpoint::GetBuffer()
+	{
+		__ASSERT_DEBUG(iBuffer!=NULL, Kern::Fault("TUsbcScEndpoint::GetBuffer", __LINE__));
+	return iBuffer;
+	}
+
+inline TBool DLddUsbcScChannel::ValidEndpoint(TInt aEndpoint)
+	{
+	return (aEndpoint <= iNumberOfEndpoints && aEndpoint >= 0);
+	}
+
+inline TBool DLddUsbcScChannel::Configured()
+	{
+	if (iValidInterface && 
+		(iDeviceState == UsbShai::EUsbPeripheralStateConfigured || iDeviceState == UsbShai::EUsbPeripheralStateSuspended))
+		return ETrue;
+	return EFalse;
+	}
+
+#endif // __USBCSC_INL__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/public/usbcshared.h	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,997 @@
+// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\include\drivers\usbcshared.h
+// Kernel side definitions for the USB Device driver stack (PIL + LDD).
+// 
+//
+
+/**
+ @file usbcshared.h
+ @internalTechnology
+*/
+
+#ifndef __USBCSHARED_H__
+#define __USBCSHARED_H__
+
+//#include <drivers/usbcque.h>
+#include <usb/usbcque.h>
+
+// Define here what options are required:
+// (USB_SUPPORTS_CONTROLENDPOINTS and USB_SUPPORTS_SET_DESCRIPTOR_REQUEST
+//  have never been tested though...)
+//#define USB_SUPPORTS_CONTROLENDPOINTS
+//#define USB_SUPPORTS_SET_DESCRIPTOR_REQUEST
+
+//#include <drivers/usbcdesc.h>
+#include <usb/usbcdesc.h>
+//#include <drivers/usbotgperipheralcontrolif.h>
+#include <usb/usbotgperipheralcontrolif.h>
+
+#include <usb/usb_peripheral_shai.h>
+#include <usb/usb_charger_detection_shai.h>
+
+#include <usb/usbcontrolxferif.h>
+
+// FIXME: Remove this typedef once PIL and LDD are ready for SHAI
+typedef UsbShai::TUsbPeripheralEvent TUsbcDeviceEvent;
+typedef UsbShai::TUsbPeripheralPacketArray TUsbcPacketArray;
+
+// Forward declaration
+class DControlTransferManager;
+class TUsbcSetup;
+
+// Debug Support
+
+// Use for debugging purposes only (commented out for normal operation):
+//#define USBC_LDD_BUFFER_TRACE
+
+static const char KUsbPILPanicCat[] = "USB PIL FAULT"; // kernel fault category
+_LIT(KUsbPILKillCat, "USB PIL KILL");                    // thread kill category
+_LIT(KUsbLDDKillCat, "USB LDD KILL");                    // thread kill category
+
+/** Error code for stalled endpoint.
+*/
+const TInt KErrEndpointStall = KErrLocked;
+
+/** Error code for Ep0 write prematurely ended by a host OUT token.
+*/
+const TInt KErrPrematureEnd = KErrDiskFull;
+
+/** The following constants control the buffer arrangement for OUT transfers (IN transfers have only 1
+    buffer). The total size of buffering for an OUT endpoint will be number of buffers * buffersize,
+    so that, for example, a Bulk OUT endpoint will have KUsbcDmaBufNumBulk * KUsbcDmaBufSzBulk bytes of
+    buffering.
+    These buffers will be physically contiguous, so that DMA may be used.
+    The number of buffers MUST be >=2 - otherwise the buffering scheme won't work.
+    The buffer sizes should be an exact fraction of 4kB and the number of buffers such that the
+    buffersize * number of buffers is an exact multiple of 4kB, otherwise memory will be wasted.
+*/
+/** Size of a Control ep buffer.
+*/
+const TInt KUsbcDmaBufSzControl = 1024;
+
+/** Size of a Bulk ep buffer.
+*/
+const TInt KUsbcDmaBufSzBulk = 4096;
+
+/** Size of an Interrupt ep buffer.
+*/
+const TInt KUsbcDmaBufSzInterrupt = 4096;
+
+/** Size of an Isochronous ep buffer.
+*/
+const TInt KUsbcDmaBufSzIsochronous = 4096;
+
+/** Number of buffers for Control OUT endpoints.
+*/
+const TInt KUsbcDmaBufNumControl = 2;
+
+/** Number of buffers for Isochronous OUT endpoints.
+*/
+const TInt KUsbcDmaBufNumIsochronous = 2;
+
+/** Number of buffers for Bulk OUT endpoints.
+*/
+const TInt KUsbcDmaBufNumBulk = 2;
+
+/** Number of buffers for Interrupt OUT endpoints.
+*/
+const TInt KUsbcDmaBufNumInterrupt = 2;
+
+/** Maximum buffer number.
+*/
+const TInt KUsbcDmaBufNumMax = MAX4(KUsbcDmaBufNumControl, KUsbcDmaBufNumIsochronous,
+                                    KUsbcDmaBufNumBulk, KUsbcDmaBufNumInterrupt);
+
+/** Maximum number of recorded packets possible.
+*/
+const TUint KUsbcDmaBufMaxPkts = 2;
+
+/** Number of arrays.
+*/
+const TInt KUsbcDmaBufNumArrays = 2;
+
+/** Max size that Ep0 packets might have.
+*/
+const TInt KUsbcBufSzControl = 64;
+
+/** The Ep0 RX data collection buffer area.
+    (Arbitrary size, judged to be sufficient for SET_DESCRIPTOR requests)
+*/
+const TInt KUsbcBufSz_Ep0Rx = 1024;
+
+/** The Ep0 TX buffer area.
+    (Size sufficient to hold as much data as can be requested via GET_DESCRIPTOR)
+*/
+const TInt KUsbcBufSz_Ep0Tx = 1024 * 64; 
+
+
+/** The USB version the stack is compliant with: 2.0 (BCD).
+*/
+const TUint16 KUsbcUsbVersion = 0x0200;
+
+/** Maximum number of endpoints an interface (i.e. LDD) may have.
+*/
+const TInt KUsbcMaxEpNumber = 5;
+
+/** Status FIFO depth; enough for 2 complete configs.
+*/
+const TInt KUsbDeviceStatusQueueDepth = 15;
+
+/** = 'no status info'.
+*/
+const TUint32 KUsbDeviceStatusNull = 0xffffffffu;
+
+/** = 'no buffer available'.
+*/
+const TInt KUsbcInvalidBufferIndex = -1;
+
+/** = 'no packet available'.
+*/
+const TUint KUsbcInvalidPacketIndex = (TUint)(-1);
+
+/** = 'no drainable buffers'.
+*/
+const TInt KUsbcInvalidDrainQueueIndex = -1;
+
+/** Number of possible bandwidth priorities.
+*/
+const TInt KUsbcDmaBufMaxPriorities = 4;
+
+// The following buffer sizes are used within the LDD for the different
+// user-selectable endpoint bandwidth priorities
+// (EUsbcBandwidthOUTDefault/Plus1/Plus2/Maximum + the same for 'IN').
+// These values, in particular those for the Maximum setting, were obtained
+// empirically.
+
+/** Bulk IN buffer sizes for different priorities (4K, 16K, 64K, 512K).
+*/
+const TInt KUsbcDmaBufSizesBulkIN[KUsbcDmaBufMaxPriorities] =
+    {KUsbcDmaBufSzBulk, 0x4000, 0x10000, 0x80000};
+
+/** Bulk OUT buffer sizes for different priorities (4K, 16K, 64K, 512K).
+*/
+const TInt KUsbcDmaBufSizesBulkOUT[KUsbcDmaBufMaxPriorities] =
+    {KUsbcDmaBufSzBulk, 0x4000, 0x10000, 0x80000};
+
+/** Number of UDCs supported in the system.
+    (Support for more than one UDC is preliminary.)
+*/
+const TInt KUsbcMaxUdcs = 2;
+
+/** Number of endpoints a USB device can have.
+    (30 regular endpoints + 2 x Ep0)
+*/
+const TInt KUsbcEpArraySize = KUsbcMaxEndpoints + 2;
+
+/** Number of notification requests of the same kind that can be registered at
+    a time. As normally not more than one request per kind per LDD is
+    permitted, this number is roughly equivalent to the maximum number of LDDs
+    that can be operating at the same time.
+    This constant is used by the PIL while maintaining its request lists
+    (iClientCallbacks, iStatusCallbacks, iEpStatusCallbacks, iOtgCallbacks) to
+    ensure that the lists are of a finite length and thus the list traverse
+    time is bounded.
+    This value is chosen with the maximum number of USB interfaces (not
+    settings) allowed by the spec for a single device in mind.
+*/
+const TInt KUsbcMaxListLength = 256;
+
+/**
+ * device event FIFO depth, there are 5 different event define currently,
+ * 10 should be enough
+ */
+const TInt KUsbDeviceEventQueueDepth = 10;
+
+/** USB LDD client callback.
+*/
+class TUsbcClientCallback
+    {
+public:
+    inline TUsbcClientCallback(DBase* aOwner, TDfcFn aCallback, TInt aPriority);
+    inline DBase* Owner() const;
+    inline TInt DoCallback();
+    inline void Cancel();
+    inline void SetDfcQ(TDfcQue* aDfcQ);
+public:
+    /** Used by the PIL to queue callback objects into a TSglQue. */
+    TSglQueLink iLink;
+private:
+    DBase* iOwner;
+    TDfc iDfc;
+    };
+
+
+/** The endpoint halt/clear_halt status.
+*/
+class TUsbcEndpointStatusCallback
+    {
+public:
+    inline TUsbcEndpointStatusCallback(DBase* aOwner, TDfcFn aCallback, TInt aPriority);
+    inline void SetState(TUint aState);
+    inline TUint State() const;
+    inline DBase* Owner() const;
+    inline TInt DoCallback();
+    inline void Cancel();
+    inline void SetDfcQ(TDfcQue* aDfcQ);
+public:
+    /** Used by the PIL to queue callback objects into a TSglQue. */
+    TSglQueLink iLink;
+private:
+    DBase* iOwner;
+    TDfc iDfc;
+    TUint iState;
+    };
+
+
+/** Maximum number of device status requests that can be queued at a time.
+    The value chosen is thought to be sufficient in all situations.
+*/
+const TInt KUsbcDeviceStateRequests = 8;
+
+        
+/** The USB device status.
+*/
+class TUsbcStatusCallback
+    {
+public:
+    inline TUsbcStatusCallback(DBase* aOwner, TDfcFn aCallback, TInt aPriority);
+    inline void SetState(UsbShai::TUsbPeripheralState aState);
+    inline UsbShai::TUsbPeripheralState State(TInt aIndex) const;
+    inline void ResetState();
+    inline DBase* Owner() const;
+    inline TInt DoCallback();
+    inline void Cancel();
+    inline void SetDfcQ(TDfcQue* aDfcQ);
+public:
+    /** Used by the PIL to queue callback objects into a TSglQue. */
+    TSglQueLink iLink;
+private:
+    DBase* iOwner;
+    TDfc iDfc;
+    UsbShai::TUsbPeripheralState iState[KUsbcDeviceStateRequests];
+    };
+
+
+/** A USB transfer request.
+
+    @publishedPartner
+    @released
+*/
+class TUsbcRequestCallback : public UsbShai::TUsbPeripheralRequest
+    {
+public:
+    /** @internalTechnology */
+    inline TUsbcRequestCallback(const DBase* aOwner, TInt aEndpointNum, TDfcFn aDfcFunc,
+                         TAny* aEndpoint, TDfcQue* aDfcQ, TInt aPriority);
+    /** @internalTechnology    */
+    inline ~TUsbcRequestCallback();
+    
+    IMPORT_C void SetRxBufferInfo(TUint8* aBufferStart,
+                                      TUintPtr aBufferAddr,
+                                      TUint32* aPacketIndex,
+                                      TUint32* aPacketSize, 
+                                      TInt aLength);
+                                    
+    IMPORT_C void SetTxBufferInfo(TUint8* aBufferStart, 
+                                      TUintPtr aBufferAddr,
+                                      TInt aLength);
+                                        
+    /** @internalTechnology    */
+    inline void SetTransferDirection(UsbShai::TTransferDirection aTransferDir);
+    /** @internalTechnology    */
+    inline const DBase* Owner() const;
+    /** @internalTechnology    */
+    inline TInt DoCallback();
+    /** @internalTechnology    */
+    inline void Cancel();
+public:
+    /** Used by the PIL to queue callback objects into a TSglQue.
+        @internalTechnology
+    */
+    TSglQueLink iLink;
+public:
+    /** The endpoint number. */
+    const TInt iEndpointNum;
+
+    /** Indicates the LDD client for this transfer. */
+    const DBase* const iOwner;
+    /** DFC, used by PIL to call back the LDD when transfer completes to the LDD. */
+    TDfc iDfc;
+    };
+
+/** USB On-The-Go feature change callback.
+*/
+class TUsbcOtgFeatureCallback
+    {
+public:
+    inline TUsbcOtgFeatureCallback(DBase* aOwner, TDfcFn aCallback, TInt aPriority);
+    inline void SetFeatures(TUint8 aFeatures);
+    inline TUint8 Features() const;
+    inline DBase* Owner() const;
+    inline TInt DoCallback();
+    inline void Cancel();
+    inline void SetDfcQ(TDfcQue* aDfcQ);
+public:
+    /** Used by the PIL to queue callback objects into a TSglQue. */
+    TSglQueLink iLink;
+private:
+    DBase* iOwner;
+    TDfc iDfc;
+    TUint8 iValue;
+    };
+
+//
+//########################### Physical Device Driver (PIL + PSL) ######################
+//
+
+class TUsbcLogicalEndpoint;
+
+/** This models a physical (real) endpoint of the UDC.
+*/
+class TUsbcPhysicalEndpoint
+    {
+public:
+    TUsbcPhysicalEndpoint();
+    ~TUsbcPhysicalEndpoint();
+    TBool EndpointSuitable(const TUsbcEndpointInfo* aEpInfo, TInt aIfcNumber) const; // Check Todo, SC will pass pointer to derived class
+    TInt TypeAvailable(TUint aType) const;
+    TInt DirAvailable(TUint aDir) const;
+public:
+    /** This endpoint's capabilities. */
+    UsbShai::TUsbPeripheralEndpointCaps iCaps;
+    /** USB address: 0x00, 0x80, 0x01, 0x81, etc. */
+    TUint8 iEndpointAddr;
+    /** Pointer to interface # this endpoint has been assigned to. */
+    const TUint8* iIfcNumber;
+    /** Pointer to corresponding logical endpoint or NULL. */
+    const TUsbcLogicalEndpoint* iLEndpoint;
+    /** Only used when searching for available endpoints. */
+    TBool iSettingReserve;
+    /** True if endpoint is halted (i.e. issues STALL handshakes), false otherwise. */
+    TBool iHalt;
+    };
+
+
+class DUsbClientController;
+class TUsbcInterface;
+
+/** This is a 'logical' endpoint, as used by our device configuration model.
+*/
+class TUsbcLogicalEndpoint
+    {
+public:
+    TUsbcLogicalEndpoint(DUsbClientController* aController, TUint aEndpointNum,
+                         const TUsbcEndpointInfo& aEpInfo, TUsbcInterface* aInterface,
+                         TUsbcPhysicalEndpoint* aPEndpoint);        // Check Todo, SC will pass pointer to derived class
+    ~TUsbcLogicalEndpoint();
+public:
+    /** Pointer to controller object. */
+    DUsbClientController* iController;
+    /** The virtual (logical) endpoint number. */
+    const TInt iLEndpointNum;
+    /** This endpoint's info structure. */
+    TUsbcEndpointInfo iInfo;                                        // Check Todo, SC will pass pointer to derived class
+    /** Stores the endpoint size to be used for FS. */
+    TInt iEpSize_Fs;
+    /** Stores the endpoint size to be used for HS. */
+    TInt iEpSize_Hs;
+    /** 'Back' pointer. */
+    const TUsbcInterface* iInterface;
+    /** Pointer to corresponding physical endpoint, never NULL. */
+    TUsbcPhysicalEndpoint* const iPEndpoint;
+    };
+
+
+class TUsbcInterfaceSet;
+
+/** This is an 'alternate setting' of an interface.
+*/
+class TUsbcInterface
+    {
+public:
+    TUsbcInterface(TUsbcInterfaceSet* aIfcSet, TUint8 aSetting, TBool aNoEp0Requests);
+    ~TUsbcInterface();
+public:
+    /** Array of endpoints making up (belonging to) this setting. */
+    RPointerArray<TUsbcLogicalEndpoint> iEndpoints;
+    /** 'Back' pointer. */
+    TUsbcInterfaceSet* const iInterfaceSet;
+    /** bAlternateSetting (zero-based). */
+    const TUint8 iSettingCode;
+    /** KUsbcInterfaceInfo_NoEp0RequestsPlease: stall non-std Setup requests. */
+    const TBool iNoEp0Requests;
+    };
+
+
+/** This is an 'interface' (owning 1 or more alternate settings).
+
+    @see TUsbcInterface
+*/
+class TUsbcInterfaceSet
+    {
+public:
+    TUsbcInterfaceSet(const DBase* aClientId, TUint8 aIfcNum);
+    ~TUsbcInterfaceSet();
+    inline const TUsbcInterface* CurrentInterface() const;
+    inline TUsbcInterface* CurrentInterface();
+public:
+    /** Array of alternate settings provided by (belonging to) this interface. */
+    RPointerArray<TUsbcInterface> iInterfaces;
+    /** Pointer to the LDD which created and owns this interface. */
+    const DBase* const iClientId;
+    /** bInterfaceNumber (zero-based). */
+    TUint8 iInterfaceNumber;
+    /** bAlternateSetting (zero-based). */
+    TUint8 iCurrentInterface;
+    };
+
+
+/** This is a 'configuration' of the USB device.
+    Currently we support only one configuration.
+*/
+class TUsbcConfiguration
+    {
+public:
+    TUsbcConfiguration(TUint8 aConfigVal);
+    ~TUsbcConfiguration();
+public:
+    /** Array of interfaces making up (belonging to) this configuration. */
+    RPointerArray<TUsbcInterfaceSet> iInterfaceSets;
+    /** bConfigurationValue (one-based). */
+    const TUint8 iConfigValue;
+    };
+
+
+/** The USB controller's power handler class.
+*/
+NONSHARABLE_CLASS(DUsbcPowerHandler) : public DPowerHandler
+    {
+public:
+    void PowerUp();
+    void PowerDown(TPowerState);
+public:
+    DUsbcPowerHandler(DUsbClientController* aController);
+private:
+    DUsbClientController* iController;
+    };
+
+
+/*
+This is the EndpointInfo class used by the usb shared chunk client driver. 
+*/
+
+class TUsbcScEndpointInfo;
+
+
+/**
+Used to represent an array of (or inheriting from) TUsbcEndpointInfo objects.
+
+@see DUsbClientController::SetInterface
+*/
+
+class TUsbcEndpointInfoArray
+    {
+public:
+    typedef enum {EUsbcEndpointInfo, EUsbcScEndpointInfo} TArrayType;
+
+    TUsbcEndpointInfoArray(const TUsbcEndpointInfo* aData, TInt aDataSize=0);
+    TUsbcEndpointInfoArray(const TUsbcScEndpointInfo* aData, TInt aDataSize=0);
+    inline TUsbcEndpointInfo& operator[](TInt aIndex) const; 
+
+    TArrayType iType;
+private:
+    TUint8* iData;
+    TInt iDataSize;
+    };
+
+class TUsbPeriDeviceEventQueue
+    {
+public:
+    TUsbPeriDeviceEventQueue();
+    
+    void FifoAdd(TUsbcDeviceEvent aDeviceStatus);
+    TUsbcDeviceEvent FifoGet();
+
+private:
+    TUsbcDeviceEvent iDeviceEventQueue[KUsbDeviceEventQueueDepth];
+    TInt iDeviceQueueHead;
+    TInt iDeviceQueueTail;
+    };
+    
+class TUsbcRequestCallback; // todo?? required only for class below
+
+/** The USB Device software controller class.
+
+    Implements the platform-independent layer (PIL), and defines the interface to the
+    platform-specific layer PSL).
+
+    The implementation of the platform-specific layer interfaces with the hardware.
+*/
+NONSHARABLE_CLASS(DUsbClientController) : public DBase, 
+                                          public MUsbOtgPeripheralControlIf,
+                                          public UsbShai::MUsbPeripheralPilCallbackIf, 
+                                          public MControlTransferIf, 
+                                          public UsbShai::MChargerDetectorObserverIf
+    {   
+    friend class UsbShai::UsbPeripheralPil;
+    friend class TUsbHostWrapperEntry;
+    friend class DUsbcPowerHandler;
+    friend TUsbcLogicalEndpoint::~TUsbcLogicalEndpoint();
+    //
+    // --- Platform Independent Layer (PIL) ---
+    //
+
+
+private:
+    /**
+     * Two-phase constructor used by the friend classes that receive
+     * the registration calls for peripheral controllers.
+     *
+     * @param aPeripheralControllerIf Reference to the Peripheral
+     *   Controller interface implemented by the registering PSL.
+     *
+     * @param aProperties Reference to an object describing the
+     *   static properties of the Peripheral Controller. The PIL
+     *   layer requires that the supplied reference remains valid
+     *   indefinitely, as a Peripheral Controller cannot unregister.
+     *
+     * @param aIsOtgPort ETrue if this Peripheral Controller is part
+     *   of an OTG port. EFalse otherwise.
+     *
+     * @return Pointer to a new instance or NULL if failed
+     */
+    IMPORT_C static DUsbClientController* Create(UsbShai::MPeripheralControllerIf& aPeripheralControllerIf, 
+                                                 const UsbShai::TPeripheralControllerProperties& aProperties,
+                                                 TBool aIsOtgPort);
+    
+
+public:
+
+    //
+    // --- The following functions constitute the PIL interface to the LDD ---
+    //
+    virtual ~DUsbClientController();
+    IMPORT_C void DisableClientStack();
+    IMPORT_C void EnableClientStack();
+    IMPORT_C TBool IsActive();
+    IMPORT_C TInt RegisterClientCallback(TUsbcClientCallback& aCallback);
+    IMPORT_C static DUsbClientController* UsbcControllerPointer(TInt aUdc=0);
+    IMPORT_C void EndpointCaps(const DBase* aClientId, TDes8 &aCapsBuf) const;
+    IMPORT_C void DeviceCaps(const DBase* aClientId, TDes8 &aCapsBuf) const;
+    IMPORT_C TInt SetInterface(const DBase* aClientId, DThread* aThread, TInt aInterfaceNum,
+                               TUsbcClassInfo& aClass, TDesC8* aString, TInt aTotalEndpointsUsed,
+                               const TUsbcEndpointInfo aEndpointData[], TInt (*aRealEpNumbers)[6],
+                               TUint32 aFeatureWord);
+    IMPORT_C TInt SetInterface(const DBase* aClientId, DThread* aThread,
+                                                 TInt aInterfaceNum, TUsbcClassInfo& aClass,
+                                                 TDesC8* aString, TInt aTotalEndpointsUsed,
+                                                 const TUsbcEndpointInfoArray aEndpointData,
+                                                 TInt aRealEpNumbers[], TUint32 aFeatureWord);
+    IMPORT_C TInt ReleaseInterface(const DBase* aClientId, TInt aInterfaceNum);
+    IMPORT_C TInt ReEnumerate();
+    IMPORT_C TInt PowerUpUdc();
+    IMPORT_C TInt UsbConnect();
+    IMPORT_C TInt UsbDisconnect();
+    IMPORT_C TInt RegisterForStatusChange(TUsbcStatusCallback& aCallback);
+    IMPORT_C TInt DeRegisterForStatusChange(const DBase* aClientId);
+    IMPORT_C TInt RegisterForEndpointStatusChange(TUsbcEndpointStatusCallback& aCallback);
+    IMPORT_C TInt DeRegisterForEndpointStatusChange(const DBase* aClientId);
+    IMPORT_C TInt GetInterfaceNumber(const DBase* aClientId, TInt& aInterfaceNum) const;
+    IMPORT_C TInt DeRegisterClient(const DBase* aClientId);
+    IMPORT_C TInt Ep0PacketSize() const;
+    IMPORT_C TInt Ep0Stall(const DBase* aClientId);
+    IMPORT_C void SendEp0StatusPacket(const DBase* aClientId);
+    IMPORT_C UsbShai::TUsbPeripheralState GetDeviceStatus() const;
+    IMPORT_C TEndpointState GetEndpointStatus(const DBase* aClientId, TInt aEndpointNum) const;
+    IMPORT_C TInt SetupReadBuffer(TUsbcRequestCallback& aCallback);
+    IMPORT_C TInt SetupWriteBuffer(TUsbcRequestCallback& aCallback);
+    IMPORT_C void CancelReadBuffer(const DBase* aClientId, TInt aRealEndpoint);
+    IMPORT_C void CancelWriteBuffer(const DBase* aClientId, TInt aRealEndpoint);
+    IMPORT_C TInt HaltEndpoint(const DBase* aClientId, TInt aEndpointNum);
+    IMPORT_C TInt ClearHaltEndpoint(const DBase* aClientId, TInt aEndpointNum);
+    IMPORT_C TInt SetDeviceControl(const DBase* aClientId);
+    IMPORT_C TInt ReleaseDeviceControl(const DBase* aClientId);
+    IMPORT_C TUint EndpointZeroMaxPacketSizes() const;
+    IMPORT_C TInt SetEndpointZeroMaxPacketSize(TInt aMaxPacketSize);
+    IMPORT_C TInt GetDeviceDescriptor(DThread* aThread, TDes8& aDeviceDescriptor);
+    IMPORT_C TInt SetDeviceDescriptor(DThread* aThread, const TDes8& aDeviceDescriptor);
+    IMPORT_C TInt GetDeviceDescriptorSize(DThread* aThread, TDes8& aSize);
+    IMPORT_C TInt GetConfigurationDescriptor(DThread* aThread, TDes8& aConfigurationDescriptor);
+    IMPORT_C TInt SetConfigurationDescriptor(DThread* aThread, const TDes8& aConfigurationDescriptor);
+    IMPORT_C TInt GetConfigurationDescriptorSize(DThread* aThread, TDes8& aSize);
+    IMPORT_C TInt SetOtgDescriptor(DThread* aThread, const TDesC8& aOtgDesc);
+    IMPORT_C TInt GetOtgDescriptor(DThread* aThread, TDes8& aOtgDesc) const;
+    IMPORT_C TInt GetOtgFeatures(DThread* aThread, TDes8& aFeatures) const;
+    IMPORT_C TInt GetCurrentOtgFeatures(TUint8& aFeatures) const;
+    IMPORT_C TInt RegisterForOtgFeatureChange(TUsbcOtgFeatureCallback& aCallback);
+    IMPORT_C TInt DeRegisterForOtgFeatureChange(const DBase* aClientId);
+    IMPORT_C TInt GetInterfaceDescriptor(DThread* aThread, const DBase* aClientId, TInt aSettingNum,
+                                         TDes8& aInterfaceDescriptor);
+    IMPORT_C TInt SetInterfaceDescriptor(DThread* aThread, const DBase* aClientId, TInt aSettingNum,
+                                         const TDes8& aInterfaceDescriptor);
+    IMPORT_C TInt GetInterfaceDescriptorSize(DThread* aThread, const DBase* aClientId, TInt aSettingNum,
+                                             TDes8& aSize);
+    IMPORT_C TInt GetEndpointDescriptor(DThread* aThread, const DBase* aClientId, TInt aSettingNum,
+                                        TInt aEndpointNum, TDes8& aEndpointDescriptor);
+    IMPORT_C TInt SetEndpointDescriptor(DThread* aThread, const DBase* aClientId, TInt aSettingNum,
+                                        TInt aEndpointNum, const TDes8& aEndpointDescriptor);
+    IMPORT_C TInt GetEndpointDescriptorSize(DThread* aThread, const DBase* aClientId, TInt aSettingNum,
+                                            TInt aEndpointNum, TDes8& aSize);
+    IMPORT_C TInt GetDeviceQualifierDescriptor(DThread* aThread, TDes8& aDeviceQualifierDescriptor);
+    IMPORT_C TInt SetDeviceQualifierDescriptor(DThread* aThread, const TDes8& aDeviceQualifierDescriptor);
+    IMPORT_C TInt GetOtherSpeedConfigurationDescriptor(DThread* aThread, TDes8& aConfigurationDescriptor);
+    IMPORT_C TInt SetOtherSpeedConfigurationDescriptor(DThread* aThread, const TDes8& aConfigurationDescriptor);
+    IMPORT_C TInt GetCSInterfaceDescriptorBlock(DThread* aThread, const DBase* aClientId, TInt aSettingNum,
+                                                TDes8& aInterfaceDescriptor);
+    IMPORT_C TInt SetCSInterfaceDescriptorBlock(DThread* aThread, const DBase* aClientId, TInt aSettingNum,
+                                                const TDes8& aInterfaceDescriptor, TInt aSize);
+    IMPORT_C TInt GetCSInterfaceDescriptorBlockSize(DThread* aThread, const DBase* aClientId,
+                                                    TInt aSettingNum, TDes8& aSize);
+    IMPORT_C TInt GetCSEndpointDescriptorBlock(DThread* aThread, const DBase* aClientId, TInt aSettingNum,
+                                               TInt aEndpointNum, TDes8& aEndpointDescriptor);
+    IMPORT_C TInt SetCSEndpointDescriptorBlock(DThread* aThread, const DBase* aClientId, TInt aSettingNum,
+                                               TInt aEndpointNum, const TDes8& aEndpointDescriptor,
+                                               TInt aSize);
+    IMPORT_C TInt GetCSEndpointDescriptorBlockSize(DThread* aThread, const DBase* aClientId, TInt aSettingNum,
+                                                   TInt aEndpointNum, TDes8& aSize);
+    IMPORT_C TInt GetStringDescriptorLangId(DThread* aThread, TDes8& aLangId);
+    IMPORT_C TInt SetStringDescriptorLangId(TUint16 aLangId);
+    IMPORT_C TInt GetManufacturerStringDescriptor(DThread* aThread, TDes8& aString);
+    IMPORT_C TInt SetManufacturerStringDescriptor(DThread* aThread, const TDes8& aString);
+    IMPORT_C TInt RemoveManufacturerStringDescriptor();
+    IMPORT_C TInt GetProductStringDescriptor(DThread* aThread, TDes8& aString);
+    IMPORT_C TInt SetProductStringDescriptor(DThread* aThread, const TDes8& aString);
+    IMPORT_C TInt RemoveProductStringDescriptor();
+    IMPORT_C TInt GetSerialNumberStringDescriptor(DThread* aThread, TDes8& aString);
+    IMPORT_C TInt SetSerialNumberStringDescriptor(DThread* aThread, const TDes8& aString);
+    IMPORT_C TInt RemoveSerialNumberStringDescriptor();
+    IMPORT_C TInt GetConfigurationStringDescriptor(DThread* aThread, TDes8& aString);
+    IMPORT_C TInt SetConfigurationStringDescriptor(DThread* aThread, const TDes8& aString);
+    IMPORT_C TInt RemoveConfigurationStringDescriptor();
+    IMPORT_C TInt GetStringDescriptor(DThread* aThread, TUint8 aIndex, TDes8& aString);
+    IMPORT_C TInt SetStringDescriptor(DThread* aThread, TUint8 aIndex, const TDes8& aString);
+    IMPORT_C TInt RemoveStringDescriptor(TUint8 aIndex);
+    IMPORT_C TBool QueryEndpointResource(const DBase* aClientId, TInt aEndpointNum,
+                                         TUsbcEndpointResource aResource);
+    IMPORT_C TInt EndpointPacketSize(const DBase* aClientId, TInt aEndpointNum);
+    
+    // Called by LDD
+    IMPORT_C TDfcQue*  DfcQ(TInt aIndex);
+    IMPORT_C void DumpRegisters();
+    IMPORT_C TInt SignalRemoteWakeup();
+    IMPORT_C TBool CurrentlyUsingHighSpeed();
+    
+    TInt RegisterUdc(TInt aUdc);
+
+protected:
+
+    // From base class MUsbPeripheralPilCallbackIf
+    void EnablePeripheralStack();
+    void DisablePeripheralStack();
+    void SetOtgObserver(MUsbOtgPeripheralObserverIf* aObserver);
+
+    // Function derived from MUsbPeripheralPilCallbackIf
+    UsbShai::TControlStage EnquireEp0NextStage(const TUint8* aSetupBuf) const;
+    TInt Ep0RequestComplete(TInt aRealEndpoint, TInt aCount, TInt aError,UsbShai::TControlPacketType aPktType);
+    void EndpointRequestComplete(UsbShai::TUsbPeripheralRequest* aCallback);
+    TInt DeviceEventNotification(TUsbcDeviceEvent aEvent);
+    void MoveToAddressState();
+    TInt ProcessSetConfiguration(const TUsbcSetup& aPacket);
+    void HandleHnpRequest(TInt aHnpState);
+    void GetEp0RxBufferInfo(TUint8*& aBuffer, TInt& aBufferLen); 
+    void SetRmWakeupStatusEnabled(TBool aRmEnabled);
+    UsbShai::TUsbPeripheralState DeviceStatus() const;
+    TBool Ep0ReceivedNonStdRequest();
+    
+    // Functions derived from MControlTransferIf
+    // PSL -> PIL
+    void ProcessDataInPacket(TInt aCount,TInt aErrCode);
+    void ProcessStatusInPacket(TInt aErrCode);
+    void ProcessDataOutPacket(TInt aCount,TInt aErrCode);
+    void ProcessStatusOutPacket(TInt aErrCode);
+    void ProcessSetupPacket(TInt aCount,TInt aErrCode);
+    
+    // Request from PIL -> PSL
+    TInt ProcessSetupEndpointZeroRead();
+    TInt ProcessSetupEndpointZeroWrite(const TUint8* aBuffer, TInt aLength, TBool aZlpReqd=EFalse);
+    TInt ProcessSendEp0ZeroByteStatusPacket();
+    TInt ProcessStallEndpoint(TInt aRealEndpoint);
+    
+    // Flow control PIL <--> PSL
+    void ProcessEp0SetupPacketProceed();
+    void ProcessEp0DataPacketProceed();
+    
+    // Functions from MChargerDetectorObserverIf
+    void NotifyPortType(UsbShai::TPortType aPortType);
+    //
+    //
+    // --- Functions and data members provided by PIL, called by PSL ---
+    //
+private:
+    struct TUsbPeripheralDescriptorPool
+        {
+        TUsbcDeviceDescriptor* iDeviceDesc;
+        TUsbcConfigDescriptor* iConfigDesc;
+        TUsbcLangIdDescriptor* iLangId;
+        TUsbcStringDescriptor* iManufacturer;
+        TUsbcStringDescriptor* iProduct;
+        TUsbcStringDescriptor* iSerialNum;
+        TUsbcStringDescriptor* iConfig;
+        TUsbcOtgDescriptor* iOtgDesc;
+        };
+        
+private:
+    // Internal functions that used in Construct only
+    // This function will new a set of descriptors
+    TBool CreateDescriptors(TUsbPeripheralDescriptorPool& aOutput);
+    
+    TBool Initialise(TUsbPeripheralDescriptorPool& aDescPool,
+                     const UsbShai::TUsbPeripheralEndpointCaps* aEndpointCaps,
+                     TInt aTotalEndpoint);                    
+
+    DUsbClientController(UsbShai::MPeripheralControllerIf&               aPeripheralControllerIf, 
+                         const UsbShai::TPeripheralControllerProperties& aProperties,
+                         TBool                                  aIsOtgPort);
+    
+    TInt Construct();
+    
+    void ProcessStandardRequest(TInt aCount,const TUsbcSetup& aPacket);    
+    void ProcessNonStandardRequest(TInt aCount,const TUsbcSetup& aPacket);
+    
+    const DBase* FindNonStandardRequestClient(TUint8 aPacketTypeDestination,const TUsbcSetup& aPacket);
+    
+    TInt SetupEp0StateMachine();
+    
+private:
+    
+    /** This info can be used by the PSL before sending ZLPs.
+
+        @publishedPartner @released
+    */
+    TBool iEp0ReceivedNonStdRequest;
+
+    /** True if RMW is currently enabled (set by either PIL or PSL).
+
+        @publishedPartner @released
+    */
+    TBool iRmWakeupStatus_Enabled;
+
+    /** Ep0 incoming (rx) data is placed here (one packet).
+
+        @publishedPartner @released
+    */
+    TUint8 iEp0_RxBuf[KUsbcBufSzControl];
+
+private:
+
+    //
+    // --- Private member functions (used by PIL) ---
+    //
+    TInt DeRegisterClientCallback(const DBase* aClientId);
+    TBool CheckEpAvailability(TInt aEndpointsUsed, const TUsbcEndpointInfoArray& aEndpointData, TInt aIfcNumber)
+        const;
+    TUsbcInterface* CreateInterface(const DBase* aClientId, TInt aIfc, TUint32 aFeatureWord);
+    TInt CreateEndpoints(TUsbcInterface* aIfc, TInt aEndpointsUsed, const TUsbcEndpointInfoArray& aEndpointData,
+                         TInt *aRealEpNumbers);
+    TInt SetupIfcDescriptor(TUsbcInterface* aIfc, TUsbcClassInfo& aClass, DThread* aThread, TDesC8* aString,
+                            const TUsbcEndpointInfoArray& aEndpointData);
+    TInt ClientId2InterfaceNumber(const DBase* aClientId) const;
+    TUsbcInterfaceSet* ClientId2InterfacePointer(const DBase* aClientId) const;
+    const DBase* InterfaceNumber2ClientId(TInt aIfcSet) const;
+    TUsbcInterfaceSet* InterfaceNumber2InterfacePointer(TInt aIfcSet) const;
+    inline const DBase* PEndpoint2ClientId(TInt aRealEndpoint) const;
+    inline TInt PEndpoint2LEndpoint(TInt aRealEndpoint) const;
+    TInt ActivateHardwareController();
+    void DeActivateHardwareController();
+    void DeleteInterfaceSet(TInt aIfcSet);
+    void DeleteInterface(TInt aIfcSet, TInt aIfc);
+    void CancelTransferRequests(TInt aRealEndpoint);
+    void DeleteRequestCallback(const DBase* aClientId, TInt aEndpointNum, UsbShai::TTransferDirection aTransferDir);
+    void DeleteRequestCallbacks(const DBase* aClientId);
+    void StatusNotify(UsbShai::TUsbPeripheralState aState, const DBase* aClientId=NULL);
+    void EpStatusNotify(TInt aRealEndpoint);
+    void OtgFeaturesNotify();
+    void RunClientCallbacks();
+    void ProcessDataTransferDone(TUsbcRequestCallback& aRcb);
+    void NextDeviceState(UsbShai::TUsbPeripheralState aNextState);
+    TInt ProcessSuspendEvent();
+    TInt ProcessSuspendEventProceed();
+    TInt ProcessResumeEvent();
+    TInt ProcessResetEvent(TBool aPslUpcall=ETrue);
+    TInt ProcessVbusRisenEvent();
+    TInt ProcessVbusFallenEvent();
+    
+    void ProcessGetDeviceStatus(const TUsbcSetup& aPacket);
+    void ProcessGetInterfaceStatus(const TUsbcSetup& aPacket);
+    void ProcessGetEndpointStatus(const TUsbcSetup& aPacket);
+    void ProcessSetClearDevFeature(const TUsbcSetup& aPacket);
+    void ProcessSetClearIfcFeature(const TUsbcSetup& aPacket);
+    void ProcessSetClearEpFeature(const TUsbcSetup& aPacket);
+    void ProcessSetAddress(const TUsbcSetup& aPacket);
+    void ProcessGetDescriptor(const TUsbcSetup& aPacket);
+    void ProcessSetDescriptor(const TUsbcSetup& aPacket);
+    void ProcessGetConfiguration(const TUsbcSetup& aPacket);
+    void ProcessGetInterface(const TUsbcSetup& aPacket);
+    void ProcessSetInterface(const TUsbcSetup& aPacket);
+    void ProcessSynchFrame(const TUsbcSetup& aPacket);
+    
+    void ProceedSetDescriptor();
+    void ProcessDeviceEventNotification(TUsbcDeviceEvent aEvent);
+    
+    void SetClearHaltFeature(TInt aRealEndpoint, TUint8 aRequest);
+    TInt ClearHaltFeature(TInt aRealEndpoint);
+    void ChangeConfiguration(TUint16 aValue);
+    void InterfaceSetup(TUsbcInterface* aIfc);
+    void InterfaceSetTeardown(TUsbcInterfaceSet* aIfc);
+    void ChangeInterface(TUsbcInterface* aIfc);
+    TInt DoForEveryEndpointInUse(TInt (DUsbClientController::*aFunction)(TInt), TInt& aCount);
+    void EnterFullSpeed();
+    void EnterHighSpeed();
+    TInt EvaluateOtgConnectFlags();
+    inline const TUsbcConfiguration* CurrentConfig() const;
+    inline TUsbcConfiguration* CurrentConfig();
+    inline TBool InterfaceExists(TInt aNumber) const;
+    inline TBool EndpointExists(TUint aAddress) const;
+    void Buffer2Setup(const TAny* aBuf, TUsbcSetup& aSetup) const;
+    inline TUint EpIdx2Addr(TUint aRealEndpoint) const;
+    inline TUint EpAddr2Idx(TUint aAddress) const;
+    inline void SetEp0DataOutVars(const DBase* aClientId = NULL);
+    inline void ResetEp0DataOutVars();
+    inline TBool IsInTheStatusList(const TUsbcStatusCallback& aCallback);
+    inline TBool IsInTheEpStatusList(const TUsbcEndpointStatusCallback& aCallback);
+    inline TBool IsInTheOtgFeatureList(const TUsbcOtgFeatureCallback& aCallback);
+    inline TBool IsInTheRequestList(const TUsbcRequestCallback& aCallback);
+    static void ReconnectTimerCallback(TAny* aPtr);
+    static void CableStatusTimerCallback(TAny* aPtr);
+    static void PowerUpDfc(TAny* aPtr);
+    static void PowerDownDfc(TAny* aPtr);
+    static void DeviceEventNotifyDfc(TAny* aPtr);
+    static void ThreadContextFinderDfc(TAny* aPtr);
+
+private:
+
+    //
+    // --- Private data members ---
+    //
+
+    static DUsbClientController* UsbClientController[KUsbcMaxUdcs];
+
+    TInt iDeviceTotalEndpoints;                                 // number of endpoints reported by PSL
+    TInt iDeviceUsableEndpoints;                                // number of endpoints reported to LDD
+    
+    UsbShai::TUsbPeripheralState iDeviceState;                              // states as of USB spec chapter 9.1
+    UsbShai::TUsbPeripheralState iDeviceStateB4Suspend;                     // state before entering suspend state
+
+    TBool iSelfPowered;                                         // true if device is capable of beeing self-powered
+    TBool iRemoteWakeup;                                        // true if device is capable of signalling rmwakeup
+    TBool iHardwareActivated;                                   // true if controller silicon is in operating state
+    TBool iOtgSupport;                                          // true if OTG is supported by this device
+    TUint8 iOtgFuncMap;                                         // bitmap indicating OTG extension features
+    TBool iHighSpeed;                                           // true if currently operating at high-speed
+    
+    TInt iEp0MaxPacketSize;                                     // currently configured max packet size for Ep0    
+    const DBase* iEp0ClientId;                                  // see comment at the begin of ps_usbc.cpp
+    TUint16 iEp0DataReceived;                                   // indicates how many bytes have already been received
+    TBool iEp0WritePending;                                     // true if a write on ep0 has been set up
+    TBool iEp0ClientDataTransmitting;                           // true if ep0's in DATA_IN on behalf of a client
+    const DBase* iEp0DeviceControl;                             // Device Ep0 requests are delivered to this LDD
+    
+    TUsbcDescriptorPool iDescriptors;                           // the descriptors as of USB spec chapter 9.5
+    TUint8 iCurrentConfig;                                      // bConfigurationValue of current Config (1-based!)
+    RPointerArray<TUsbcConfiguration> iConfigs;                 // the root of the modelled USB device
+    TUsbcPhysicalEndpoint iRealEndpoints[KUsbcEpArraySize];     // array will be filled once at startup
+    TUint8 iEp0_TxBuf[KUsbcBufSz_Ep0Tx];                        // ep0 outgoing (tx) data is placed here
+#ifdef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST
+    TUint8 iEp0_RxCollectionBuf[KUsbcBufSz_Ep0Rx];              // used for (optional) SET_DESCRIPTOR request
+#endif
+    TInt iEp0_RxExtraCount;                                     // number of bytes received but not yet delivered
+    TBool iEp0_RxExtraData;                                     // true if iEp0_RxExtraCount is valid
+    TInt iEp0_TxNonStdCount;                                    // number of bytes requested by non-std Ep0 request
+    
+    TUsbcRequestCallback* iRequestCallbacks[KUsbcEpArraySize];  // xfer requests; indexed by real ep number
+    TSglQue<TUsbcRequestCallback> iEp0ReadRequestCallbacks;     // list of ep0 read requests
+    TSglQue<TUsbcClientCallback> iClientCallbacks;              // registered LDD clients and their callback functions
+    TSglQue<TUsbcStatusCallback> iStatusCallbacks;              // list of device state notification requests
+    TSglQue<TUsbcEndpointStatusCallback> iEpStatusCallbacks;    // list of endpoint state notification requests
+    TSglQue<TUsbcOtgFeatureCallback> iOtgCallbacks;             // list of OTG feature change requests
+    
+    NTimer iReconnectTimer;                                     // implements USB re-enumeration delay
+    NTimer iCableStatusTimer;                                   // implements USB cable status detection delay
+    DUsbcPowerHandler* iPowerHandler;                           // pointer to USB power handler object
+    TSpinLock iUsbLock;                                         // implement SMP for USB PDD and LDD
+    NFastMutex iMutex;                                          // To pretect interface set with NFastMutex
+    UsbShai::MPeripheralControllerIf& iController;              // PSL code
+    
+    const UsbShai::TPeripheralControllerProperties& iControllerProperties;   // Static configuration from PSL
+    TBool iIsOtgPort;                                               // Is this instance a driver for otg port,
+                                                                    // Set at construction time.
+
+    /**
+     * Pointer to the currently set OTG Observer, if any. Not owned.
+     */
+	MUsbOtgPeripheralObserverIf* iOtgObserver;  // Otg interface which is used to listen event from DeviceEventNotification
+    
+    DControlTransferManager* iConTransferMgr;    // Usb Control transfer manager, responsible for chaptor9
+    
+    TInt iLastError;                            // Used by chaptor9 sm. No else.
+    TBool iSetupPacketPending;                  // Indicate whether the no-req-callback data is a setup packet
+                                                            
+    TUsbPeriDeviceEventQueue iDevEventQueue;    // PSL can call DeviceEventNotification(...) at any context, 
+                                                // but for PIL, we want to serialize the execution of each event
+    
+    // The thread context for the DfcQ pass by PSL to us.
+    NThread* iCommonDfcQThread;
+    
+protected:
+    TDfc iPowerUpDfc;                         // queued by power handler upon power-up
+    TDfc iPowerDownDfc;                       // queued by power handler upon power-down
+    TDfc iDeviceEventNotifyDfc;               // queued by device event notification
+    TDfc iThreadContextFinder;                // this is used to find which thread does the DfcQ passed by PSL
+                                              // is runing.
+
+private:
+    TBool iStandby;                           // toggled by power handler as appropriate
+    TBool iStackIsActive;                     // client stack's function is usable
+    TBool iClientSupportReady;                // user-side USB Client support is loaded & active
+    TBool iUsbResetDeferred;                  // set when user-side wasn't ready yet
+
+public:
+    // FIXME: These used to be filled by the OTG component Dummy DCD
+    // so that the PIL layer can call it to enable and disable the D+
+    // pull-up. This mechanism is no longer used
+    TInt (*iEnablePullUpOnDPlus)(TAny* aOtgContext);
+    TInt (*iDisablePullUpOnDPlus)(TAny* aOtgContext);
+    TAny* iOtgContext;
+    };
+    
+/** Simple queue of status changes to be recorded.
+    Items are fetched by userside when able.
+*/
+class TUsbcDeviceStatusQueue
+    {
+public:
+    TUsbcDeviceStatusQueue();
+    void AddStatusToQueue(TUint32 aDeviceStatus);
+    TInt GetDeviceQueuedStatus(TUint32& aDeviceStatus);
+    void FlushQueue();
+
+private:
+    TUint32 iDeviceStatusQueue[KUsbDeviceStatusQueueDepth];
+    TInt iStatusQueueHead;
+    };
+    
+#include <usb/usbcshared.inl>
+
+#endif    // __USBCSHARED_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/public/usbcshared.inl	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,571 @@
+// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\include\drivers\usbcshared.inl
+// Kernel side definitions for the USB Device driver stack (PIL + LDD).
+// 
+//
+
+/**
+ @file usbcshared.inl
+ @internalTechnology
+*/
+
+#ifndef __USBCSHARED_INL__
+#define __USBCSHARED_INL__
+
+//
+// --- DUsbClientController (USB PDD) ---
+//
+
+// --- Private member functions, used by controller itself ---
+
+const DBase* DUsbClientController::PEndpoint2ClientId(TInt aRealEndpoint) const
+	{
+	if (iRealEndpoints[aRealEndpoint].iLEndpoint)
+		return iRealEndpoints[aRealEndpoint].iLEndpoint->iInterface->iInterfaceSet->iClientId;
+	else
+		return NULL;
+	}
+
+
+TInt DUsbClientController::PEndpoint2LEndpoint(TInt aRealEndpoint) const
+	{
+	if (iRealEndpoints[aRealEndpoint].iLEndpoint)
+		return iRealEndpoints[aRealEndpoint].iLEndpoint->iLEndpointNum;
+	else
+		return -1;
+	}
+
+
+const TUsbcConfiguration* DUsbClientController::CurrentConfig() const
+	{
+	return (iCurrentConfig ? iConfigs[iCurrentConfig - 1] : NULL);
+	}
+
+
+TUsbcConfiguration* DUsbClientController::CurrentConfig()
+	{
+	return (iCurrentConfig ? iConfigs[iCurrentConfig - 1] : NULL);
+	}
+
+
+TBool DUsbClientController::InterfaceExists(TInt aNumber) const
+	{
+	const TInt num_ifcsets = iConfigs[0]->iInterfaceSets.Count();
+	RPointerArray<TUsbcInterfaceSet>& ifcsets = iConfigs[0]->iInterfaceSets;
+	for (TInt i = 0; i < num_ifcsets; i++)
+		{
+		if (ifcsets[i]->iInterfaceNumber == aNumber)
+			{
+			return ETrue;
+			}
+		}
+	return EFalse;
+	}
+
+
+TBool DUsbClientController::EndpointExists(TUint aAddress) const
+	{
+	// Ep0 doesn't have a "logical ep" pointer (there's no virtual endpoint zero);
+	// that's why this pointer being non-NULL is not a sufficient criterion for
+	// endpoint-existence. (Apart from that, ep0 always exists.)
+	const TInt idx = EpAddr2Idx(aAddress);
+	return ((idx < iDeviceTotalEndpoints) &&
+			((iRealEndpoints[idx].iLEndpoint != NULL) ||
+			 ((aAddress & KUsbEpAddress_Portmask) == 0)));
+	}
+
+TUint DUsbClientController::EpIdx2Addr(TUint aRealEndpoint) const
+	{
+	return ((aRealEndpoint << 7) & 0x80) | ((aRealEndpoint >> 1) & 0x0f);
+	}
+
+
+TUint DUsbClientController::EpAddr2Idx(TUint aAddress) const
+	{
+	return ((aAddress & 0x80) >> 7) | ((aAddress & 0x0f) << 1);
+	}
+
+
+void DUsbClientController::SetEp0DataOutVars(const DBase* aClientId)
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetEp0DataOutVars()"));
+	//iSetup = aPacket;
+	iEp0DataReceived = 0;
+	iEp0ClientId = aClientId;
+	}
+
+
+void DUsbClientController::ResetEp0DataOutVars()
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ResetEp0DataOutVars()"));
+	iEp0DataReceived = 0;
+	iEp0ClientId = NULL;
+	}
+
+
+TBool DUsbClientController::IsInTheRequestList(const TUsbcRequestCallback& aCallback)
+	{
+    	const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
+	TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks);
+	TUsbcRequestCallback* p;
+	while ((p = iter++) != NULL)
+		{
+		if (p == &aCallback)
+			{
+			__SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+			return ETrue;
+			}
+		}
+    	__SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+	return EFalse;
+	}
+
+
+TBool DUsbClientController::IsInTheStatusList(const TUsbcStatusCallback& aCallback)
+	{
+    	const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
+	TSglQueIter<TUsbcStatusCallback> iter(iStatusCallbacks);
+	TUsbcStatusCallback* p;
+	while ((p = iter++) != NULL)
+		{
+		if (p == &aCallback)
+			{
+            		__SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+			return ETrue;
+			}
+		}
+    	__SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+	return EFalse;
+	}
+
+
+TBool DUsbClientController::IsInTheEpStatusList(const TUsbcEndpointStatusCallback& aCallback)
+	{
+    	const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
+	TSglQueIter<TUsbcEndpointStatusCallback> iter(iEpStatusCallbacks);
+	TUsbcEndpointStatusCallback* p;
+	while ((p = iter++) != NULL)
+		{
+		if (p == &aCallback)
+			{
+		    	__SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+			return ETrue;
+			}
+		}
+    	__SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+	return EFalse;
+	}
+
+
+TBool DUsbClientController::IsInTheOtgFeatureList(const TUsbcOtgFeatureCallback& aCallback)
+	{
+    	const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
+	TSglQueIter<TUsbcOtgFeatureCallback> iter(iOtgCallbacks);
+	TUsbcOtgFeatureCallback* p;
+	while ((p = iter++) != NULL)
+		{
+		if (p == &aCallback)
+			{
+		    	__SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+			return ETrue;
+			}
+		}
+    	__SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+	return EFalse;
+	}
+
+//
+// --- Misc classes ---
+//
+
+// --- TUsbcClientCallback
+
+/** Constructor.
+ */
+TUsbcClientCallback::TUsbcClientCallback(DBase* aOwner, TDfcFn aCallback, TInt aPriority)
+	: iOwner(aOwner),
+	  iDfc(aCallback, aOwner, aPriority)
+	{}
+
+
+/** Returns a pointer to the owner of this request.
+
+	@return A pointer to the owner of this request.
+*/
+DBase* TUsbcClientCallback::Owner() const
+	{
+	return iOwner;
+	}
+
+
+/** Executes the callback function set by the owner of this request.
+
+	@return KErrNone.
+*/
+TInt TUsbcClientCallback::DoCallback()
+	{
+	__ASSERT_DEBUG((NKern::CurrentContext() == EThread), Kern::Fault(KUsbPILPanicCat, __LINE__));
+	iDfc.Enque();
+	return KErrNone;
+	}
+
+
+/** Cancels the callback function set by the owner of this request.
+ */
+void TUsbcClientCallback::Cancel()
+	{
+	iDfc.Cancel();
+	}
+
+
+/** Sets the DFC queue used by the callback function.
+	@param aDfcQ DFC queue to be set
+ */
+void TUsbcClientCallback::SetDfcQ(TDfcQue* aDfcQ)
+	{
+	iDfc.SetDfcQ(aDfcQ);
+	}
+
+
+// --- TUsbcEndpointStatusCallback
+
+/** Constructor.
+ */
+TUsbcEndpointStatusCallback::TUsbcEndpointStatusCallback(DBase* aOwner, TDfcFn aCallback,
+														 TInt aPriority)
+	: iOwner(aOwner),
+	  iDfc(aCallback, aOwner, aPriority),
+	  iState(0)
+	{}
+
+
+/** Sets the state of this request to aState.
+
+	@param aState The new state to be set.
+*/
+void TUsbcEndpointStatusCallback::SetState(TUint aState)
+	{
+	iState = aState;
+	}
+
+
+/** Returns the state value of this request.
+
+	@return The state value of this request.
+*/
+TUint TUsbcEndpointStatusCallback::State() const
+	{
+	return iState;
+	}
+
+
+/** Returns a pointer to the owner of this request.
+
+	@return A pointer to the owner of this request.
+*/
+DBase* TUsbcEndpointStatusCallback::Owner() const
+	{
+	return iOwner;
+	}
+
+
+/** Executes the callback function set by the owner of this request.
+
+	@return KErrNone.
+*/
+TInt TUsbcEndpointStatusCallback::DoCallback()
+	{
+	if (NKern::CurrentContext() == EThread)
+		iDfc.Enque();
+	else
+		iDfc.Add();
+	return KErrNone;
+	}
+
+
+/** Cancels the callback function set by the owner of this request.
+*/
+void TUsbcEndpointStatusCallback::Cancel()
+	{
+	iDfc.Cancel();
+	}
+
+
+/** Sets the DFC queue used by the callback function.
+*/
+void TUsbcEndpointStatusCallback::SetDfcQ(TDfcQue* aDfcQ)
+	{
+	iDfc.SetDfcQ(aDfcQ);
+	}
+
+
+// --- TUsbcStatusCallback
+
+/** Constructor.
+ */
+TUsbcStatusCallback::TUsbcStatusCallback(DBase* aOwner, TDfcFn aCallback, TInt aPriority)
+	: iOwner(aOwner),
+	  iDfc(aCallback, aOwner, aPriority)
+	{
+ 	ResetState();
+	}
+
+
+/** Sets the state of this request to aState (at the first available position
+	in the state value array).
+
+	@param aState The new state to be set.
+*/
+void TUsbcStatusCallback::SetState(UsbShai::TUsbPeripheralState aState)
+	{
+	for (TInt i = 0; i < KUsbcDeviceStateRequests; i++)
+		{
+		if (iState[i] == UsbShai::EUsbPeripheralNoState)
+			{
+			iState[i] = aState;
+			return;
+			}
+		}
+	__KTRACE_OPT(KPANIC, Kern::Printf("  Error: KUsbcDeviceStateRequests too small (%d)!",
+									  KUsbcDeviceStateRequests));
+	}
+
+
+/** Returns the state value of this request at a certain index.
+
+	@param aIndex The index to be used for referencing the state array.
+
+	@return The state value of this request at aIndex.
+*/
+UsbShai::TUsbPeripheralState TUsbcStatusCallback::State(TInt aIndex) const
+	{
+	if (aIndex >= 0 && aIndex < KUsbcDeviceStateRequests)
+		{
+		return iState[aIndex];
+		}
+	else
+		{
+		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: aIndex too large (%d)!", aIndex));
+		return UsbShai::EUsbPeripheralNoState;
+		}
+	}
+
+
+/** Resets the entire state value array of this request.
+*/
+void TUsbcStatusCallback::ResetState()
+	{
+	for (TInt i = 0; i < KUsbcDeviceStateRequests; ++i)
+		{
+		iState[i] = UsbShai::EUsbPeripheralNoState;
+		}
+	}
+
+
+/** Returns a pointer to the owner of this request.
+
+	@return A pointer to the owner of this request.
+*/
+DBase* TUsbcStatusCallback::Owner() const
+	{
+	return iOwner;
+	}
+
+
+/** Executes the callback function set by the owner of this request.
+
+	@return KErrNone.
+*/
+TInt TUsbcStatusCallback::DoCallback()
+	{
+	if (NKern::CurrentContext() == EThread)
+		iDfc.Enque();
+	else
+		iDfc.Add();
+	return KErrNone;
+	}
+
+
+/** Cancels the callback function set by the owner of this request.
+*/
+void TUsbcStatusCallback::Cancel()
+	{
+	iDfc.Cancel();
+	}
+
+
+/** Sets the DFC queue used by the callback function.
+*/
+void TUsbcStatusCallback::SetDfcQ(TDfcQue* aDfcQ)
+	{
+	iDfc.SetDfcQ(aDfcQ);
+	}
+
+// --- TUsbcRequestCallback
+
+/** Constructor.
+ */
+TUsbcRequestCallback::TUsbcRequestCallback(const DBase* aOwner, TInt aEndpointNum, TDfcFn aDfcFunc,
+										   TAny* aEndpoint, TDfcQue* aDfcQ, TInt aPriority)
+	: TUsbPeripheralRequest(-1),
+      iEndpointNum(aEndpointNum),
+	  iOwner(aOwner),
+	  iDfc(aDfcFunc, aEndpoint, aDfcQ, aPriority)
+	{
+	}
+
+
+/** Destructor.
+ */
+TUsbcRequestCallback::~TUsbcRequestCallback()
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcRequestCallback::~TUsbcRequestCallback()"));
+	iDfc.Cancel();
+	}
+
+/** Sets the transfer direction for this request.
+
+	@param aTransferDir The new transfer direction.
+*/
+void TUsbcRequestCallback::SetTransferDirection(UsbShai::TTransferDirection aTransferDir)
+	{
+	iTransferDir = aTransferDir;
+	}
+
+
+/** Returns a pointer to the owner of this request.
+
+	@return A pointer to the owner of this request.
+*/
+const DBase* TUsbcRequestCallback::Owner() const
+	{
+	return iOwner;
+	}
+
+
+/** Executes the callback function set by the owner of this request.
+
+	@return KErrNone.
+*/
+TInt TUsbcRequestCallback::DoCallback()
+	{
+	if (NKern::CurrentContext() == NKern::EThread)
+		iDfc.Enque();
+	else
+		iDfc.Add();
+	return KErrNone;
+	}
+
+
+/** Cancels the callback function set by the owner of this request.
+*/
+void TUsbcRequestCallback::Cancel()
+	{
+	iDfc.Cancel();
+	}
+
+// --- TUsbcOtgFeatureCallback
+
+/** Constructor.
+ */
+TUsbcOtgFeatureCallback::TUsbcOtgFeatureCallback(DBase* aOwner, TDfcFn aCallback,
+												 TInt aPriority)
+	: iOwner(aOwner),
+	  iDfc(aCallback, aOwner, aPriority),
+	  iValue(0)
+	{}
+
+
+/** Returns a pointer to the owner of this request.
+	@return A pointer to the owner of this request.
+*/
+DBase* TUsbcOtgFeatureCallback::Owner() const
+	{
+	return iOwner;
+	}
+
+
+/** Set feature value which is to be notified to client.
+	@param OTG feature value to be set
+*/
+void TUsbcOtgFeatureCallback::SetFeatures(TUint8 aFeatures)
+	{
+	iValue = aFeatures;
+	}
+
+
+/** Set feature value which is to be notified to client.
+	@return Value of OTG features
+*/
+TUint8 TUsbcOtgFeatureCallback::Features() const
+	{
+	return iValue;
+	}
+
+
+/** Set DFC queue.
+	@param aDfcQ  DFC queue to be set
+*/ 
+void TUsbcOtgFeatureCallback::SetDfcQ(TDfcQue* aDfcQ)
+	{
+	iDfc.SetDfcQ(aDfcQ);
+	}
+
+
+/** Executes the callback function set by the owner of this request.
+	@return KErrNone.
+*/
+TInt TUsbcOtgFeatureCallback::DoCallback()
+	{
+	if (NKern::CurrentContext() == EThread)
+		iDfc.Enque();
+	else
+		iDfc.Add();
+	return KErrNone;
+	}
+
+
+/** Cancels the callback function set by the owner of this request.
+ */
+void TUsbcOtgFeatureCallback::Cancel()
+	{
+	iDfc.Cancel();
+	}
+
+
+/** Returns a pointer to the currently selected (active) setting of this interface.
+
+	@return A pointer to the currently selected (active) setting of this interface.
+*/
+const TUsbcInterface* TUsbcInterfaceSet::CurrentInterface() const
+	{
+	return iInterfaces[iCurrentInterface];
+	}
+
+
+/** Returns a pointer to the currently selected (active) setting of this interface.
+
+	@return A pointer to the currently selected (active) setting of this interface.
+*/
+
+TUsbcInterface* TUsbcInterfaceSet::CurrentInterface()
+	{
+	return iInterfaces[iCurrentInterface];
+	}
+
+#endif // __USBCSHARED_INL__
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbdrv/peripheral/public/usbotgperipheralcontrolif.h	Fri Jul 23 15:54:47 2010 +0800
@@ -0,0 +1,80 @@
+// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\include\drivers\usbcshared.h
+// Kernel side definitions for the USB Device driver stack (PIL + LDD).
+// 
+//
+
+/**
+ @file usbotgperipheralcontrolif.h
+ @internalTechnology
+*/
+
+#ifndef USBOTGPERIPHERALCONTROLIF_H
+#define USBOTGPERIPHERALCONTROLIF_H
+
+#include <usb/usb_peripheral_shai.h> // For UsbShai::TUsbPeripheralEvent
+
+/**
+ * This M-class specifies the observer interface that the OTG state
+ * machine implements to listen to events of the peripheral stack.
+ */
+NONSHARABLE_CLASS(MUsbOtgPeripheralObserverIf)
+    {
+    public:
+    /**
+     * Called by the peripheral stack to report a peripheral event to
+     * the OTG stack.
+     *
+     * @param aEvent An enumeration value specifying the type of event
+     *   that has occurred
+     */
+    virtual void NotifyPeripheralEvent(UsbShai::TUsbPeripheralEvent aEvent) = 0;
+    };
+
+
+/**
+ * This M-class specifies the control interface that the OTG state
+ * machine uses to control the peripheral stack and register for
+ * peripheral events.
+ */
+NONSHARABLE_CLASS(MUsbOtgPeripheralControlIf)
+    {
+    public:
+    /**
+     * Called by the OTG state machine to enable the peripheral stack.
+     * When called, the peripheral stack must activate the controller
+     * and connect to the bus as soon as possible.
+     */
+    virtual void EnablePeripheralStack() = 0;
+
+    /**
+     * Called by the OTG state machine to disable the peripheral
+     * stack. When called, the peripheral stack must immediately
+     * disconnect from the bus and deactivate the controller.
+     */
+    virtual void DisablePeripheralStack() = 0;
+
+    /**
+     * Called by the OTG state machine to set the peripheral event
+     * observer.
+     *
+     * @param aObserver Pointer to the OTG Observer, or NULL when the
+     *   OTG stack is being shutdown.
+     */
+    virtual void SetOtgObserver(MUsbOtgPeripheralObserverIf* aObserver) = 0;
+    };
+
+
+#endif    // USBOTGPERIPHERALCONTROLIF_H