static void Main(string[] args) { string filePath = null; string fileExt = null; bool help = false; bool isDfuFile = false; // Vendor and Product IDs are required, set them to invalid int vid = 0x10000, pid = 0x10000; // version is optional, FF means forced update int vmajor = 0xFF, vminor = 0xFF; // parameter parsing OptionSet optionSet = new OptionSet() .Add("?|help|h", "Prints out the options.", option => help = option != null) .Add("i|image=", "Path of the image file to download. Supported formats are DFU, Intel HEX and Motorola SREC.", option => filePath = option) .Add("d|device=", "USB Device Vendor and Product ID in XXXX:XXXX format. Ignored if the file format is DFU.", option => { var result = UsbIdRegex.Match(option); if (!result.Success) { help = true; } else { vid = UInt16.Parse(result.Groups["vid"].Value, NumberStyles.HexNumber); pid = UInt16.Parse(result.Groups["pid"].Value, NumberStyles.HexNumber); } }) .Add("v|version=", "Firmware version in D.D format. Ignored if the file format is DFU.", option => { var result = VersionRegex.Match(option); if (!result.Success) { help = true; } else { vmajor = Byte.Parse(result.Groups["major"].Value); vminor = Byte.Parse(result.Groups["minor"].Value); } }); try { // try to get required arguments optionSet.Parse(args); fileExt = Path.GetExtension(filePath); isDfuFile = Dfu.IsExtensionSupported(fileExt); if (!isDfuFile && ((vid > 0xFFFF) || (pid > 0xFFFF))) { help = true; } } catch (Exception) { help = true; } if (help) { // print help text and exit Console.Error.WriteLine("Usage:"); optionSet.WriteOptionDescriptions(Console.Error); Environment.Exit(-1); } // DFU device event printers int prevCursor = -1; EventHandler <ProgressChangedEventArgs> printDownloadProgress = (obj, e) => { if (prevCursor == Console.CursorTop) { Console.SetCursorPosition(0, Console.CursorTop - 1); } Console.WriteLine("Download progress: {0}%", e.ProgressPercentage); prevCursor = Console.CursorTop; }; EventHandler <ErrorEventArgs> printDevError = (obj, e) => { Console.Error.WriteLine("The DFU device reported the following error: {0}", e.GetException().Message); }; Device device = null; try { Version fileVer = new Version(vmajor, vminor); Dfu.FileContent dfuFileData = null; RawMemory memory = null; // find the matching file parser by extension if (isDfuFile) { dfuFileData = Dfu.ParseFile(filePath); Console.WriteLine("DFU image parsed successfully."); // DFU file specifies VID, PID and version, so override any arguments vid = dfuFileData.DeviceInfo.VendorId; pid = dfuFileData.DeviceInfo.ProductId; fileVer = dfuFileData.DeviceInfo.ProductVersion; } else if (IntelHex.IsExtensionSupported(fileExt)) { memory = IntelHex.ParseFile(filePath); Console.WriteLine("Intel HEX image parsed successfully."); } else if (SRecord.IsExtensionSupported(fileExt)) { memory = SRecord.ParseFile(filePath); Console.WriteLine("SRecord image parsed successfully."); } else { throw new ArgumentException("Image file format not recognized."); } // find the DFU device device = Device.OpenFirst(UsbDevice.AllDevices, vid, pid); device.DeviceError += printDevError; if (isDfuFile) { // verify protocol version if (dfuFileData.DeviceInfo.DfuVersion != device.DfuDescriptor.DfuVersion) { throw new InvalidOperationException(String.Format("DFU file version {0} doesn't match device DFU version {1}", dfuFileData.DeviceInfo.DfuVersion, device.DfuDescriptor.DfuVersion)); } } // if the device is in normal application mode, reconfigure it if (device.InAppMode()) { bool skipUpdate = fileVer <= device.Info.ProductVersion; // skip update when it's deemed unnecessary if (skipUpdate) { Console.WriteLine("The device is already up-to-date (version {0}), skipping update (version {1}).", device.Info.ProductVersion, fileVer); return; } Console.WriteLine("Device found in application mode, reconfiguring device to DFU mode..."); device.Reconfigure(); // in case the device detached, we must find the DFU mode device if (!device.IsOpen()) { // clean up old device first device.DeviceError -= printDevError; device.Dispose(); device = null; device = Device.OpenFirst(UsbDevice.AllDevices, vid, pid); device.DeviceError += printDevError; } } else { Console.WriteLine("Device found in DFU mode."); } // perform upgrade device.DownloadProgressChanged += printDownloadProgress; if (isDfuFile) { device.DownloadFirmware(dfuFileData); } else { device.DownloadFirmware(memory); } device.DownloadProgressChanged -= printDownloadProgress; Console.WriteLine("Download successful, manifesting update..."); device.Manifest(); // if the device detached, clean up if (!device.IsOpen()) { device.DeviceError -= printDevError; device.Dispose(); device = null; } // TODO find device again to verify new version Console.WriteLine("The device has been successfully upgraded."); } catch (Exception e) { Console.Error.WriteLine("Device Firmware Upgrade failed with exception: {0}.", e.ToString()); Environment.Exit(-1); } finally { if (device != null) { device.Dispose(); } } }
public static void Flash(string filePath, int BinMemOffset = 0, int vid = 0x0483, int pid = 0xDF11) { // version is optional, FF means forced update int vmajor = 0xFF, vminor = 0xFF; var fileExt = Path.GetExtension(filePath); var isDfuFile = Dfu.IsExtensionSupported(fileExt); EventHandler <ProgressChangedEventArgs> printDownloadProgress = (obj, e) => { Progress(e.ProgressPercentage, "Download progress"); Console.WriteLine("Download progress: {0}%", e.ProgressPercentage); }; EventHandler <ErrorEventArgs> printDevError = (obj, e) => { Progress(-1, String.Format("The DFU device reported the following error: {0}", e.GetException().Message)); Console.Error.WriteLine("The DFU device reported the following error: {0}", e.GetException().Message); }; LibUsbDfu.Device device = null; try { Version fileVer = new Version(vmajor, vminor); Dfu.FileContent dfuFileData = null; RawMemory memory = null; // find the matching file parser by extension if (isDfuFile) { dfuFileData = Dfu.ParseFile(filePath); Console.WriteLine("DFU image parsed successfully."); // DFU file specifies VID, PID and version, so override any arguments vid = dfuFileData.DeviceInfo.VendorId; pid = dfuFileData.DeviceInfo.ProductId; fileVer = dfuFileData.DeviceInfo.ProductVersion; } else if (IntelHex.IsExtensionSupported(fileExt)) { memory = IntelHex.ParseFile(filePath); Console.WriteLine("Intel HEX image parsed successfully."); } else if (SRecord.IsExtensionSupported(fileExt)) { memory = SRecord.ParseFile(filePath); Console.WriteLine("SRecord image parsed successfully."); } else if (BinMemOffset > 0) { memory = new RawMemory(); memory.TryAddSegment(new Segment((ulong)BinMemOffset, File.ReadAllBytes(filePath))); } else { throw new ArgumentException("Image file format not recognized."); } // find the DFU device if (vid == 0 && pid == 0) { LibUsbDfu.Device.TryOpen(UsbDevice.AllDevices.First(), out device); } else { device = LibUsbDfu.Device.OpenFirst(UsbDevice.AllDevices, vid, pid); } device.DeviceError += printDevError; if (isDfuFile) { // verify protocol version if (dfuFileData.DeviceInfo.DfuVersion != device.DfuDescriptor.DfuVersion) { throw new InvalidOperationException(String.Format("DFU file version {0} doesn't match device DFU version {1}", dfuFileData.DeviceInfo.DfuVersion, device.DfuDescriptor.DfuVersion)); } } // if the device is in normal application mode, reconfigure it if (device.InAppMode()) { bool skipUpdate = fileVer <= device.Info.ProductVersion; // skip update when it's deemed unnecessary if (skipUpdate) { Console.WriteLine("The device is already up-to-date (version {0}), skipping update (version {1}).", device.Info.ProductVersion, fileVer); return; } Console.WriteLine("Device found in application mode, reconfiguring device to DFU mode..."); device.Reconfigure(); // in case the device detached, we must find the DFU mode device if (!device.IsOpen()) { // clean up old device first device.DeviceError -= printDevError; device.Dispose(); device = null; device = LibUsbDfu.Device.OpenFirst(UsbDevice.AllDevices, vid, pid); device.DeviceError += printDevError; } } else { Console.WriteLine("Device found in DFU mode."); } // perform upgrade device.DownloadProgressChanged += printDownloadProgress; if (isDfuFile) { device.DownloadFirmware(dfuFileData); } else { device.DownloadFirmware(memory); } device.DownloadProgressChanged -= printDownloadProgress; Console.WriteLine("Download successful, manifesting update..."); Progress(100, "Download successful, manifesting update..."); device.Manifest(); // if the device detached, clean up if (!device.IsOpen()) { device.DeviceError -= printDevError; device.Dispose(); device = null; } // TODO find device again to verify new version Console.WriteLine("The device has been successfully upgraded."); Progress(100, "The device has been successfully upgraded."); } catch (Exception e) { Console.Error.WriteLine("Device Firmware Upgrade failed with exception: {0}.", e.ToString()); //Environment.Exit(-1); Progress(-1, String.Format("Device Firmware Upgrade failed with exception: {0}.", e.ToString())); } finally { if (device != null) { device.Dispose(); } } }