670 { |
670 { |
671 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::UsbConnect()")); |
671 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::UsbConnect()")); |
672 #ifdef USB_OTG_CLIENT |
672 #ifdef USB_OTG_CLIENT |
673 iClientSupportReady = ETrue; |
673 iClientSupportReady = ETrue; |
674 const TInt r = EvaluateOtgConnectFlags(); |
674 const TInt r = EvaluateOtgConnectFlags(); |
675 const TInt irq = NKern::DisableAllInterrupts(); |
675 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
676 if (iUsbResetDeferred) // implies (iOtgHnpHandledByHw == ETrue) |
676 if (iUsbResetDeferred) // implies (iOtgHnpHandledByHw == ETrue) |
677 { |
677 { |
678 __KTRACE_OPT(KUSB, Kern::Printf(" Resetting USB Reset 'defer' flag")); |
678 __KTRACE_OPT(KUSB, Kern::Printf(" Resetting USB Reset 'defer' flag")); |
679 iUsbResetDeferred = EFalse; |
679 iUsbResetDeferred = EFalse; |
680 (void) ProcessResetEvent(EFalse); |
680 (void) ProcessResetEvent(EFalse); |
681 } |
681 } |
682 NKern::RestoreInterrupts(irq); |
682 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
683 #else |
683 #else |
684 const TInt r = UdcConnect(); |
684 const TInt r = UdcConnect(); |
685 #endif // USB_OTG_CLIENT |
685 #endif // USB_OTG_CLIENT |
686 return r; |
686 return r; |
687 } |
687 } |
741 if (IsInTheStatusList(aCallback)) |
741 if (IsInTheStatusList(aCallback)) |
742 { |
742 { |
743 __KTRACE_OPT(KUSB, Kern::Printf(" Error: StatusCallback @ 0x%x already registered", &aCallback)); |
743 __KTRACE_OPT(KUSB, Kern::Printf(" Error: StatusCallback @ 0x%x already registered", &aCallback)); |
744 return KErrGeneral; |
744 return KErrGeneral; |
745 } |
745 } |
746 const TInt irq = NKern::DisableAllInterrupts(); |
746 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
747 iStatusCallbacks.AddLast(aCallback); |
747 iStatusCallbacks.AddLast(aCallback); |
748 NKern::RestoreInterrupts(irq); |
748 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
749 return KErrNone; |
749 return KErrNone; |
750 } |
750 } |
751 |
751 |
752 |
752 |
753 /** De-registers (removes from the list of pending requests) a notification callback for the USB device |
753 /** De-registers (removes from the list of pending requests) a notification callback for the USB device |
759 */ |
759 */ |
760 EXPORT_C TInt DUsbClientController::DeRegisterForStatusChange(const DBase* aClientId) |
760 EXPORT_C TInt DUsbClientController::DeRegisterForStatusChange(const DBase* aClientId) |
761 { |
761 { |
762 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForStatusChange()")); |
762 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForStatusChange()")); |
763 __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
763 __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
764 const TInt irq = NKern::DisableAllInterrupts(); |
764 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
765 TSglQueIter<TUsbcStatusCallback> iter(iStatusCallbacks); |
765 TSglQueIter<TUsbcStatusCallback> iter(iStatusCallbacks); |
766 TUsbcStatusCallback* p; |
766 TUsbcStatusCallback* p; |
767 while ((p = iter++) != NULL) |
767 while ((p = iter++) != NULL) |
768 { |
768 { |
769 if (p->Owner() == aClientId) |
769 if (p->Owner() == aClientId) |
770 { |
770 { |
771 __KTRACE_OPT(KUSB, Kern::Printf(" removing StatusCallback @ 0x%x", p)); |
771 __KTRACE_OPT(KUSB, Kern::Printf(" removing StatusCallback @ 0x%x", p)); |
772 iStatusCallbacks.Remove(*p); |
772 iStatusCallbacks.Remove(*p); |
773 NKern::RestoreInterrupts(irq); |
773 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
774 return KErrNone; |
774 return KErrNone; |
775 } |
775 } |
776 } |
776 } |
777 __KTRACE_OPT(KUSB, Kern::Printf(" client not found")); |
777 __KTRACE_OPT(KUSB, Kern::Printf(" client not found")); |
778 NKern::RestoreInterrupts(irq); |
778 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
779 return KErrNotFound; |
779 return KErrNotFound; |
780 } |
780 } |
781 |
781 |
782 |
782 |
783 /** Registers a notification callback for changes of the state of endpoints. |
783 /** Registers a notification callback for changes of the state of endpoints. |
807 if (IsInTheEpStatusList(aCallback)) |
807 if (IsInTheEpStatusList(aCallback)) |
808 { |
808 { |
809 __KTRACE_OPT(KUSB, Kern::Printf(" Error: EpStatusCallback @ 0x%x already registered", &aCallback)); |
809 __KTRACE_OPT(KUSB, Kern::Printf(" Error: EpStatusCallback @ 0x%x already registered", &aCallback)); |
810 return KErrGeneral; |
810 return KErrGeneral; |
811 } |
811 } |
812 const TInt irq = NKern::DisableAllInterrupts(); |
812 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
813 iEpStatusCallbacks.AddLast(aCallback); |
813 iEpStatusCallbacks.AddLast(aCallback); |
814 NKern::RestoreInterrupts(irq); |
814 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
815 return KErrNone; |
815 return KErrNone; |
816 } |
816 } |
817 |
817 |
818 |
818 |
819 /** De-registers (removes from the list of pending requests) a notification callback for changes of the state |
819 /** De-registers (removes from the list of pending requests) a notification callback for changes of the state |
825 */ |
825 */ |
826 EXPORT_C TInt DUsbClientController::DeRegisterForEndpointStatusChange(const DBase* aClientId) |
826 EXPORT_C TInt DUsbClientController::DeRegisterForEndpointStatusChange(const DBase* aClientId) |
827 { |
827 { |
828 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForEndpointStatusChange()")); |
828 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForEndpointStatusChange()")); |
829 __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
829 __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
830 const TInt irq = NKern::DisableAllInterrupts(); |
830 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
831 TSglQueIter<TUsbcEndpointStatusCallback> iter(iEpStatusCallbacks); |
831 TSglQueIter<TUsbcEndpointStatusCallback> iter(iEpStatusCallbacks); |
832 TUsbcEndpointStatusCallback* p; |
832 TUsbcEndpointStatusCallback* p; |
833 while ((p = iter++) != NULL) |
833 while ((p = iter++) != NULL) |
834 { |
834 { |
835 if (p->Owner() == aClientId) |
835 if (p->Owner() == aClientId) |
836 { |
836 { |
837 __KTRACE_OPT(KUSB, Kern::Printf(" removing EpStatusCallback @ 0x%x", p)); |
837 __KTRACE_OPT(KUSB, Kern::Printf(" removing EpStatusCallback @ 0x%x", p)); |
838 iEpStatusCallbacks.Remove(*p); |
838 iEpStatusCallbacks.Remove(*p); |
839 NKern::RestoreInterrupts(irq); |
839 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
840 return KErrNone; |
840 return KErrNone; |
841 } |
841 } |
842 } |
842 } |
843 __KTRACE_OPT(KUSB, Kern::Printf(" client not found")); |
843 __KTRACE_OPT(KUSB, Kern::Printf(" client not found")); |
844 NKern::RestoreInterrupts(irq); |
844 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
845 return KErrNotFound; |
845 return KErrNotFound; |
846 } |
846 } |
847 |
847 |
848 |
848 |
849 /** Returns the number of the currently active alternate interface setting for this interface. |
849 /** Returns the number of the currently active alternate interface setting for this interface. |
1054 __KTRACE_OPT(KUSB, Kern::Printf(" RequestCallback @ 0x%x already registered", &aCallback)); |
1054 __KTRACE_OPT(KUSB, Kern::Printf(" RequestCallback @ 0x%x already registered", &aCallback)); |
1055 return KErrNone; |
1055 return KErrNone; |
1056 } |
1056 } |
1057 // Ep0 reads don't need to be prepared - there's always one pending |
1057 // Ep0 reads don't need to be prepared - there's always one pending |
1058 __KTRACE_OPT(KUSB, Kern::Printf(" adding RequestCallback @ 0x%x (ep0)", &aCallback)); |
1058 __KTRACE_OPT(KUSB, Kern::Printf(" adding RequestCallback @ 0x%x (ep0)", &aCallback)); |
1059 TInt irq = NKern::DisableAllInterrupts(); |
1059 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
1060 iEp0ReadRequestCallbacks.AddLast(aCallback); |
1060 iEp0ReadRequestCallbacks.AddLast(aCallback); |
1061 NKern::RestoreInterrupts(irq); |
1061 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
1062 err = KErrNone; |
1062 err = KErrNone; |
1063 if (iEp0_RxExtraData) |
1063 if (iEp0_RxExtraData) |
1064 { |
1064 { |
1065 __KTRACE_OPT(KUSB, Kern::Printf(" iEp0_RxExtraData: trying again...")); |
1065 __KTRACE_OPT(KUSB, Kern::Printf(" iEp0_RxExtraData: trying again...")); |
1066 const TBool rx_data = iEp0DataReceiving; |
1066 const TBool rx_data = iEp0DataReceiving; |
1067 const TInt irq = NKern::DisableAllInterrupts(); |
1067 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
1068 err = ProcessEp0ReceiveDone(iEp0_RxExtraCount); |
1068 err = ProcessEp0ReceiveDone(iEp0_RxExtraCount); |
1069 NKern::RestoreInterrupts(irq); |
1069 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
1070 if (err == KErrNone) |
1070 if (err == KErrNone) |
1071 { |
1071 { |
1072 iEp0_RxExtraData = EFalse; |
1072 iEp0_RxExtraData = EFalse; |
1073 // Queue a new Ep0 read (because xxxProceed only re-enables the interrupt) |
1073 // Queue a new Ep0 read (because xxxProceed only re-enables the interrupt) |
1074 SetupEndpointZeroRead(); |
1074 SetupEndpointZeroRead(); |
1641 if (IsInTheOtgFeatureList(aCallback)) |
1641 if (IsInTheOtgFeatureList(aCallback)) |
1642 { |
1642 { |
1643 __KTRACE_OPT(KUSB, Kern::Printf(" Error: OtgFeatureCallback @ 0x%x already registered", &aCallback)); |
1643 __KTRACE_OPT(KUSB, Kern::Printf(" Error: OtgFeatureCallback @ 0x%x already registered", &aCallback)); |
1644 return KErrAlreadyExists; |
1644 return KErrAlreadyExists; |
1645 } |
1645 } |
1646 const TInt irq = NKern::DisableAllInterrupts(); |
1646 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
1647 iOtgCallbacks.AddLast(aCallback); |
1647 iOtgCallbacks.AddLast(aCallback); |
1648 NKern::RestoreInterrupts(irq); |
1648 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
1649 return KErrNone; |
1649 return KErrNone; |
1650 } |
1650 } |
1651 |
1651 |
1652 |
1652 |
1653 /** De-registers (removes from the list of pending requests) a notification callback for |
1653 /** De-registers (removes from the list of pending requests) a notification callback for |
1659 */ |
1659 */ |
1660 EXPORT_C TInt DUsbClientController::DeRegisterForOtgFeatureChange(const DBase* aClientId) |
1660 EXPORT_C TInt DUsbClientController::DeRegisterForOtgFeatureChange(const DBase* aClientId) |
1661 { |
1661 { |
1662 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForOtgFeatureChange()")); |
1662 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForOtgFeatureChange()")); |
1663 __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
1663 __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
1664 const TInt irq = NKern::DisableAllInterrupts(); |
1664 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
1665 TSglQueIter<TUsbcOtgFeatureCallback> iter(iOtgCallbacks); |
1665 TSglQueIter<TUsbcOtgFeatureCallback> iter(iOtgCallbacks); |
1666 TUsbcOtgFeatureCallback* p; |
1666 TUsbcOtgFeatureCallback* p; |
1667 while ((p = iter++) != NULL) |
1667 while ((p = iter++) != NULL) |
1668 { |
1668 { |
1669 if (!aClientId || p->Owner() == aClientId) |
1669 if (!aClientId || p->Owner() == aClientId) |
1670 { |
1670 { |
1671 __KTRACE_OPT(KUSB, Kern::Printf(" removing OtgFeatureCallback @ 0x%x", p)); |
1671 __KTRACE_OPT(KUSB, Kern::Printf(" removing OtgFeatureCallback @ 0x%x", p)); |
1672 iOtgCallbacks.Remove(*p); |
1672 iOtgCallbacks.Remove(*p); |
1673 NKern::RestoreInterrupts(irq); |
1673 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
1674 return KErrNone; |
1674 return KErrNone; |
1675 } |
1675 } |
1676 } |
1676 } |
1677 __KTRACE_OPT(KUSB, Kern::Printf(" client not found")); |
1677 __KTRACE_OPT(KUSB, Kern::Printf(" client not found")); |
1678 NKern::RestoreInterrupts(irq); |
1678 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
1679 return KErrNotFound; |
1679 return KErrNotFound; |
1680 } |
1680 } |
1681 |
1681 |
1682 |
1682 |
1683 /** Returns a specific standard USB interface descriptor. |
1683 /** Returns a specific standard USB interface descriptor. |
2879 iStatusCallbacks(_FOFF(TUsbcStatusCallback, iLink)), |
2879 iStatusCallbacks(_FOFF(TUsbcStatusCallback, iLink)), |
2880 iEpStatusCallbacks(_FOFF(TUsbcEndpointStatusCallback, iLink)), |
2880 iEpStatusCallbacks(_FOFF(TUsbcEndpointStatusCallback, iLink)), |
2881 iOtgCallbacks(_FOFF(TUsbcOtgFeatureCallback, iLink)), |
2881 iOtgCallbacks(_FOFF(TUsbcOtgFeatureCallback, iLink)), |
2882 iReconnectTimer(ReconnectTimerCallback, this), |
2882 iReconnectTimer(ReconnectTimerCallback, this), |
2883 iCableStatusTimer(CableStatusTimerCallback, this), |
2883 iCableStatusTimer(CableStatusTimerCallback, this), |
|
2884 iUsbLock(TSpinLock::EOrderGenericIrqLow3), |
2884 iPowerUpDfc(PowerUpDfc, this, 3), |
2885 iPowerUpDfc(PowerUpDfc, this, 3), |
2885 iPowerDownDfc(PowerDownDfc, this, 3), |
2886 iPowerDownDfc(PowerDownDfc, this, 3), |
2886 iStandby(EFalse), |
2887 iStandby(EFalse), |
2887 #ifdef USB_OTG_CLIENT |
2888 #ifdef USB_OTG_CLIENT |
2888 // In the OTG case the device starts out disabled |
2889 // In the OTG case the device starts out disabled |
3763 { |
3764 { |
3764 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteRequestCallback()")); |
3765 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteRequestCallback()")); |
3765 // Ep0 OUT |
3766 // Ep0 OUT |
3766 if (aEndpointNum == 0) |
3767 if (aEndpointNum == 0) |
3767 { |
3768 { |
3768 const TInt irq = NKern::DisableAllInterrupts(); |
3769 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
3769 TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks); |
3770 TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks); |
3770 TUsbcRequestCallback* p; |
3771 TUsbcRequestCallback* p; |
3771 while ((p = iter++) != NULL) |
3772 while ((p = iter++) != NULL) |
3772 { |
3773 { |
3773 if (p->Owner() == aClientId) |
3774 if (p->Owner() == aClientId) |
3776 __ASSERT_DEBUG((p->iTransferDir == EControllerRead), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
3777 __ASSERT_DEBUG((p->iTransferDir == EControllerRead), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
3777 __KTRACE_OPT(KUSB, Kern::Printf(" removing RequestCallback @ 0x%x (ep0)", p)); |
3778 __KTRACE_OPT(KUSB, Kern::Printf(" removing RequestCallback @ 0x%x (ep0)", p)); |
3778 iEp0ReadRequestCallbacks.Remove(*p); |
3779 iEp0ReadRequestCallbacks.Remove(*p); |
3779 } |
3780 } |
3780 } |
3781 } |
3781 NKern::RestoreInterrupts(irq); |
3782 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
3782 return; |
3783 return; |
3783 } |
3784 } |
3784 // Other endpoints |
3785 // Other endpoints |
3785 TUsbcRequestCallback* const p = iRequestCallbacks[aEndpointNum]; |
3786 TUsbcRequestCallback* const p = iRequestCallbacks[aEndpointNum]; |
3786 if (p) |
3787 if (p) |
3796 void DUsbClientController::DeleteRequestCallbacks(const DBase* aClientId) |
3797 void DUsbClientController::DeleteRequestCallbacks(const DBase* aClientId) |
3797 { |
3798 { |
3798 // aClientId being NULL means: delete all requests for *all* clients. |
3799 // aClientId being NULL means: delete all requests for *all* clients. |
3799 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteRequestCallbacks()")); |
3800 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteRequestCallbacks()")); |
3800 // Ep0 OUT |
3801 // Ep0 OUT |
3801 const TInt irq = NKern::DisableAllInterrupts(); |
3802 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
3802 TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks); |
3803 TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks); |
3803 TUsbcRequestCallback* p; |
3804 TUsbcRequestCallback* p; |
3804 while ((p = iter++) != NULL) |
3805 while ((p = iter++) != NULL) |
3805 { |
3806 { |
3806 if (!aClientId || p->Owner() == aClientId) |
3807 if (!aClientId || p->Owner() == aClientId) |
3807 { |
3808 { |
3808 __KTRACE_OPT(KUSB, Kern::Printf(" removing RequestCallback @ 0x%x (ep0)", p)); |
3809 __KTRACE_OPT(KUSB, Kern::Printf(" removing RequestCallback @ 0x%x (ep0)", p)); |
3809 iEp0ReadRequestCallbacks.Remove(*p); |
3810 iEp0ReadRequestCallbacks.Remove(*p); |
3810 } |
3811 } |
3811 } |
3812 } |
3812 NKern::RestoreInterrupts(irq); |
3813 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
3813 // Other endpoints |
3814 // Other endpoints |
3814 for (TInt i = 1; i < KUsbcEpArraySize; i++) |
3815 for (TInt i = 1; i < KUsbcEpArraySize; i++) |
3815 { |
3816 { |
3816 TUsbcRequestCallback* const p = iRequestCallbacks[i]; |
3817 TUsbcRequestCallback* const p = iRequestCallbacks[i]; |
3817 if (p && (!aClientId || p->Owner() == aClientId)) |
3818 if (p && (!aClientId || p->Owner() == aClientId)) |
4276 iDPlusEnabled = enableDPlus; |
4277 iDPlusEnabled = enableDPlus; |
4277 // First we move to Suspend state to trigger a state change |
4278 // First we move to Suspend state to trigger a state change |
4278 // notification in any case, even if no cable and/or host are |
4279 // notification in any case, even if no cable and/or host are |
4279 // connected. The next Reset will get us out of it again. |
4280 // connected. The next Reset will get us out of it again. |
4280 iDeviceStateB4Suspend = iDeviceState; |
4281 iDeviceStateB4Suspend = iDeviceState; |
4281 NextDeviceState(EUsbcDeviceStateSuspended); |
4282 // Please pay attention to that the above comment now is not accurate! |
|
4283 // It's not updated according the below modification just for keeping the original comment! |
|
4284 // |
|
4285 // Moving to Suspend state arbitrarily will cause DEFECT EDHO-7Y3AAD. |
|
4286 // DEFECT EDHO-7Y3AAD: Connected to the USB Charger, the UI displayed wrongly connected as default mode |
|
4287 // since the iDeviceState changed wrongly from Undefined to Suspended, and keep |
|
4288 // always Suspended becauseof NO Reset coming next! |
|
4289 // So, to fix this defect, the state change notification is modified to be triggerred by loop the current state again |
|
4290 // if the current state is Undefined! |
|
4291 if (EUsbcDeviceStateUndefined != iDeviceState) |
|
4292 { |
|
4293 NextDeviceState(EUsbcDeviceStateSuspended); |
|
4294 } |
|
4295 else |
|
4296 { |
|
4297 NextDeviceState(iDeviceState); |
|
4298 } |
4282 r = (*iEnablePullUpOnDPlus)(iOtgContext); |
4299 r = (*iEnablePullUpOnDPlus)(iOtgContext); |
4283 if (r != KErrNone) |
4300 if (r != KErrNone) |
4284 { |
4301 { |
4285 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: iEnablePullUpOnDPlus() = %d", r)); |
4302 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: iEnablePullUpOnDPlus() = %d", r)); |
4286 } |
4303 } |