diff -r 2d65c2f76d7b -r 947f0dc9f7a8 kernel/eka/drivers/usbcc/ps_usbc.cpp --- a/kernel/eka/drivers/usbcc/ps_usbc.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/drivers/usbcc/ps_usbc.cpp Fri Apr 16 16:24:37 2010 +0300 @@ -180,11 +180,13 @@ } 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(EUsbcDeviceStateUndefined); // Complete all pending requests, returning KErrDisconnected RunClientCallbacks(); - // Notify registered clients on the user side about a USB device state - // change event and a transition to the "Undefined" state. - NextDeviceState(EUsbcDeviceStateUndefined); } @@ -672,14 +674,14 @@ #ifdef USB_OTG_CLIENT iClientSupportReady = ETrue; const TInt r = EvaluateOtgConnectFlags(); - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); if (iUsbResetDeferred) // implies (iOtgHnpHandledByHw == ETrue) { __KTRACE_OPT(KUSB, Kern::Printf(" Resetting USB Reset 'defer' flag")); iUsbResetDeferred = EFalse; (void) ProcessResetEvent(EFalse); } - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); #else const TInt r = UdcConnect(); #endif // USB_OTG_CLIENT @@ -743,9 +745,9 @@ __KTRACE_OPT(KUSB, Kern::Printf(" Error: StatusCallback @ 0x%x already registered", &aCallback)); return KErrGeneral; } - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); iStatusCallbacks.AddLast(aCallback); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return KErrNone; } @@ -761,7 +763,7 @@ { __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForStatusChange()")); __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__)); - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); TSglQueIter iter(iStatusCallbacks); TUsbcStatusCallback* p; while ((p = iter++) != NULL) @@ -770,12 +772,12 @@ { __KTRACE_OPT(KUSB, Kern::Printf(" removing StatusCallback @ 0x%x", p)); iStatusCallbacks.Remove(*p); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return KErrNone; } } __KTRACE_OPT(KUSB, Kern::Printf(" client not found")); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return KErrNotFound; } @@ -809,9 +811,9 @@ __KTRACE_OPT(KUSB, Kern::Printf(" Error: EpStatusCallback @ 0x%x already registered", &aCallback)); return KErrGeneral; } - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); iEpStatusCallbacks.AddLast(aCallback); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return KErrNone; } @@ -827,7 +829,7 @@ { __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForEndpointStatusChange()")); __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__)); - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); TSglQueIter iter(iEpStatusCallbacks); TUsbcEndpointStatusCallback* p; while ((p = iter++) != NULL) @@ -836,12 +838,12 @@ { __KTRACE_OPT(KUSB, Kern::Printf(" removing EpStatusCallback @ 0x%x", p)); iEpStatusCallbacks.Remove(*p); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return KErrNone; } } __KTRACE_OPT(KUSB, Kern::Printf(" client not found")); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return KErrNotFound; } @@ -1056,17 +1058,17 @@ } // Ep0 reads don't need to be prepared - there's always one pending __KTRACE_OPT(KUSB, Kern::Printf(" adding RequestCallback @ 0x%x (ep0)", &aCallback)); - TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); iEp0ReadRequestCallbacks.AddLast(aCallback); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); err = KErrNone; if (iEp0_RxExtraData) { __KTRACE_OPT(KUSB, Kern::Printf(" iEp0_RxExtraData: trying again...")); const TBool rx_data = iEp0DataReceiving; - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); err = ProcessEp0ReceiveDone(iEp0_RxExtraCount); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); if (err == KErrNone) { iEp0_RxExtraData = EFalse; @@ -1643,9 +1645,9 @@ __KTRACE_OPT(KUSB, Kern::Printf(" Error: OtgFeatureCallback @ 0x%x already registered", &aCallback)); return KErrAlreadyExists; } - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); iOtgCallbacks.AddLast(aCallback); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return KErrNone; } @@ -1661,7 +1663,7 @@ { __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForOtgFeatureChange()")); __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__)); - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); TSglQueIter iter(iOtgCallbacks); TUsbcOtgFeatureCallback* p; while ((p = iter++) != NULL) @@ -1670,12 +1672,12 @@ { __KTRACE_OPT(KUSB, Kern::Printf(" removing OtgFeatureCallback @ 0x%x", p)); iOtgCallbacks.Remove(*p); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return KErrNone; } } __KTRACE_OPT(KUSB, Kern::Printf(" client not found")); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return KErrNotFound; } @@ -2881,6 +2883,7 @@ iOtgCallbacks(_FOFF(TUsbcOtgFeatureCallback, iLink)), iReconnectTimer(ReconnectTimerCallback, this), iCableStatusTimer(CableStatusTimerCallback, this), + iUsbLock(TSpinLock::EOrderGenericIrqLow3), iPowerUpDfc(PowerUpDfc, this, 3), iPowerDownDfc(PowerDownDfc, this, 3), iStandby(EFalse), @@ -3711,7 +3714,17 @@ __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; } @@ -3730,15 +3743,25 @@ __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); - delete ifc_ptr; + 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; } @@ -3765,7 +3788,7 @@ // Ep0 OUT if (aEndpointNum == 0) { - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); TSglQueIter iter(iEp0ReadRequestCallbacks); TUsbcRequestCallback* p; while ((p = iter++) != NULL) @@ -3778,7 +3801,7 @@ iEp0ReadRequestCallbacks.Remove(*p); } } - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return; } // Other endpoints @@ -3798,7 +3821,7 @@ // aClientId being NULL means: delete all requests for *all* clients. __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteRequestCallbacks()")); // Ep0 OUT - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); TSglQueIter iter(iEp0ReadRequestCallbacks); TUsbcRequestCallback* p; while ((p = iter++) != NULL) @@ -3809,7 +3832,7 @@ iEp0ReadRequestCallbacks.Remove(*p); } } - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); // Other endpoints for (TInt i = 1; i < KUsbcEpArraySize; i++) { @@ -4278,7 +4301,23 @@ // notification in any case, even if no cable and/or host are // connected. The next Reset will get us out of it again. iDeviceStateB4Suspend = iDeviceState; - NextDeviceState(EUsbcDeviceStateSuspended); + // Please pay attention to that the above comment now is not accurate! + // It's not updated according the below modification just for keeping the original comment! + // + // Moving to Suspend state arbitrarily will cause DEFECT EDHO-7Y3AAD. + // DEFECT EDHO-7Y3AAD: Connected to the USB Charger, the UI displayed wrongly connected as default mode + // since the iDeviceState changed wrongly from Undefined to Suspended, and keep + // always Suspended becauseof NO Reset coming next! + // So, to fix this defect, the state change notification is modified to be triggerred by loop the current state again + // if the current state is Undefined! + if (EUsbcDeviceStateUndefined != iDeviceState) + { + NextDeviceState(EUsbcDeviceStateSuspended); + } + else + { + NextDeviceState(iDeviceState); + } r = (*iEnablePullUpOnDPlus)(iOtgContext); if (r != KErrNone) {