| 
					
				 | 
			
			
				@@ -475,6 +475,7 @@ private: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		if (dlg.ShowModal() == wxID_CANCEL) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		std::string filename(dlg.GetPath()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		wxLogMessage("Attempting firmware update from file %s", filename); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		wxWindowPtr<wxGenericProgressDialog> progress( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			new wxGenericProgressDialog( 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -485,6 +486,7 @@ private: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				wxPD_AUTO_HIDE | wxPD_CAN_ABORT) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		mmLogStatus("Searching for bootloader"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		bool versionChecked = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		while (true) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			try 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -492,6 +494,16 @@ private: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				if (!myHID) myHID.reset(HID::Open()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				if (myHID) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					if (!myHID->isCorrectFirmware(filename)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						wxMessageBox( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							"Firmware does not match device hardware", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							"Wrong filename", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							wxOK | wxICON_ERROR); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					versionChecked = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					mmLogStatus("Resetting SCSI2SD into bootloader"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					myHID->enterBootloader(); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -499,10 +511,25 @@ private: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if (myDfu.hasDevice() && !versionChecked) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					mmLogStatus("STM DFU Bootloader found, checking compatibility"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					progress->Show(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					if (!checkVersionMarker(filename)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						wxMessageBox( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							"Firmware does not match device hardware", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							"Wrong filename", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							wxOK | wxICON_ERROR); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					versionChecked = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				if (myDfu.hasDevice()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					mmLogStatus("STM DFU Bootloader found"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					progress->Show(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					progress->Show(10); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					doDFUUpdate(filename); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				} 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -520,6 +547,90 @@ private: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	bool checkVersionMarker(const std::string& firmware) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		std::stringstream ss; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#ifdef __WINDOWS__ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		ss << "dfu-util "; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (wxExecute("which dfu-util", wxEXEC_SYNC) == 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			ss << "dfu-util "; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			wxFileName exePath(wxStandardPaths::Get().GetExecutablePath()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			ss << '"' << exePath.GetPathWithSep() << "dfu-util\" "; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		std::string tmpFile = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			wxFileName::CreateTempFileName( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				_("SCSI2SD_MARKER"), static_cast<wxFile*>(NULL)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		wxRemoveFile(tmpFile); // dfu-util won't overwrite. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		ss << "--alt 2 -s 0x1FFF7800:4 -U \"" << tmpFile << "\""; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		wxLogMessage("Running: %s", ss.str()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		std::string cmd = ss.str(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		long result = wxExecute( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			cmd.c_str(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			wxEXEC_SYNC 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (result != 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			wxLogMessage("OTP Version check failed."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// Ok, we now have a file with 8 bytes in it. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		wxFile file(tmpFile); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (file.Length() != 4) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			wxLogMessage("OTP Version check file isn't 4 bytes."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		uint8_t data[4]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (file.Read(data, sizeof(data)) != sizeof(data)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			wxMessageBox( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				"Couldn't read file", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				"Couldn't read file", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				wxOK | wxICON_ERROR); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		wxRemoveFile(tmpFile); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		uint32_t value = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			(((uint32_t)(data[0]))) | 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			(((uint32_t)(data[1])) << 8) | 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			(((uint32_t)(data[2])) << 16) | 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			(((uint32_t)(data[3])) << 24); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (value == 0xFFFFFFFF) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// Not set, ignore. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			wxLogMessage("OTP Hardware version not set. Ignoring."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		else if (value == 0x06002020) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			wxLogMessage("Found V6 2020 hardware marker"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return firmware.rfind("firmware.V6.2020.dfu") != std::string::npos; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		else if (value == 0x06002019) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			wxLogMessage("Found V6 revF hardware marker"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return firmware.rfind("firmware.V6.revF.dfu") != std::string::npos || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				firmware.rfind("firmware.dfu") != std::string::npos; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			wxLogMessage("Found unknown hardware marker: %u", value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return false; // Some unknown version. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	void doDFUUpdate(const std::string& filename) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		if (filename.find(".dfu") == std::string::npos) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -531,7 +642,6 @@ private: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		std::stringstream ss; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #ifdef __WINDOWS__ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		ss << "dfu-util --download \"" 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -697,6 +807,13 @@ private: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 						myHID->getFirmwareVersionStr(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					mmLogStatus(msg.str()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					std::stringstream devInfo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					devInfo << "Hardware version: " << 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						myHID->getHardwareVersion() << std::endl << 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						"Serial Number: " << 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						myHID->getSerialNumber(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					wxLogMessage(this, "%s", devInfo.str()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					std::vector<uint8_t> csd(myHID->getSD_CSD()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					std::vector<uint8_t> cid(myHID->getSD_CID()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					std::stringstream sdinfo; 
			 |