usbdrv/peripheral/pdd/pil/src/ps_usbc.cpp
changeset 48 21625e5de155
parent 33 089413cdde3c
child 59 bbdce6bffaad
--- a/usbdrv/peripheral/pdd/pil/src/ps_usbc.cpp	Wed Aug 25 15:55:37 2010 +0800
+++ b/usbdrv/peripheral/pdd/pil/src/ps_usbc.cpp	Mon Sep 06 11:27:08 2010 +0800
@@ -101,6 +101,8 @@
 // Charger observer is the guy who want to monitor the chager type event.
 static UsbShai::MChargerDetectorObserverIf* gChargerObsever = NULL;
 
+static UsbShai::TChargerDetectorProperties gChargerDetectorProperties;
+
 
 // Those const variables are used to construct the default 
 // Usb descriptors, Upper layer can change them later.
@@ -352,6 +354,9 @@
     __KTRACE_OPT(KUSB, Kern::Printf("> DUsbClientController::DeviceCaps()"));
     TUsbDeviceCaps caps;
     caps().iTotalEndpoints = iDeviceUsableEndpoints;        // not DeviceTotalEndpoints()!
+
+    // In the SHAI API, all PSLs are required to support soft connection
+    caps().iConnect = ETrue;
     
     caps().iSelfPowered = iSelfPowered;
     caps().iRemoteWakeup = iRemoteWakeup;
@@ -404,6 +409,14 @@
     }
 
 
+
+EXPORT_C void DUsbClientController::ChargerDetectorCaps(UsbShai::TChargerDetectorProperties& aProperties)
+    {
+    aProperties = gChargerDetectorProperties;
+    }
+
+
+
 /** Creates a new USB interface (one setting), complete with endpoints, descriptors, etc.,
     and chains it into the internal device configuration tree.
 
@@ -923,6 +936,7 @@
     DeRegisterForEndpointStatusChange(aClientId);
     DeRegisterForOtgFeatureChange(aClientId);
     DeRegisterClientCallback(aClientId);
+    DeRegisterChargingPortTypeNotify(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);
@@ -2619,6 +2633,68 @@
     {
     return iController.SignalRemoteWakeup();
     }
+/** Registers client request for USB charger type notification. Client is notified when USB device is
+    attached to or detached from any USB charger, and the charger type is sent to client.
+    
+    @param aCallback A reference to a properly filled in charger type 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::RegisterChargingPortTypeNotify(TUsbcChargerTypeCallback& aCallback)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RegisterChargingPortTypeNotify()"));
+    if (iChargerTypeCallbacks.Elements() == KUsbcMaxListLength)
+        {
+        __KTRACE_OPT(KPANIC, Kern::Printf("  Error: In charger type list, the maximum list length reached: %d",
+                                          KUsbcMaxListLength));
+        return KErrGeneral;
+        }
+    if (IsInTheChargerTypeList(aCallback))
+        {
+        __KTRACE_OPT(KUSB, Kern::Printf("  Error: UsbcChargerTypeCallback @ 0x%x already registered", &aCallback));
+        return KErrGeneral;
+        }
+    const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
+    iChargerTypeCallbacks.AddLast(aCallback);
+    __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);    
+    
+    if(iCurrentChargerType !=  UsbShai::EPortTypeNone)
+        {
+        aCallback.SetChargerType(iCurrentChargerType);
+        aCallback.SetPendingNotify(ETrue);
+        }
+    return KErrNone;
+    }
+
+/** De-registers (removes from the list of pending requests) a notification callback for
+    USB charger type change.
+
+    @param aClientId A pointer to the LDD owning the charger type callback.
+
+    @return KErrNone if callback successfully unregistered, KErrNotFound if the callback couldn't be found.
+*/
+EXPORT_C TInt DUsbClientController::DeRegisterChargingPortTypeNotify(const DBase* aClientId)
+    {
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterChargingPortTypeNotify()"));
+    __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
+    const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock);
+    TSglQueIter<TUsbcChargerTypeCallback> iter(iChargerTypeCallbacks);
+    TUsbcChargerTypeCallback* p;
+    while ((p = iter++) != NULL)
+        {
+        if (p->Owner() == aClientId)
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("  removing UsbcChargerTypeCallback @ 0x%x", p));
+            iChargerTypeCallbacks.Remove(*p);
+            __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+            return KErrNone;
+            }
+        }
+    __KTRACE_OPT(KUSB, Kern::Printf("  client not found"));
+    __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq);
+    return KErrNotFound;
+    }
     
 EXPORT_C TBool DUsbClientController::CurrentlyUsingHighSpeed()
     {
@@ -2913,10 +2989,19 @@
       iUsbResetDeferred(EFalse),
       iEnablePullUpOnDPlus(NULL),
       iDisablePullUpOnDPlus(NULL),
-      iOtgContext(NULL)
+      iOtgContext(NULL),
+	  iChargerTypeCallbacks(_FOFF(TUsbcChargerTypeCallback, iLink)),
+	  iCurrentChargerType(UsbShai::EPortTypeNone)
     {
     __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DUsbClientController()"));
     
+    // Note that we take a direct copy of the controller properties in
+    // the initialization list for now. If fields are later added to
+    // the properties class in the SHAI, we need to start copying
+    // field-by-field and check the PSL reported capabilities before
+    // accessing a field that may not be present in an older PSL
+    // binary.
+
     iLastError = KErrNone;
     
 #ifndef SEPARATE_USB_DFC_QUEUE
@@ -4687,7 +4772,18 @@
 // Functions from UsbShai::MChargerDetectorObserverIf
 void DUsbClientController::NotifyPortType(UsbShai::TPortType aPortType)
     {
-    // FIXME: Not yet implemented!
+    __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::NotifyPortType(), aPortType = %d", aPortType));
+
+    TSglQueIter<TUsbcChargerTypeCallback> iter(iChargerTypeCallbacks);
+    TUsbcChargerTypeCallback* p;
+    
+    iCurrentChargerType = aPortType;
+    
+    while ((p = iter++) != NULL)
+        {
+        p->SetChargerType(aPortType);
+        p->DoCallback();
+        }    
     }
 
 void DUsbClientController::Buffer2Setup(const TAny* aBuf, TUsbcSetup& aSetup) const
@@ -4818,8 +4914,14 @@
         {
         return ;
         }
-        
+
+    // We take a direct copy of the charger detector properties for
+    // now. If fields are later added to the properties classes in the
+    // SHAI, we need to start copying field-by-field and check the PSL
+    // reported capabilities before accessing a field that may not be
+    // present in an older PSL binary.
     gChargerDetector = &aChargerDetector;
+    gChargerDetectorProperties = aProperties;
     
     if(gChargerObsever != NULL)
         {