internal SwitchModeViewModel(PhoneNotifierViewModel PhoneNotifier, PhoneInterfaces?TargetMode, ModeSwitchProgressHandler ModeSwitchProgress, ModeSwitchErrorHandler ModeSwitchError, ModeSwitchSuccessHandler ModeSwitchSuccess, SetWorkingStatus SetWorkingStatus = null, UpdateWorkingStatus UpdateWorkingStatus = null) : base() { if ((PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) && (TargetMode == PhoneInterfaces.Lumia_Flash)) { PhoneInfo Info = ((NokiaFlashModel)PhoneNotifier.CurrentModel).ReadPhoneInfo(false); if (Info.BootManagerProtocolVersionMajor >= 2) { try { // The implementation of SwitchToFlashAppContext() is improved // SwitchToFlashAppContext() should only be used with BootMgr v2 // For switching from BootMgr to FlashApp, it will use NOKS // That will switch to a charging state, whereas a normal context switch will not start charging // The implementation of NOKS in BootMgr mode has changed in BootMgr v2 // It does not disconnect / reconnect anymore and the apptype is changed immediately // NOKS still doesnt return a status // BootMgr v1 uses normal NOKS and waits for arrival of FlashApp ((NokiaFlashModel)PhoneNotifier.CurrentModel).SwitchToFlashAppContext(); // But this was called as a real switch, so we will raise an arrival event. PhoneNotifier.CurrentInterface = PhoneInterfaces.Lumia_Flash; PhoneNotifier.NotifyArrival(); } catch { } } } if (PhoneNotifier.CurrentInterface == TargetMode) { ModeSwitchSuccess(PhoneNotifier.CurrentModel, (PhoneInterfaces)PhoneNotifier.CurrentInterface); } else { this.PhoneNotifier = PhoneNotifier; this.CurrentModel = (NokiaPhoneModel)PhoneNotifier.CurrentModel; this.CurrentMode = PhoneNotifier.CurrentInterface; this.TargetMode = TargetMode; if (ModeSwitchProgress != null) { this.ModeSwitchProgress += ModeSwitchProgress; } if (ModeSwitchError != null) { this.ModeSwitchError += ModeSwitchError; } if (ModeSwitchSuccess != null) { this.ModeSwitchSuccess += ModeSwitchSuccess; } if (SetWorkingStatus != null) { this.SetWorkingStatus = SetWorkingStatus; } if (UpdateWorkingStatus != null) { this.UpdateWorkingStatus = UpdateWorkingStatus; } if (this.CurrentMode == null) { LogFile.Log("Waiting for phone to connect...", LogType.FileAndConsole); PhoneNotifier.NewDeviceArrived += NewDeviceArrived; } else { // Make sure this ViewModel has its View loaded before we continue, // or else loading of Views can get mixed up. if (SynchronizationContext.Current == null) { StartSwitch(); } else { SynchronizationContext.Current.Post((s) => { ((SwitchModeViewModel)s).StartSwitch(); }, this); } } } }
private void NewDeviceArrived(ArrivalEventArgs Args) { PhoneNotifier.NewDeviceArrived -= NewDeviceArrived; CurrentModel = (IDisposable)Args.NewModel; CurrentMode = Args.NewInterface; if ((CurrentMode == PhoneInterfaces.Lumia_Bootloader) && (TargetMode == PhoneInterfaces.Lumia_Flash)) { try { // Going from BootMgr to FlashApp // SwitchToFlashAppContext() will only switch context. Phone will not charge. // ResetPhoneToFlashMode() reboots to real flash app. Phone will charge. Works when in BootMgrApp, not when already in FlashApp. ((NokiaFlashModel)CurrentModel).ResetPhoneToFlashMode(); CurrentMode = PhoneInterfaces.Lumia_Flash; PhoneNotifier.NotifyArrival(); } catch { } } if (CurrentMode == TargetMode) { if (TargetMode == PhoneInterfaces.Lumia_Bootloader) { ((NokiaFlashModel)CurrentModel).DisableRebootTimeOut(); } ModeSwitchSuccessWrapper(); } else if (!IsSwitching) { StartSwitch(); } else if ((CurrentMode == PhoneInterfaces.Lumia_Bootloader) && (TargetMode == PhoneInterfaces.Lumia_Normal)) { // Do nothing, because booting to Normal shortly goes into Flash mode too. // Just wait to arrive in Normal mode; PhoneNotifier.NewDeviceArrived += NewDeviceArrived; } else if ((CurrentMode == PhoneInterfaces.Lumia_Flash) && (TargetMode == PhoneInterfaces.Lumia_MassStorage)) { SwitchFromFlashToMassStorageMode(Continuation: true); } else if ((CurrentMode == PhoneInterfaces.Lumia_Flash) && (TargetMode == PhoneInterfaces.Qualcomm_Download)) { byte[] RebootCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x52 }; byte[] RebootToQualcommDownloadCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x58, 0x43, 0x42, 0x45 }; // NOKXCBE IsSwitchingInterface = true; LogFile.Log("Sending command for rebooting to Emergency Download mode"); byte[] RebootCommandResult = ((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(RebootToQualcommDownloadCommand); if ((RebootCommandResult != null) && (RebootCommandResult.Length >= 8)) { int ResultCode = (RebootCommandResult[6] << 8) + RebootCommandResult[7]; LogFile.Log("Resultcode: 0x" + ResultCode.ToString("X4")); } if ((RebootCommandResult != null) && (RebootCommandResult.Length == 4)) // This means fail: NOKU (unknow command) { ModeSwitchErrorWrapper("Failed to switch to Qualcomm Download mode"); IsSwitchingInterface = false; } else { PhoneNotifier.NewDeviceArrived += NewDeviceArrived; ModeSwitchProgressWrapper("And now rebooting phone to Qualcomm Download mode...", null); LogFile.Log("Rebooting phone to Qualcomm Download mode"); } } else { switch (TargetMode) { case PhoneInterfaces.Lumia_Normal: ModeSwitchErrorWrapper("Failed to switch to Normal mode"); break; case PhoneInterfaces.Lumia_Flash: ModeSwitchErrorWrapper("Failed to switch to Flash mode"); break; case PhoneInterfaces.Lumia_Label: ModeSwitchErrorWrapper("Failed to switch to Label mode"); break; case PhoneInterfaces.Lumia_MassStorage: ModeSwitchErrorWrapper("Failed to switch to Mass Storage mode"); break; } } }