diff -r 613028a7da24 -r eaaed528d5fd usbdrv/peripheral/pdd/pil/src/ps_usbc.cpp --- a/usbdrv/peripheral/pdd/pil/src/ps_usbc.cpp Thu Sep 02 22:23:37 2010 +0300 +++ b/usbdrv/peripheral/pdd/pil/src/ps_usbc.cpp Fri Sep 17 08:40:15 2010 +0300 @@ -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 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 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) {