178 // (If the hardware is NOT activated at this point, we can only be in |
178 // (If the hardware is NOT activated at this point, we can only be in |
179 // state EUsbcDeviceStateAttached, so we don't have to move to it.) |
179 // state EUsbcDeviceStateAttached, so we don't have to move to it.) |
180 } |
180 } |
181 DeActivateHardwareController(); // turn off UDC altogether |
181 DeActivateHardwareController(); // turn off UDC altogether |
182 iStackIsActive = EFalse; |
182 iStackIsActive = EFalse; |
|
183 // Notify registered clients on the user side about a USB device state |
|
184 // change event and a transition to the "Undefined" state. |
|
185 // Note: the state should be changed to "Undefined" before calling RunClientCallbacks(), |
|
186 // otherwise the "Undefined" state will probably be lost. |
|
187 NextDeviceState(EUsbcDeviceStateUndefined); |
183 // Complete all pending requests, returning KErrDisconnected |
188 // Complete all pending requests, returning KErrDisconnected |
184 RunClientCallbacks(); |
189 RunClientCallbacks(); |
185 // Notify registered clients on the user side about a USB device state |
|
186 // change event and a transition to the "Undefined" state. |
|
187 NextDeviceState(EUsbcDeviceStateUndefined); |
|
188 } |
190 } |
189 |
191 |
190 |
192 |
191 /** To be called by the OTG/Host stack in an OTG setup to enable USB device |
193 /** To be called by the OTG/Host stack in an OTG setup to enable USB device |
192 functionality. |
194 functionality. |
670 { |
672 { |
671 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::UsbConnect()")); |
673 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::UsbConnect()")); |
672 #ifdef USB_OTG_CLIENT |
674 #ifdef USB_OTG_CLIENT |
673 iClientSupportReady = ETrue; |
675 iClientSupportReady = ETrue; |
674 const TInt r = EvaluateOtgConnectFlags(); |
676 const TInt r = EvaluateOtgConnectFlags(); |
675 const TInt irq = NKern::DisableAllInterrupts(); |
677 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
676 if (iUsbResetDeferred) // implies (iOtgHnpHandledByHw == ETrue) |
678 if (iUsbResetDeferred) // implies (iOtgHnpHandledByHw == ETrue) |
677 { |
679 { |
678 __KTRACE_OPT(KUSB, Kern::Printf(" Resetting USB Reset 'defer' flag")); |
680 __KTRACE_OPT(KUSB, Kern::Printf(" Resetting USB Reset 'defer' flag")); |
679 iUsbResetDeferred = EFalse; |
681 iUsbResetDeferred = EFalse; |
680 (void) ProcessResetEvent(EFalse); |
682 (void) ProcessResetEvent(EFalse); |
681 } |
683 } |
682 NKern::RestoreInterrupts(irq); |
684 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
683 #else |
685 #else |
684 const TInt r = UdcConnect(); |
686 const TInt r = UdcConnect(); |
685 #endif // USB_OTG_CLIENT |
687 #endif // USB_OTG_CLIENT |
686 return r; |
688 return r; |
687 } |
689 } |
741 if (IsInTheStatusList(aCallback)) |
743 if (IsInTheStatusList(aCallback)) |
742 { |
744 { |
743 __KTRACE_OPT(KUSB, Kern::Printf(" Error: StatusCallback @ 0x%x already registered", &aCallback)); |
745 __KTRACE_OPT(KUSB, Kern::Printf(" Error: StatusCallback @ 0x%x already registered", &aCallback)); |
744 return KErrGeneral; |
746 return KErrGeneral; |
745 } |
747 } |
746 const TInt irq = NKern::DisableAllInterrupts(); |
748 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
747 iStatusCallbacks.AddLast(aCallback); |
749 iStatusCallbacks.AddLast(aCallback); |
748 NKern::RestoreInterrupts(irq); |
750 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
749 return KErrNone; |
751 return KErrNone; |
750 } |
752 } |
751 |
753 |
752 |
754 |
753 /** De-registers (removes from the list of pending requests) a notification callback for the USB device |
755 /** De-registers (removes from the list of pending requests) a notification callback for the USB device |
759 */ |
761 */ |
760 EXPORT_C TInt DUsbClientController::DeRegisterForStatusChange(const DBase* aClientId) |
762 EXPORT_C TInt DUsbClientController::DeRegisterForStatusChange(const DBase* aClientId) |
761 { |
763 { |
762 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForStatusChange()")); |
764 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForStatusChange()")); |
763 __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
765 __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
764 const TInt irq = NKern::DisableAllInterrupts(); |
766 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
765 TSglQueIter<TUsbcStatusCallback> iter(iStatusCallbacks); |
767 TSglQueIter<TUsbcStatusCallback> iter(iStatusCallbacks); |
766 TUsbcStatusCallback* p; |
768 TUsbcStatusCallback* p; |
767 while ((p = iter++) != NULL) |
769 while ((p = iter++) != NULL) |
768 { |
770 { |
769 if (p->Owner() == aClientId) |
771 if (p->Owner() == aClientId) |
770 { |
772 { |
771 __KTRACE_OPT(KUSB, Kern::Printf(" removing StatusCallback @ 0x%x", p)); |
773 __KTRACE_OPT(KUSB, Kern::Printf(" removing StatusCallback @ 0x%x", p)); |
772 iStatusCallbacks.Remove(*p); |
774 iStatusCallbacks.Remove(*p); |
773 NKern::RestoreInterrupts(irq); |
775 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
774 return KErrNone; |
776 return KErrNone; |
775 } |
777 } |
776 } |
778 } |
777 __KTRACE_OPT(KUSB, Kern::Printf(" client not found")); |
779 __KTRACE_OPT(KUSB, Kern::Printf(" client not found")); |
778 NKern::RestoreInterrupts(irq); |
780 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
779 return KErrNotFound; |
781 return KErrNotFound; |
780 } |
782 } |
781 |
783 |
782 |
784 |
783 /** Registers a notification callback for changes of the state of endpoints. |
785 /** Registers a notification callback for changes of the state of endpoints. |
807 if (IsInTheEpStatusList(aCallback)) |
809 if (IsInTheEpStatusList(aCallback)) |
808 { |
810 { |
809 __KTRACE_OPT(KUSB, Kern::Printf(" Error: EpStatusCallback @ 0x%x already registered", &aCallback)); |
811 __KTRACE_OPT(KUSB, Kern::Printf(" Error: EpStatusCallback @ 0x%x already registered", &aCallback)); |
810 return KErrGeneral; |
812 return KErrGeneral; |
811 } |
813 } |
812 const TInt irq = NKern::DisableAllInterrupts(); |
814 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
813 iEpStatusCallbacks.AddLast(aCallback); |
815 iEpStatusCallbacks.AddLast(aCallback); |
814 NKern::RestoreInterrupts(irq); |
816 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
815 return KErrNone; |
817 return KErrNone; |
816 } |
818 } |
817 |
819 |
818 |
820 |
819 /** De-registers (removes from the list of pending requests) a notification callback for changes of the state |
821 /** De-registers (removes from the list of pending requests) a notification callback for changes of the state |
825 */ |
827 */ |
826 EXPORT_C TInt DUsbClientController::DeRegisterForEndpointStatusChange(const DBase* aClientId) |
828 EXPORT_C TInt DUsbClientController::DeRegisterForEndpointStatusChange(const DBase* aClientId) |
827 { |
829 { |
828 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForEndpointStatusChange()")); |
830 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForEndpointStatusChange()")); |
829 __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
831 __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
830 const TInt irq = NKern::DisableAllInterrupts(); |
832 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
831 TSglQueIter<TUsbcEndpointStatusCallback> iter(iEpStatusCallbacks); |
833 TSglQueIter<TUsbcEndpointStatusCallback> iter(iEpStatusCallbacks); |
832 TUsbcEndpointStatusCallback* p; |
834 TUsbcEndpointStatusCallback* p; |
833 while ((p = iter++) != NULL) |
835 while ((p = iter++) != NULL) |
834 { |
836 { |
835 if (p->Owner() == aClientId) |
837 if (p->Owner() == aClientId) |
836 { |
838 { |
837 __KTRACE_OPT(KUSB, Kern::Printf(" removing EpStatusCallback @ 0x%x", p)); |
839 __KTRACE_OPT(KUSB, Kern::Printf(" removing EpStatusCallback @ 0x%x", p)); |
838 iEpStatusCallbacks.Remove(*p); |
840 iEpStatusCallbacks.Remove(*p); |
839 NKern::RestoreInterrupts(irq); |
841 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
840 return KErrNone; |
842 return KErrNone; |
841 } |
843 } |
842 } |
844 } |
843 __KTRACE_OPT(KUSB, Kern::Printf(" client not found")); |
845 __KTRACE_OPT(KUSB, Kern::Printf(" client not found")); |
844 NKern::RestoreInterrupts(irq); |
846 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
845 return KErrNotFound; |
847 return KErrNotFound; |
846 } |
848 } |
847 |
849 |
848 |
850 |
849 /** Returns the number of the currently active alternate interface setting for this interface. |
851 /** 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)); |
1056 __KTRACE_OPT(KUSB, Kern::Printf(" RequestCallback @ 0x%x already registered", &aCallback)); |
1055 return KErrNone; |
1057 return KErrNone; |
1056 } |
1058 } |
1057 // Ep0 reads don't need to be prepared - there's always one pending |
1059 // 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)); |
1060 __KTRACE_OPT(KUSB, Kern::Printf(" adding RequestCallback @ 0x%x (ep0)", &aCallback)); |
1059 TInt irq = NKern::DisableAllInterrupts(); |
1061 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
1060 iEp0ReadRequestCallbacks.AddLast(aCallback); |
1062 iEp0ReadRequestCallbacks.AddLast(aCallback); |
1061 NKern::RestoreInterrupts(irq); |
1063 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
1062 err = KErrNone; |
1064 err = KErrNone; |
1063 if (iEp0_RxExtraData) |
1065 if (iEp0_RxExtraData) |
1064 { |
1066 { |
1065 __KTRACE_OPT(KUSB, Kern::Printf(" iEp0_RxExtraData: trying again...")); |
1067 __KTRACE_OPT(KUSB, Kern::Printf(" iEp0_RxExtraData: trying again...")); |
1066 const TBool rx_data = iEp0DataReceiving; |
1068 const TBool rx_data = iEp0DataReceiving; |
1067 const TInt irq = NKern::DisableAllInterrupts(); |
1069 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
1068 err = ProcessEp0ReceiveDone(iEp0_RxExtraCount); |
1070 err = ProcessEp0ReceiveDone(iEp0_RxExtraCount); |
1069 NKern::RestoreInterrupts(irq); |
1071 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
1070 if (err == KErrNone) |
1072 if (err == KErrNone) |
1071 { |
1073 { |
1072 iEp0_RxExtraData = EFalse; |
1074 iEp0_RxExtraData = EFalse; |
1073 // Queue a new Ep0 read (because xxxProceed only re-enables the interrupt) |
1075 // Queue a new Ep0 read (because xxxProceed only re-enables the interrupt) |
1074 SetupEndpointZeroRead(); |
1076 SetupEndpointZeroRead(); |
1641 if (IsInTheOtgFeatureList(aCallback)) |
1643 if (IsInTheOtgFeatureList(aCallback)) |
1642 { |
1644 { |
1643 __KTRACE_OPT(KUSB, Kern::Printf(" Error: OtgFeatureCallback @ 0x%x already registered", &aCallback)); |
1645 __KTRACE_OPT(KUSB, Kern::Printf(" Error: OtgFeatureCallback @ 0x%x already registered", &aCallback)); |
1644 return KErrAlreadyExists; |
1646 return KErrAlreadyExists; |
1645 } |
1647 } |
1646 const TInt irq = NKern::DisableAllInterrupts(); |
1648 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
1647 iOtgCallbacks.AddLast(aCallback); |
1649 iOtgCallbacks.AddLast(aCallback); |
1648 NKern::RestoreInterrupts(irq); |
1650 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
1649 return KErrNone; |
1651 return KErrNone; |
1650 } |
1652 } |
1651 |
1653 |
1652 |
1654 |
1653 /** De-registers (removes from the list of pending requests) a notification callback for |
1655 /** De-registers (removes from the list of pending requests) a notification callback for |
1659 */ |
1661 */ |
1660 EXPORT_C TInt DUsbClientController::DeRegisterForOtgFeatureChange(const DBase* aClientId) |
1662 EXPORT_C TInt DUsbClientController::DeRegisterForOtgFeatureChange(const DBase* aClientId) |
1661 { |
1663 { |
1662 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForOtgFeatureChange()")); |
1664 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForOtgFeatureChange()")); |
1663 __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
1665 __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
1664 const TInt irq = NKern::DisableAllInterrupts(); |
1666 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
1665 TSglQueIter<TUsbcOtgFeatureCallback> iter(iOtgCallbacks); |
1667 TSglQueIter<TUsbcOtgFeatureCallback> iter(iOtgCallbacks); |
1666 TUsbcOtgFeatureCallback* p; |
1668 TUsbcOtgFeatureCallback* p; |
1667 while ((p = iter++) != NULL) |
1669 while ((p = iter++) != NULL) |
1668 { |
1670 { |
1669 if (!aClientId || p->Owner() == aClientId) |
1671 if (!aClientId || p->Owner() == aClientId) |
1670 { |
1672 { |
1671 __KTRACE_OPT(KUSB, Kern::Printf(" removing OtgFeatureCallback @ 0x%x", p)); |
1673 __KTRACE_OPT(KUSB, Kern::Printf(" removing OtgFeatureCallback @ 0x%x", p)); |
1672 iOtgCallbacks.Remove(*p); |
1674 iOtgCallbacks.Remove(*p); |
1673 NKern::RestoreInterrupts(irq); |
1675 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
1674 return KErrNone; |
1676 return KErrNone; |
1675 } |
1677 } |
1676 } |
1678 } |
1677 __KTRACE_OPT(KUSB, Kern::Printf(" client not found")); |
1679 __KTRACE_OPT(KUSB, Kern::Printf(" client not found")); |
1678 NKern::RestoreInterrupts(irq); |
1680 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
1679 return KErrNotFound; |
1681 return KErrNotFound; |
1680 } |
1682 } |
1681 |
1683 |
1682 |
1684 |
1683 /** Returns a specific standard USB interface descriptor. |
1685 /** Returns a specific standard USB interface descriptor. |
2879 iStatusCallbacks(_FOFF(TUsbcStatusCallback, iLink)), |
2881 iStatusCallbacks(_FOFF(TUsbcStatusCallback, iLink)), |
2880 iEpStatusCallbacks(_FOFF(TUsbcEndpointStatusCallback, iLink)), |
2882 iEpStatusCallbacks(_FOFF(TUsbcEndpointStatusCallback, iLink)), |
2881 iOtgCallbacks(_FOFF(TUsbcOtgFeatureCallback, iLink)), |
2883 iOtgCallbacks(_FOFF(TUsbcOtgFeatureCallback, iLink)), |
2882 iReconnectTimer(ReconnectTimerCallback, this), |
2884 iReconnectTimer(ReconnectTimerCallback, this), |
2883 iCableStatusTimer(CableStatusTimerCallback, this), |
2885 iCableStatusTimer(CableStatusTimerCallback, this), |
|
2886 iUsbLock(TSpinLock::EOrderGenericIrqLow3), |
2884 iPowerUpDfc(PowerUpDfc, this, 3), |
2887 iPowerUpDfc(PowerUpDfc, this, 3), |
2885 iPowerDownDfc(PowerDownDfc, this, 3), |
2888 iPowerDownDfc(PowerDownDfc, this, 3), |
2886 iStandby(EFalse), |
2889 iStandby(EFalse), |
2887 #ifdef USB_OTG_CLIENT |
2890 #ifdef USB_OTG_CLIENT |
2888 // In the OTG case the device starts out disabled |
2891 // In the OTG case the device starts out disabled |
3709 if (idx == KErrNotFound) |
3712 if (idx == KErrNotFound) |
3710 { |
3713 { |
3711 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: interface not found in array")); |
3714 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: interface not found in array")); |
3712 return; |
3715 return; |
3713 } |
3716 } |
|
3717 //Add this mutex to protect the interface set data structure |
|
3718 if (NKern::CurrentContext() == EThread) |
|
3719 { |
|
3720 NKern::FMWait(&iMutex); |
|
3721 } |
|
3722 |
3714 iConfigs[0]->iInterfaceSets.Remove(idx); |
3723 iConfigs[0]->iInterfaceSets.Remove(idx); |
|
3724 if (NKern::CurrentContext() == EThread) |
|
3725 { |
|
3726 NKern::FMSignal(&iMutex); |
|
3727 } |
3715 delete ifcset_ptr; |
3728 delete ifcset_ptr; |
3716 } |
3729 } |
3717 |
3730 |
3718 |
3731 |
3719 void DUsbClientController::DeleteInterface(TInt aIfcSet, TInt aIfc) |
3732 void DUsbClientController::DeleteInterface(TInt aIfcSet, TInt aIfc) |
3728 if (ifcset_ptr->iInterfaces.Count() <= aIfc) |
3741 if (ifcset_ptr->iInterfaces.Count() <= aIfc) |
3729 { |
3742 { |
3730 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: invalid interface setting: %d", aIfc)); |
3743 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: invalid interface setting: %d", aIfc)); |
3731 return; |
3744 return; |
3732 } |
3745 } |
|
3746 //Add this mutex to protect the interface set data structure |
|
3747 if (NKern::CurrentContext() == EThread) |
|
3748 { |
|
3749 NKern::FMWait(&iMutex); |
|
3750 } |
3733 TUsbcInterface* const ifc_ptr = ifcset_ptr->iInterfaces[aIfc]; |
3751 TUsbcInterface* const ifc_ptr = ifcset_ptr->iInterfaces[aIfc]; |
3734 // Always first remove, then delete (see ~TUsbcLogicalEndpoint() for the reason why) |
3752 // Always first remove, then delete (see ~TUsbcLogicalEndpoint() for the reason why) |
3735 ifcset_ptr->iInterfaces.Remove(aIfc); |
3753 ifcset_ptr->iInterfaces.Remove(aIfc); |
3736 delete ifc_ptr; |
3754 |
3737 if (aIfc == ifcset_ptr->iCurrentInterface) |
3755 if (aIfc == ifcset_ptr->iCurrentInterface) |
3738 { |
3756 { |
3739 __KTRACE_OPT(KUSB, Kern::Printf(" > Warning: deleting current interface setting")); |
3757 __KTRACE_OPT(KUSB, Kern::Printf(" > Warning: deleting current interface setting")); |
3740 ifcset_ptr->iCurrentInterface = 0; |
3758 ifcset_ptr->iCurrentInterface = 0; |
3741 } |
3759 } |
|
3760 if (NKern::CurrentContext() == EThread) |
|
3761 { |
|
3762 NKern::FMSignal(&iMutex); |
|
3763 } |
|
3764 delete ifc_ptr; |
3742 } |
3765 } |
3743 |
3766 |
3744 |
3767 |
3745 void DUsbClientController::CancelTransferRequests(TInt aRealEndpoint) |
3768 void DUsbClientController::CancelTransferRequests(TInt aRealEndpoint) |
3746 { |
3769 { |
3763 { |
3786 { |
3764 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteRequestCallback()")); |
3787 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteRequestCallback()")); |
3765 // Ep0 OUT |
3788 // Ep0 OUT |
3766 if (aEndpointNum == 0) |
3789 if (aEndpointNum == 0) |
3767 { |
3790 { |
3768 const TInt irq = NKern::DisableAllInterrupts(); |
3791 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
3769 TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks); |
3792 TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks); |
3770 TUsbcRequestCallback* p; |
3793 TUsbcRequestCallback* p; |
3771 while ((p = iter++) != NULL) |
3794 while ((p = iter++) != NULL) |
3772 { |
3795 { |
3773 if (p->Owner() == aClientId) |
3796 if (p->Owner() == aClientId) |
3776 __ASSERT_DEBUG((p->iTransferDir == EControllerRead), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
3799 __ASSERT_DEBUG((p->iTransferDir == EControllerRead), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
3777 __KTRACE_OPT(KUSB, Kern::Printf(" removing RequestCallback @ 0x%x (ep0)", p)); |
3800 __KTRACE_OPT(KUSB, Kern::Printf(" removing RequestCallback @ 0x%x (ep0)", p)); |
3778 iEp0ReadRequestCallbacks.Remove(*p); |
3801 iEp0ReadRequestCallbacks.Remove(*p); |
3779 } |
3802 } |
3780 } |
3803 } |
3781 NKern::RestoreInterrupts(irq); |
3804 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
3782 return; |
3805 return; |
3783 } |
3806 } |
3784 // Other endpoints |
3807 // Other endpoints |
3785 TUsbcRequestCallback* const p = iRequestCallbacks[aEndpointNum]; |
3808 TUsbcRequestCallback* const p = iRequestCallbacks[aEndpointNum]; |
3786 if (p) |
3809 if (p) |
3796 void DUsbClientController::DeleteRequestCallbacks(const DBase* aClientId) |
3819 void DUsbClientController::DeleteRequestCallbacks(const DBase* aClientId) |
3797 { |
3820 { |
3798 // aClientId being NULL means: delete all requests for *all* clients. |
3821 // aClientId being NULL means: delete all requests for *all* clients. |
3799 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteRequestCallbacks()")); |
3822 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteRequestCallbacks()")); |
3800 // Ep0 OUT |
3823 // Ep0 OUT |
3801 const TInt irq = NKern::DisableAllInterrupts(); |
3824 const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); |
3802 TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks); |
3825 TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks); |
3803 TUsbcRequestCallback* p; |
3826 TUsbcRequestCallback* p; |
3804 while ((p = iter++) != NULL) |
3827 while ((p = iter++) != NULL) |
3805 { |
3828 { |
3806 if (!aClientId || p->Owner() == aClientId) |
3829 if (!aClientId || p->Owner() == aClientId) |
3807 { |
3830 { |
3808 __KTRACE_OPT(KUSB, Kern::Printf(" removing RequestCallback @ 0x%x (ep0)", p)); |
3831 __KTRACE_OPT(KUSB, Kern::Printf(" removing RequestCallback @ 0x%x (ep0)", p)); |
3809 iEp0ReadRequestCallbacks.Remove(*p); |
3832 iEp0ReadRequestCallbacks.Remove(*p); |
3810 } |
3833 } |
3811 } |
3834 } |
3812 NKern::RestoreInterrupts(irq); |
3835 __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); |
3813 // Other endpoints |
3836 // Other endpoints |
3814 for (TInt i = 1; i < KUsbcEpArraySize; i++) |
3837 for (TInt i = 1; i < KUsbcEpArraySize; i++) |
3815 { |
3838 { |
3816 TUsbcRequestCallback* const p = iRequestCallbacks[i]; |
3839 TUsbcRequestCallback* const p = iRequestCallbacks[i]; |
3817 if (p && (!aClientId || p->Owner() == aClientId)) |
3840 if (p && (!aClientId || p->Owner() == aClientId)) |
4276 iDPlusEnabled = enableDPlus; |
4299 iDPlusEnabled = enableDPlus; |
4277 // First we move to Suspend state to trigger a state change |
4300 // First we move to Suspend state to trigger a state change |
4278 // notification in any case, even if no cable and/or host are |
4301 // notification in any case, even if no cable and/or host are |
4279 // connected. The next Reset will get us out of it again. |
4302 // connected. The next Reset will get us out of it again. |
4280 iDeviceStateB4Suspend = iDeviceState; |
4303 iDeviceStateB4Suspend = iDeviceState; |
4281 NextDeviceState(EUsbcDeviceStateSuspended); |
4304 // Please pay attention to that the above comment now is not accurate! |
|
4305 // It's not updated according the below modification just for keeping the original comment! |
|
4306 // |
|
4307 // Moving to Suspend state arbitrarily will cause DEFECT EDHO-7Y3AAD. |
|
4308 // DEFECT EDHO-7Y3AAD: Connected to the USB Charger, the UI displayed wrongly connected as default mode |
|
4309 // since the iDeviceState changed wrongly from Undefined to Suspended, and keep |
|
4310 // always Suspended becauseof NO Reset coming next! |
|
4311 // So, to fix this defect, the state change notification is modified to be triggerred by loop the current state again |
|
4312 // if the current state is Undefined! |
|
4313 if (EUsbcDeviceStateUndefined != iDeviceState) |
|
4314 { |
|
4315 NextDeviceState(EUsbcDeviceStateSuspended); |
|
4316 } |
|
4317 else |
|
4318 { |
|
4319 NextDeviceState(iDeviceState); |
|
4320 } |
4282 r = (*iEnablePullUpOnDPlus)(iOtgContext); |
4321 r = (*iEnablePullUpOnDPlus)(iOtgContext); |
4283 if (r != KErrNone) |
4322 if (r != KErrNone) |
4284 { |
4323 { |
4285 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: iEnablePullUpOnDPlus() = %d", r)); |
4324 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: iEnablePullUpOnDPlus() = %d", r)); |
4286 } |
4325 } |