diff --git a/README.md b/README.md
index 7890d636..c238d7b7 100644
--- a/README.md
+++ b/README.md
@@ -12,11 +12,11 @@ Is part of **nanoFramework** toolbox, along with other various tools that are re
It makes use of several 3rd party tools:
-- Espressif esptool.
+- Espressif esptool
You can find the esptool and licensing information on the repository [here](http://github.com/espressif/esptool).
-- ST DfuSe USB.
- You can find the source, licensing information and documentation [here](https://www.st.com/en/development-tools/stsw-stm32080.html).
-- ST-LINK Utility.
+- QMKDfuSe
+ Tool based on STM DfusSe tool. You can find the source, licensing information and documentation [here](https://github.com/qmk/qmk_dfuse).
+- ST-LINK Utility
You can find the source, licensing information and documentation [here](https://www.st.com/content/st_com/en/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-programmers/stsw-link004.html).
- Texas Instruments Uniflash
You can find the Uniflash tool and licensing information [here](http://www.ti.com/tool/download/UNIFLASH).
diff --git a/lib/stdfu/qmk-dfuse.exe b/lib/stdfu/qmk-dfuse.exe
new file mode 100644
index 00000000..1b674b36
Binary files /dev/null and b/lib/stdfu/qmk-dfuse.exe differ
diff --git a/lib/stdfu/x64/STDFU.dll b/lib/stdfu/x64/STDFU.dll
deleted file mode 100644
index 6ef75b58..00000000
Binary files a/lib/stdfu/x64/STDFU.dll and /dev/null differ
diff --git a/lib/stdfu/x64/STTubeDevice30.dll b/lib/stdfu/x64/STTubeDevice30.dll
deleted file mode 100644
index 3a7945f8..00000000
Binary files a/lib/stdfu/x64/STTubeDevice30.dll and /dev/null differ
diff --git a/lib/stdfu/x86/STDFU.dll b/lib/stdfu/x86/STDFU.dll
deleted file mode 100644
index 90e78051..00000000
Binary files a/lib/stdfu/x86/STDFU.dll and /dev/null differ
diff --git a/lib/stdfu/x86/STTubeDevice30.dll b/lib/stdfu/x86/STTubeDevice30.dll
deleted file mode 100644
index deada9cf..00000000
Binary files a/lib/stdfu/x86/STTubeDevice30.dll and /dev/null differ
diff --git a/nanoFirmwareFlasher/Exceptions/BadDfuProtocolVersionException.cs b/nanoFirmwareFlasher/Exceptions/BadDfuProtocolVersionException.cs
deleted file mode 100644
index 8ac82275..00000000
--- a/nanoFirmwareFlasher/Exceptions/BadDfuProtocolVersionException.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using System;
-using System.Runtime.Serialization;
-
-namespace nanoFramework.Tools.FirmwareFlasher
-{
- ///
- /// The connected DFU device is running a non supported version of the DFU protocol.
- ///
- [Serializable]
- internal class BadDfuProtocolVersionException : Exception
- {
- public ushort DfuVersion { get; }
-
- public BadDfuProtocolVersionException()
- {
- }
-
- public BadDfuProtocolVersionException(ushort bcdDFUVersion)
- {
- DfuVersion = bcdDFUVersion;
- }
-
- public BadDfuProtocolVersionException(string message) : base(message)
- {
- }
-
- public BadDfuProtocolVersionException(string message, Exception innerException) : base(message, innerException)
- {
- }
-
- protected BadDfuProtocolVersionException(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
- }
-}
diff --git a/nanoFirmwareFlasher/Exceptions/CantReadDfuDescriptorException.cs b/nanoFirmwareFlasher/Exceptions/CantReadDfuDescriptorException.cs
deleted file mode 100644
index d44032c3..00000000
--- a/nanoFirmwareFlasher/Exceptions/CantReadDfuDescriptorException.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using System;
-using System.Runtime.Serialization;
-
-namespace nanoFramework.Tools.FirmwareFlasher
-{
- ///
- /// Couldn't read the DFU descriptor of the connected DFU device.
- ///
- [Serializable]
- internal class CantReadDfuDescriptorException : Exception
- {
- public uint ErrorCode { get; }
-
- public CantReadDfuDescriptorException(uint errorCode)
- {
- ErrorCode = errorCode;
- }
-
- public CantReadDfuDescriptorException(uint errorCode, string message) : base(message)
- {
- }
-
- public CantReadDfuDescriptorException(uint errorCode, string message, Exception innerException) : base(message, innerException)
- {
- }
-
- protected CantReadDfuDescriptorException(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
- }
-}
diff --git a/nanoFirmwareFlasher/Exceptions/CantReadUsbDescriptorException.cs b/nanoFirmwareFlasher/Exceptions/CantReadUsbDescriptorException.cs
deleted file mode 100644
index 611a8768..00000000
--- a/nanoFirmwareFlasher/Exceptions/CantReadUsbDescriptorException.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using System;
-using System.Runtime.Serialization;
-
-namespace nanoFramework.Tools.FirmwareFlasher
-{
- ///
- /// Couldn't read the USB descriptor of the DFU device.
- ///
- [Serializable]
- internal class CantReadUsbDescriptorException : Exception
- {
- public uint ErrorCode { get; }
-
- public CantReadUsbDescriptorException(uint errorCode)
- {
- ErrorCode = errorCode;
- }
-
- public CantReadUsbDescriptorException(uint errorCode, string message) : base(message)
- {
- }
-
- public CantReadUsbDescriptorException(uint errorCode, string message, Exception innerException) : base(message, innerException)
- {
- }
-
- protected CantReadUsbDescriptorException(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
- }
-}
diff --git a/nanoFirmwareFlasher/Exceptions/DfuFileDoesNotExistException.cs b/nanoFirmwareFlasher/Exceptions/DfuFileDoesNotExistException.cs
index 1a55cd42..5303e701 100644
--- a/nanoFirmwareFlasher/Exceptions/DfuFileDoesNotExistException.cs
+++ b/nanoFirmwareFlasher/Exceptions/DfuFileDoesNotExistException.cs
@@ -1,4 +1,9 @@
-using System;
+//
+// Copyright (c) 2020 The nanoFramework project contributors
+// See LICENSE file in the project root for full license information.
+//
+
+using System;
using System.Runtime.Serialization;
namespace nanoFramework.Tools.FirmwareFlasher
diff --git a/nanoFirmwareFlasher/Exceptions/DfuOperationFailedException.cs b/nanoFirmwareFlasher/Exceptions/DfuOperationFailedException.cs
new file mode 100644
index 00000000..63be5676
--- /dev/null
+++ b/nanoFirmwareFlasher/Exceptions/DfuOperationFailedException.cs
@@ -0,0 +1,33 @@
+//
+// Copyright (c) 2020 The nanoFramework project contributors
+// See LICENSE file in the project root for full license information.
+//
+
+using System;
+using System.Runtime.Serialization;
+
+namespace nanoFramework.Tools.FirmwareFlasher
+{
+ ///
+ /// Verification of DFU write failed.
+ ///
+ [Serializable]
+ internal class DfuOperationFailedException : Exception
+ {
+ public DfuOperationFailedException()
+ {
+ }
+
+ public DfuOperationFailedException(string message) : base(message)
+ {
+ }
+
+ public DfuOperationFailedException(string message, Exception innerException) : base(message, innerException)
+ {
+ }
+
+ protected DfuOperationFailedException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+ }
+}
diff --git a/nanoFirmwareFlasher/Exceptions/DfuVerificationFailedException.cs b/nanoFirmwareFlasher/Exceptions/DfuVerificationFailedException.cs
deleted file mode 100644
index cd64efd0..00000000
--- a/nanoFirmwareFlasher/Exceptions/DfuVerificationFailedException.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-using System.Runtime.Serialization;
-
-namespace nanoFramework.Tools.FirmwareFlasher
-{
- ///
- /// Verification of DFU write failed.
- ///
- [Serializable]
- internal class DfuVerificationFailedException : Exception
- {
- public DfuVerificationFailedException()
- {
- }
-
- public DfuVerificationFailedException(string message) : base(message)
- {
- }
-
- public DfuVerificationFailedException(string message, Exception innerException) : base(message, innerException)
- {
- }
-
- protected DfuVerificationFailedException(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
- }
-}
diff --git a/nanoFirmwareFlasher/ExitCodes.cs b/nanoFirmwareFlasher/ExitCodes.cs
index a3032300..54e997c3 100644
--- a/nanoFirmwareFlasher/ExitCodes.cs
+++ b/nanoFirmwareFlasher/ExitCodes.cs
@@ -25,12 +25,6 @@ public enum ExitCodes : int
[Display(Name = "No DFU device found. Make sure it's connected and has booted in DFU mode")]
E1000 = 1000,
- ///
- /// Error with DFU file
- ///
- [Display(Name = "Error with DFU file")]
- E1001 = 1001,
-
///
/// DFU file doesn't exist
///
diff --git a/nanoFirmwareFlasher/Program.cs b/nanoFirmwareFlasher/Program.cs
index 880ee003..c22bf78d 100644
--- a/nanoFirmwareFlasher/Program.cs
+++ b/nanoFirmwareFlasher/Program.cs
@@ -515,8 +515,8 @@ static async Task RunOptionsAndReturnExitCodeAsync(Options o)
}
catch (Exception ex)
{
- // exception with DFU file
- _exitCode = ExitCodes.E1001;
+ // exception with DFU operation
+ _exitCode = ExitCodes.E1003;
_extraMessage = ex.Message;
}
}
diff --git a/nanoFirmwareFlasher/StDfu.cs b/nanoFirmwareFlasher/StDfu.cs
deleted file mode 100644
index 87fec3dd..00000000
--- a/nanoFirmwareFlasher/StDfu.cs
+++ /dev/null
@@ -1,1178 +0,0 @@
-//
-// Copyright (c) 2019 The nanoFramework project contributors
-// See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.InteropServices;
-using System.Runtime.Serialization;
-using System.Text;
-
-namespace nanoFramework.Tools.FirmwareFlasher
-{
- internal class StDfu
- {
- #region DFU file structures
-
- // generic method to marshal a section of a byte array into a struct
- static void StructFromBytes(ref T pstruct, byte[] abyBuff, int nOffset)
- {
- int nLen = Marshal.SizeOf(pstruct);
- IntPtr pbyMarsh = Marshal.AllocHGlobal(nLen);
- Marshal.Copy(abyBuff, nOffset, pbyMarsh, nLen);
- pstruct = (T)Marshal.PtrToStructure(pbyMarsh, pstruct.GetType());
- Marshal.FreeHGlobal(pbyMarsh);
- }
-
- // DFU file header
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
- unsafe struct DfuHeader
- {
- // "DfuSe"
- public fixed byte Signature[5];
- public byte Version;
- // size of the sections from the header to the tail
- public uint DfuImageSize;
- // how many targets in the file
- public byte TargetsCount;
- }
-
- // DFU target header
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
- unsafe struct DfuImageTarget
- {
- // "Target"
- public fixed byte Signature[6];
- public byte AlternateSetting;
- // flag that the target has a name
- public uint IsNamed;
- // target name, which is optional
- public fixed byte TargetName[255];
- // size of the elements that follow the header
- public uint TargetSize;
- // how many elements in this target
- public uint NumElements;
- }
-
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
- unsafe struct DfuImageElement
- {
- // start address
- public uint Address;
- // size of the data block
- public uint Size;
- // data follow the Size field
- }
-
- //this is always at the end of the file, so you can seek there and work backwards
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
- unsafe struct DfuTail
- {
- public ushort Version;
- public ushort Pid;
- public ushort Vid;
- // DFU version, seems to be fixed with 0x011A
- public ushort DfuVersion;
- // signature with DFU ASCII backwards: 'U'(55) 'F'(46) 'D'(44)
- public fixed byte Signature[3];
- // tail length (16)
- public byte Length;
- // file CRC excluding the CRC
- public uint Crc;
- }
-
- #endregion
-
- #region DFU descriptors
-
- public class DfuFile
- {
- public ushort Vid = 0;
- public ushort Pid = 0;
- public ushort Version = 0;
- public DfuTarget[] DfuTargets = null;
- }
-
- public class DfuTarget
- {
- public string Name = null;
- public DfuElement[] DfuElements = null;
- }
-
- public class DfuElement
- {
- public uint Address = 0xffffffff;
- public byte[] Data = null;
- }
-
- #endregion
-
- public const uint STDFU_ERROR_OFFSET = 0x12340000;
-
- public const uint STDFU_NOERROR = STDFU_ERROR_OFFSET + 0x0;
- public const uint STDFU_MEMORY = STDFU_ERROR_OFFSET + 0x1;
- public const uint STDFU_BADPARAMETER = STDFU_ERROR_OFFSET + 0x2;
-
- public const uint STDFU_NOTIMPLEMENTED = STDFU_ERROR_OFFSET + 0x3;
- public const uint STDFU_ENUMFINISHED = STDFU_ERROR_OFFSET + 0x4;
- public const uint STDFU_OPENDRIVERERROR = STDFU_ERROR_OFFSET + 0x5;
-
- public const uint STDFU_ERRORDESCRIPTORBUILDING = STDFU_ERROR_OFFSET + 0x6;
- public const uint STDFU_PIPECREATIONERROR = STDFU_ERROR_OFFSET + 0x7;
- public const uint STDFU_PIPERESETERROR = STDFU_ERROR_OFFSET + 0x8;
- public const uint STDFU_PIPEABORTERROR = STDFU_ERROR_OFFSET + 0x9;
- public const uint STDFU_STRINGDESCRIPTORERROR = STDFU_ERROR_OFFSET + 0xA;
-
- public const uint STDFU_DRIVERISCLOSED = STDFU_ERROR_OFFSET + 0xB;
- public const uint STDFU_VENDOR_RQ_PB = STDFU_ERROR_OFFSET + 0xC;
- public const uint STDFU_ERRORWHILEREADING = STDFU_ERROR_OFFSET + 0xD;
- public const uint STDFU_ERRORBEFOREREADING = STDFU_ERROR_OFFSET + 0xE;
- public const uint STDFU_ERRORWHILEWRITING = STDFU_ERROR_OFFSET + 0xF;
- public const uint STDFU_ERRORBEFOREWRITING = STDFU_ERROR_OFFSET + 0x10;
- public const uint STDFU_DEVICERESETERROR = STDFU_ERROR_OFFSET + 0x11;
- public const uint STDFU_CANTUSEUNPLUGEVENT = STDFU_ERROR_OFFSET + 0x12;
- public const uint STDFU_INCORRECTBUFFERSIZE = STDFU_ERROR_OFFSET + 0x13;
- public const uint STDFU_DESCRIPTORNOTFOUND = STDFU_ERROR_OFFSET + 0x14;
- public const uint STDFU_PIPESARECLOSED = STDFU_ERROR_OFFSET + 0x15;
- public const uint STDFU_PIPESAREOPEN = STDFU_ERROR_OFFSET + 0x16;
-
- public const uint STDFU_TIMEOUTWAITINGFORRESET = STDFU_ERROR_OFFSET + 0x17;
-
- public const uint STDFU_RQ_GET_DEVICE_DESCRIPTOR = 0x02000000;
- public const uint STDFU_RQ_GET_DFU_DESCRIPTOR = 0x03000000;
- public const uint STDFU_RQ_GET_STRING_DESCRIPTOR = 0x04000000;
- public const uint STDFU_RQ_GET_NB_OF_CONFIGURATIONS = 0x05000000;
- public const uint STDFU_RQ_GET_CONFIGURATION_DESCRIPTOR = 0x06000000;
- public const uint STDFU_RQ_GET_NB_OF_INTERFACES = 0x07000000;
- public const uint STDFU_RQ_GET_NB_OF_ALTERNATES = 0x08000000;
- public const uint STDFU_RQ_GET_INTERFACE_DESCRIPTOR = 0x09000000;
- public const uint STDFU_RQ_OPEN = 0x0A000000;
- public const uint STDFU_RQ_CLOSE = 0x0B000000;
- public const uint STDFU_RQ_DETACH = 0x0C000000;
- public const uint STDFU_RQ_DOWNLOAD = 0x0D000000;
- public const uint STDFU_RQ_UPLOAD = 0x0E000000;
- public const uint STDFU_RQ_GET_STATUS = 0x0F000000;
- public const uint STDFU_RQ_CLR_STATUS = 0x10000000;
- public const uint STDFU_RQ_GET_STATE = 0x11000000;
- public const uint STDFU_RQ_ABORT = 0x12000000;
- public const uint STDFU_RQ_SELECT_ALTERNATE = 0x13000000;
- public const uint STDFU_RQ_AWAITINGPNPUNPLUGEVENT = 0x14000000;
- public const uint STDFU_RQ_AWAITINGPNPPLUGEVENT = 0x15000000;
- public const uint STDFU_RQ_IDENTIFYINGDEVICE = 0x16000000;
-
- private const char SEPARATOR_ADDRESS = '/';
- private const char SEPARATOR_ADDRESS_ALIASED = '-';
- private const char SEPARATOR_BLOCKS = ',';
- private const char SEPARATOR_NBSECTORS_SECTORSIZE = '*';
-
- // DFU States
- public const uint STATE_IDLE = 0x00;
- public const uint STATE_DETACH = 0x01;
- public const uint STATE_DFU_IDLE = 0x02;
- public const uint STATE_DFU_DOWNLOAD_SYNC = 0x03;
- public const uint STATE_DFU_DOWNLOAD_BUSY = 0x04;
- public const uint STATE_DFU_DOWNLOAD_IDLE = 0x05;
- public const uint STATE_DFU_MANIFEST_SYNC = 0x06;
- public const uint STATE_DFU_MANIFEST = 0x07;
- public const uint STATE_DFU_MANIFEST_WAIT_RESET = 0x08;
- public const uint STATE_DFU_UPLOAD_IDLE = 0x09;
- public const uint STATE_DFU_ERROR = 0x0A;
-
- public const uint STATE_DFU_UPLOAD_SYNC = 0x91;
- public const uint STATE_DFU_UPLOAD_BUSY = 0x92;
-
-
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
- public struct UsbInterfaceDescriptor
- {
- public byte bLength;
- public byte bDescriptorType;
- public byte bInterfaceNumber;
- public byte bAlternateSetting;
- public byte bNumEndpoints;
- public byte bInterfaceClass;
- public byte bInterfaceSubClass;
- public byte bInterfaceProtocol;
- public byte iInterface;
- };
-
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
- public struct DfuFunctionalDescriptor
- {
- public byte bLength;
- public byte bDescriptorType;
- public byte bmAttributes;
- public ushort wDetachTimeOut;
- public ushort wTransfertSize;
- public ushort bcdDFUVersion;
- };
-
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
- public struct DfuStatus
- {
- public byte bStatus;
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
- public byte[] bwPollTimeout;
- public byte bState;
- public byte iString;
- };
-
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
- public struct UsbDeviceDescriptor
- {
- public byte bLength;
- public byte bDescriptorType;
- public ushort bcdUSB;
- public byte bDeviceClass;
- public byte bDeviceSubClass;
- public byte bDeviceProtocol;
- public byte bMaxPacketSize0;
- public ushort idVendor;
- public ushort idProduct;
- public ushort bcdDevice;
- public byte iManufacturer;
- public byte iProduct;
- public byte iSerialNumber;
- public byte bNumConfigurations;
- };
-
- // from MAPPINGSECTOR
- public class MappingSector
- {
- public enum SectorType
- {
- InternalFLASH,
- OptionBytes,
- OTP,
- DeviceFeature,
- Other
- };
-
- public uint StartAddress;
- public uint SectorIndex;
- public uint SectorSize;
- public SectorType Type;
- public string Name;
-
- public MappingSector(string name, SectorType sectorType, uint startAddress, uint size, uint sectorIndex)
- {
- Name = name;
- Type = sectorType;
- StartAddress = startAddress;
- SectorSize = size;
- SectorIndex = sectorIndex;
- }
- }
-
- #region imports from STDFU.dll
-
- // export from dumpbin
- // 1 0 000014A0 STDFU_Abort
- // 2 1 00001030 STDFU_Close
- // 3 2 000013F0 STDFU_Clrstatus
- // 4 3 00001210 STDFU_Detach
- // 5 4 00001290 STDFU_Dnload
- // 6 5 000010B0 STDFU_GetConfigurationDescriptor
- // 7 6 00001130 STDFU_GetDFUDescriptor
- // 8 7 00001050 STDFU_GetDeviceDescriptor
- // 9 8 00001110 STDFU_GetInterfaceDescriptor
- //10 9 000010F0 STDFU_GetNbOfAlternates
- //11 A 00001090 STDFU_GetNbOfConfigurations
- //12 B 000010D0 STDFU_GetNbOfInterfaces
- //13 C 00001070 STDFU_GetStringDescriptor
- //14 D 00001440 STDFU_Getstate
- //15 E 00001360 STDFU_Getstatus
- //16 F 00001010 STDFU_Open
- //17 10 000011F0 STDFU_SelectCurrentConfiguration
- //18 11 000012F0 STDFU_Upload
-
-
- [DllImport(@"stdfu\STDFU.dll", EntryPoint = "STDFU_GetInterfaceDescriptor", CharSet = CharSet.Ansi)]
- internal static extern uint STDFU_GetInterfaceDescriptor(
- ref IntPtr handle,
- uint nConfigIdx,
- uint nInterfaceIdx,
- uint nAltSetIdx,
- ref UsbInterfaceDescriptor pDesc);
-
-
- [DllImport(@"stdfu\STDFU.dll", EntryPoint = "STDFU_SelectCurrentConfiguration", CharSet = CharSet.Ansi)]
- private static extern uint STDFU_SelectCurrentConfiguration(
- ref IntPtr hDevice,
- uint ConfigIndex,
- uint InterfaceIndex,
- uint AlternateSetIndex);
-
-
- [DllImport(@"stdfu\STDFU.dll", EntryPoint = "STDFU_GetDFUDescriptor", CharSet = CharSet.Ansi)]
- internal static extern uint STDFU_GetDFUDescriptor(
- ref IntPtr handle,
- ref uint DFUInterfaceNum,
- ref uint NBOfAlternates,
- ref DfuFunctionalDescriptor dfuDescriptor);
-
- [DllImport(@"stdfu\STDFU.dll", EntryPoint = "STDFU_GetDeviceDescriptor", CharSet = CharSet.Ansi)]
- internal static extern uint STDFU_GetDeviceDescriptor(
- ref IntPtr handle,
- ref UsbDeviceDescriptor descriptor);
-
- [DllImport(@"stdfu\STDFU.dll", EntryPoint = "STDFU_GetStringDescriptor", CharSet = CharSet.Ansi)]
- internal static extern uint STDFU_GetStringDescriptor(
- ref IntPtr handle,
- uint index,
- IntPtr stringBuffer,
- uint stringLength);
-
- [DllImport(@"stdfu\STDFU.dll", EntryPoint = "STDFU_Dnload", CharSet = CharSet.Ansi)]
- internal static extern uint STDFU_Dnload(
- ref IntPtr hDevice,
- [MarshalAs(UnmanagedType.LPArray)]byte[] pBuffer,
- uint nBytes,
- ushort nBlocks);
-
- [DllImport(@"stdfu\STDFU.dll", EntryPoint = "STDFU_Getstatus", CharSet = CharSet.Ansi)]
- internal static extern uint STDFU_GetStatus(
- ref IntPtr hDevice,
- ref DfuStatus dfuStatus);
-
- [DllImport(@"stdfu\STDFU.dll", EntryPoint = "STDFU_Clrstatus", CharSet = CharSet.Ansi)]
- internal static extern uint STDFU_ClrStatus(ref IntPtr hDevice);
-
- [DllImport(@"stdfu\STDFU.dll", EntryPoint = "STDFU_Open", CharSet = CharSet.Ansi)]
- internal static extern uint STDFU_Open(
- [MarshalAs(UnmanagedType.LPStr)]string szDevicePath,
- out IntPtr hDevice);
-
- [DllImport(@"stdfu\STDFU.dll", EntryPoint = "STDFU_Upload", CharSet = CharSet.Ansi)]
- internal static extern uint STDFU_Upload(
- ref IntPtr hDevice,
- [MarshalAs(UnmanagedType.LPArray)]byte[] pBuffer,
- uint nBytes,
- ushort nBlocks);
-
-
-
- #endregion
-
- internal static List CreateMappingFromDevice(
- IntPtr hDevice,
- uint alternates,
- DfuFunctionalDescriptor dfuDescriptor)
- {
- List sectorMap = new List((int)alternates);
-
- uint returnValue;
- uint interfaceIndex = 0;
- IntPtr stringBuffer = Marshal.AllocHGlobal(512);
-
- UsbInterfaceDescriptor usbInterfaceDescriptor = new UsbInterfaceDescriptor();
-
- // Loop through Internal FLASH, Option bytes, OTP and Device Feature
- for (uint i = 0; i < alternates; i++)
- {
- uint sectorIndex = 0;
-
- returnValue = STDFU_GetInterfaceDescriptor(ref hDevice, 0, interfaceIndex, i, ref usbInterfaceDescriptor);
-
- if (returnValue != STDFU_NOERROR)
- {
- throw new ErrorGettingInterfaceDescriptorException();
- }
-
- // sanity check
- if (usbInterfaceDescriptor.iInterface == 0)
- {
- throw new ErrorGettingInterfaceDescriptorException();
- }
-
- returnValue = STDFU_GetStringDescriptor(ref hDevice, usbInterfaceDescriptor.iInterface, stringBuffer, 512);
- if (returnValue != STDFU_NOERROR)
- {
- throw new ErrorGettingStringDescriptorException();
- }
-
- if (returnValue == STDFU_NOERROR)
- {
- ushort numberOfSectors = 0;
- MappingSector.SectorType type;
-
- var rawSectorDescription = Marshal.PtrToStringAnsi(stringBuffer);
-
- // sanity check
- if (rawSectorDescription[0] != '@')
- {
- throw new WrongOrInvalidStringDescriptorException();
- }
-
- var sectorName = rawSectorDescription.Substring(1, rawSectorDescription.IndexOf('/') - 1);
- sectorName = sectorName.TrimEnd(' ');
-
- if (sectorName.Equals("Internal Flash"))
- {
- type = MappingSector.SectorType.InternalFLASH;
- }
- else if (sectorName.Equals("Option Bytes"))
- {
- type = MappingSector.SectorType.OptionBytes;
- }
- else if (sectorName.Equals("OTP Memory"))
- {
- type = MappingSector.SectorType.OTP;
- }
- else if (sectorName.Equals("Device Feature"))
- {
- type = MappingSector.SectorType.DeviceFeature;
- }
- else
- {
- type = MappingSector.SectorType.Other;
- }
-
- var startAddress = uint.Parse(rawSectorDescription.Substring(rawSectorDescription.IndexOf(SEPARATOR_ADDRESS) + 3, 8), System.Globalization.NumberStyles.HexNumber);
-
- var sectorDescription = rawSectorDescription;
-
- while (sectorDescription.IndexOf(SEPARATOR_NBSECTORS_SECTORSIZE) >= 0)
- {
- var sectorN = sectorDescription.Substring(sectorDescription.IndexOf(SEPARATOR_NBSECTORS_SECTORSIZE) - 3, 3);
- if (char.IsDigit(sectorN[0]))
- {
- numberOfSectors = ushort.Parse(sectorN);
- }
- else
- {
- numberOfSectors = ushort.Parse(sectorN.Substring(1));
- }
-
- var sectorSize = ushort.Parse(sectorDescription.Substring(sectorDescription.IndexOf(SEPARATOR_NBSECTORS_SECTORSIZE) + 1, 3));
- if (sectorDescription[sectorDescription.IndexOf(SEPARATOR_NBSECTORS_SECTORSIZE) + 4] == 'K')
- {
- sectorSize *= 1024;
- }
- else if (sectorDescription[sectorDescription.IndexOf(SEPARATOR_NBSECTORS_SECTORSIZE) + 4] == 'M')
- {
- sectorSize *= 1024;
- }
-
- for (sectorIndex = 0; sectorIndex < numberOfSectors; sectorIndex++)
- {
- sectorMap.Add(new MappingSector(sectorName, type, startAddress, sectorSize, sectorIndex));
- startAddress += sectorSize;
- }
-
- sectorDescription = sectorDescription.Substring(sectorDescription.IndexOf(SEPARATOR_NBSECTORS_SECTORSIZE) + 1);
- }
- }
- else
- {
- break;
- }
- }
-
- return sectorMap;
- }
-
- public bool ParseDfuFile(
- string filepath,
- out ushort vid,
- out ushort pid,
- out ushort version,
- bool outputMessages = false)
- {
- byte[] fileData;
- bool retval = true;
-
- try
- {
- // read content from DFU file
- fileData = System.IO.File.ReadAllBytes(filepath);
-
- // check prefix
- if (Encoding.UTF8.GetString(fileData, 0, 5) != "DfuSe")
- {
- throw new DfuFileException("File signature error");
- }
-
- // check version
- if (fileData[5] != 1)
- {
- throw new DfuFileException("DFU file version must be 1");
- }
-
- // check suffix
- if ((Encoding.UTF8.GetString(fileData, fileData.Length - 8, 3) != "UFD")
- || (fileData[fileData.Length - 5] != 16)
- || (fileData[fileData.Length - 10] != 0x1A)
- || (fileData[fileData.Length - 9] != 0x01))
- {
- throw new DfuFileException("File suffix error");
- }
-
- // check the CRC
- var crc = BitConverter.ToUInt32(fileData, fileData.Length - 4);
- if (crc != CalculateCRC(fileData))
- {
- throw new DfuFileException("File CRC error");
- }
-
- // get VID, PID and version number from file
- vid = BitConverter.ToUInt16(fileData, fileData.Length - 12);
- pid = BitConverter.ToUInt16(fileData, fileData.Length - 14);
- version = BitConverter.ToUInt16(fileData, fileData.Length - 16);
- }
- catch
- {
- vid = 0;
- pid = 0;
- version = 0;
- retval = false;
- }
-
- return retval;
- }
-
- internal static unsafe DfuFile LoadDfuFile(
- string filePath,
- VerbosityLevel verbosity)
- {
- byte[] fileData;
- DfuFile dfuFile = new DfuFile();
-
- if (verbosity >= VerbosityLevel.Normal)
- {
- Console.Write("Loading DFU file...");
- }
-
- try
- {
- /////////////////
- // read the file
- fileData = System.IO.File.ReadAllBytes(filePath);
-
- // parse DFU header
- DfuHeader dfuHeader = new DfuHeader();
- StructFromBytes(ref dfuHeader, fileData, 0);
-
- if (verbosity >= VerbosityLevel.Normal)
- {
- Console.WriteLine(" OK");
- }
-
- ////////////////////
- // validate DFU file
-
- if (verbosity >= VerbosityLevel.Normal)
- {
- Console.Write("Validating DFU file...");
- }
-
- // sanity check on the prefix
- if (dfuHeader.Signature[0] == (byte)'D' &&
- dfuHeader.Signature[1] == (byte)'f' &&
- dfuHeader.Signature[2] == (byte)'u' &&
- dfuHeader.Signature[3] == (byte)'S' &&
- dfuHeader.Signature[4] == (byte)'e'
- )
- {
- // we are good
- }
- else
- {
- throw new DfuFileException("Bad file header");
- }
-
- // check DFU file format version
- if (dfuHeader.Version != 1)
- {
- throw new DfuFileException("DFU file version must be 1");
- }
-
- // check if there are any targets in the file
- if (dfuHeader.TargetsCount > 0)
- {
- // we are good
- }
- else
- {
- throw new DfuFileException("File has no targets");
- }
-
- // DFU tail at the end of the file
- DfuTail dfuTail = new DfuTail();
- StructFromBytes(ref dfuTail, fileData, fileData.Length - Marshal.SizeOf(dfuTail));
-
- // check signature
- if (dfuTail.Signature[0] == (byte)'U' &&
- dfuTail.Signature[1] == (byte)'F' &&
- dfuTail.Signature[2] == (byte)'D')
- {
- // we are good
- }
- else
- {
- throw new DfuFileException("Wrong file signature");
- }
-
- // check declared length and DFU version
- if (16 != dfuTail.Length ||
- 0x011a != dfuTail.DfuVersion)
- {
- throw new DfuFileException("Wrong tail size or version");
- }
-
- // check CRC
- if (dfuTail.Crc != CalculateCRC(fileData))
- {
- throw new DfuFileException("Bad CRC");
- }
-
- // get VID, PID and version number
- dfuFile.Vid = dfuTail.Vid;
- dfuFile.Pid = dfuTail.Pid;
- dfuFile.Version = dfuTail.Version;
-
- if (verbosity >= VerbosityLevel.Normal)
- {
- Console.WriteLine(" OK");
- }
-
- /////////////////////////
- // now parse the DFU file
-
- if (verbosity >= VerbosityLevel.Normal)
- {
- Console.Write("Parsing DFU file...");
- }
-
- // build targets array
- dfuFile.DfuTargets = new DfuTarget[dfuHeader.TargetsCount];
-
- // loop through each target, then loop through each image element
- int targetCursor = Marshal.SizeOf(typeof(DfuHeader));
-
- for (int targetIndex = 0; targetIndex < dfuFile.DfuTargets.Length; ++targetIndex)
- {
- dfuFile.DfuTargets[targetIndex] = new DfuTarget();
- DfuTarget dfuTarget = dfuFile.DfuTargets[targetIndex];
-
- DfuImageTarget dfuImageTarget = new DfuImageTarget();
-
- StructFromBytes(ref dfuImageTarget, fileData, targetCursor);
-
- // check signature
- if (dfuImageTarget.Signature[0] == (byte)'T' &&
- dfuImageTarget.Signature[1] == (byte)'a' &&
- dfuImageTarget.Signature[2] == (byte)'r' &&
- dfuImageTarget.Signature[3] == (byte)'g' &&
- dfuImageTarget.Signature[4] == (byte)'e' &&
- dfuImageTarget.Signature[5] == (byte)'t')
- {
- // we are good
- }
- else
- {
- throw new DfuFileException($"Bad signature for target { targetIndex } @ position { targetCursor }");
- }
-
- // get target name, if set
- if (dfuImageTarget.IsNamed > 0)
- {
- // this requires a bit of processing to read the string with the name
- int nameLenght = 0;
- byte* pRawBuffer = dfuImageTarget.TargetName;
-
- // move through buffer until a \0 (terminator) is found
- // target name is 255 chars (max)
- for (int i = 0; i < 255; i++)
- {
- if (*pRawBuffer++ == 0)
- {
- nameLenght = i;
- break;
- }
- }
-
- // load byte array from pointer
- byte[] nameBuffer = new byte[nameLenght];
- pRawBuffer = dfuImageTarget.TargetName;
- for (int i = 0; i < nameLenght; i++)
- {
- nameBuffer[i] = *pRawBuffer++;
- }
-
- dfuTarget.Name = Encoding.ASCII.GetString(nameBuffer, 0, nameLenght);
- }
- else
- {
- dfuTarget.Name = "";
- }
-
- if (dfuImageTarget.NumElements == 0)
- {
- throw new DfuFileException($"Target { targetIndex } has no elements");
- }
- else
- {
- dfuTarget.DfuElements = new DfuElement[dfuImageTarget.NumElements];
-
- int elementCursor = targetCursor + Marshal.SizeOf(typeof(DfuImageTarget));
-
- for (int elementIndex = 0; elementIndex < dfuTarget.DfuElements.Length; ++elementIndex)
- {
- dfuTarget.DfuElements[elementIndex] = new DfuElement();
- DfuElement dfuElem = dfuTarget.DfuElements[elementIndex];
-
- DfuImageElement dfuImageElement = new DfuImageElement();
- StructFromBytes(ref dfuImageElement, fileData, elementCursor);
-
- dfuElem.Address = dfuImageElement.Address;
- dfuElem.Data = fileData.Skip(elementCursor + Marshal.SizeOf(typeof(DfuImageElement))).Take((int)dfuImageElement.Size).ToArray();
- elementCursor += Marshal.SizeOf(typeof(DfuImageElement)) + (int)dfuImageElement.Size;
- }
- }
-
- targetCursor += Marshal.SizeOf(typeof(DfuImageTarget)) + (int)dfuImageTarget.TargetSize;
- }
-
- if (verbosity >= VerbosityLevel.Normal)
- {
- Console.WriteLine(" OK");
- }
-
- return dfuFile;
- }
- catch (Exception ex)
- {
- throw new DfuFileException("DFU file read failed. " + ex.Message);
- }
- }
-
- private static uint CalculateCRC(byte[] data)
- {
- uint crcValue = 0xFFFFFFFF;
- int i;
-
- for (i = 0; i < data.Length - 4; i++)
- {
- crcValue = _crcTable[((crcValue) ^ (data[i])) & 0xff] ^ ((crcValue) >> 8);
- }
-
- return crcValue;
- }
-
- #region CrcTable
-
- private static readonly uint[] _crcTable = {
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
- 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
- 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
- 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
- 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
- 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
- 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
- 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
- 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
- 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
- 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
- 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
- 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
- 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
- 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
- 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
- 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
- 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
- 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
- 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
- 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
- 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
- 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
- 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
- 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
- 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
- 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
- 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
- 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
- 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
- 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
- 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
- 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d };
-
- #endregion
-
- internal static void PartialErase(
- IntPtr hDevice,
- uint startAddress,
- uint size,
- List mapSector,
- bool outputMessages = false)
- {
- foreach (MappingSector s in mapSector)
- {
- if ((startAddress < s.StartAddress + s.SectorSize) && (startAddress + size > s.StartAddress))
- {
- EraseSector(hDevice, s.StartAddress);
- }
- }
- }
-
- private static void EraseSector(
- IntPtr hDevice,
- uint Address)
- {
- DfuStatus dfuStatus = new DfuStatus();
-
- uint returnValue;
- byte[] Command = { 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-
- Command[1] = (byte)(Address & 0xFF);
- Command[2] = (byte)((Address >> 8) & 0xFF);
- Command[3] = (byte)((Address >> 16) & 0xFF);
- Command[4] = (byte)((Address >> 24) & 0xFF);
-
- returnValue = STDFU_SelectCurrentConfiguration(ref hDevice, 0, 0, 0);
- if (returnValue == STDFU_NOERROR)
- {
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
-
- while (dfuStatus.bState != STATE_DFU_IDLE)
- {
- STDFU_ClrStatus(ref hDevice);
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
- }
-
- returnValue = STDFU_Dnload(ref hDevice, Command, 5, 0);
- if (returnValue == STDFU_NOERROR)
- {
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
-
- while (dfuStatus.bState != STATE_DFU_IDLE)
- {
- STDFU_ClrStatus(ref hDevice);
- returnValue = STDFU_GetStatus(ref hDevice, ref dfuStatus);
- }
-
- if (returnValue != STDFU_NOERROR)
- {
- throw new DownloadException("STDFU_Dnload returned " + returnValue.ToString("X8"));
- }
- }
- else
- {
- throw new DownloadException("STDFU_Dnload returned " + returnValue.ToString("X8"));
- }
- }
- else
- {
- throw new SelectConfigurationException("STDFU_SelectCurrentConfiguration returned " + returnValue.ToString("X8"));
- }
- }
-
- internal static void MassErase(
- IntPtr hDevice,
- bool outputMessages = false)
- {
- DfuStatus dfuStatus = new DfuStatus();
-
- byte[] EraseCommand = { 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-
- uint returnValue = STDFU_SelectCurrentConfiguration(ref hDevice, 0, 0, 1);
- if (returnValue == STDFU_NOERROR)
- {
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
-
- while (dfuStatus.bState != STATE_DFU_IDLE)
- {
- STDFU_ClrStatus(ref hDevice);
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
- }
-
- returnValue = STDFU_Dnload(ref hDevice, EraseCommand, 1, 0);
- if (returnValue == STDFU_NOERROR)
- {
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
- while (dfuStatus.bState != STATE_DFU_IDLE)
- {
- STDFU_ClrStatus(ref hDevice);
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
- }
- }
- else
- {
- throw new DownloadException($"{returnValue.ToString("X8")}");
- }
- }
- else
- {
- throw new SelectConfigurationException($"{returnValue.ToString("X8")}");
- }
- }
-
- internal static void WriteBlock(
- IntPtr hDevice,
- uint address,
- byte[] data,
- uint blockNumber)
- {
- uint returnValue;
- DfuStatus dfuStatus = new DfuStatus();
-
- if (0 == blockNumber)
- {
- SetAddressPointer(hDevice, address);
- }
-
- returnValue = STDFU_GetStatus(ref hDevice, ref dfuStatus);
- while (dfuStatus.bState != STATE_DFU_IDLE)
- {
- STDFU_ClrStatus(ref hDevice);
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
- }
-
- returnValue = STDFU_Dnload(ref hDevice, data, (uint)data.Length, (ushort)(blockNumber + 2));
-
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
- if (dfuStatus.bState != STATE_DFU_DOWNLOAD_BUSY)
- {
- throw new DownloadException("STDFU_Dnload returned " + returnValue.ToString("X8"));
- }
-
- while (dfuStatus.bState != STATE_DFU_IDLE)
- {
- STDFU_ClrStatus(ref hDevice);
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
- }
- }
-
- internal static void ReadBlock(
- IntPtr hDevice,
- uint address,
- byte[] data,
- uint blockNumber)
- {
- DfuStatus dfuStatus = new DfuStatus();
-
- if (0 == blockNumber)
- {
- SetAddressPointer(hDevice, address);
- }
-
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
- while (dfuStatus.bState != STATE_DFU_IDLE)
- {
- STDFU_ClrStatus(ref hDevice);
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
- }
-
- STDFU_Upload(ref hDevice, data, (uint)data.Length, (ushort)(blockNumber + 2));
-
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
- while (dfuStatus.bState != STATE_DFU_UPLOAD_IDLE)
- {
- STDFU_ClrStatus(ref hDevice);
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
- }
- }
-
- private static void SetAddressPointer(
- IntPtr hDevice,
- uint address)
- {
- byte[] command = new byte[5];
- DfuStatus dfuStatus = new DfuStatus();
-
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
- while (dfuStatus.bState != STATE_DFU_IDLE)
- {
- STDFU_ClrStatus(ref hDevice);
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
- }
-
- command[0] = 0x21;
- command[1] = (byte)(address & 0xFF);
- command[2] = (byte)((address >> 8) & 0xFF);
- command[3] = (byte)((address >> 16) & 0xFF);
- command[4] = (byte)((address >> 24) & 0xFF);
-
- STDFU_Dnload(ref hDevice, command, 5, 0);
-
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
- while (dfuStatus.bState != STATE_DFU_IDLE)
- {
- STDFU_ClrStatus(ref hDevice);
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
- }
- }
-
- internal static void Detach(IntPtr hDevice, uint address)
- {
- DfuStatus dfuStatus = new DfuStatus();
-
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
- while (dfuStatus.bState != STATE_DFU_IDLE)
- {
- STDFU_ClrStatus(ref hDevice);
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
- }
-
- byte[] command = new byte[5];
- command[0] = 0x21;
- command[1] = (byte)(address & 0xFF);
- command[2] = (byte)((address >> 8) & 0xFF);
- command[3] = (byte)((address >> 16) & 0xFF);
- command[4] = (byte)((address >> 24) & 0xFF);
-
- // set command pointer to the launch address
- STDFU_Dnload(ref hDevice, command, 5, 0);
-
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
- while (dfuStatus.bState != STATE_DFU_IDLE)
- {
- STDFU_ClrStatus(ref hDevice);
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
- }
-
- // send DFU detach command
- STDFU_Dnload(ref hDevice, command, 0, 0);
-
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
- STDFU_ClrStatus(ref hDevice);
- STDFU_GetStatus(ref hDevice, ref dfuStatus);
- }
- }
-
- #region Exceptions
-
- [Serializable]
- internal class SelectConfigurationException : Exception
- {
- public SelectConfigurationException()
- {
- }
-
- public SelectConfigurationException(string message) : base(message)
- {
- }
-
- public SelectConfigurationException(string message, Exception innerException) : base(message, innerException)
- {
- }
-
- protected SelectConfigurationException(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
- }
-
- [Serializable]
- internal class DownloadException : Exception
- {
- public DownloadException()
- {
- }
-
- public DownloadException(string message) : base(message)
- {
- }
-
- public DownloadException(string message, Exception innerException) : base(message, innerException)
- {
- }
-
- protected DownloadException(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
- }
-
- [Serializable]
- internal class DfuFileException : Exception
- {
- public DfuFileException()
- {
- }
-
- public DfuFileException(string message) : base(message)
- {
- }
-
- public DfuFileException(string message, Exception innerException) : base(message, innerException)
- {
- }
-
- protected DfuFileException(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
- }
-
- [Serializable]
- internal class WrongOrInvalidStringDescriptorException : Exception
- {
- public WrongOrInvalidStringDescriptorException()
- {
- }
-
- public WrongOrInvalidStringDescriptorException(string message) : base(message)
- {
- }
-
- public WrongOrInvalidStringDescriptorException(string message, Exception innerException) : base(message, innerException)
- {
- }
-
- protected WrongOrInvalidStringDescriptorException(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
- }
-
- [Serializable]
- internal class ErrorGettingStringDescriptorException : Exception
- {
- public ErrorGettingStringDescriptorException()
- {
- }
-
- public ErrorGettingStringDescriptorException(string message) : base(message)
- {
- }
-
- public ErrorGettingStringDescriptorException(string message, Exception innerException) : base(message, innerException)
- {
- }
-
- protected ErrorGettingStringDescriptorException(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
- }
-
- [Serializable]
- internal class ErrorGettingInterfaceDescriptorException : Exception
- {
- public ErrorGettingInterfaceDescriptorException()
- {
- }
-
- public ErrorGettingInterfaceDescriptorException(string message) : base(message)
- {
- }
-
- public ErrorGettingInterfaceDescriptorException(string message, Exception innerException) : base(message, innerException)
- {
- }
-
- protected ErrorGettingInterfaceDescriptorException(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
- }
-
- #endregion
-}
diff --git a/nanoFirmwareFlasher/StmDfuDevice.cs b/nanoFirmwareFlasher/StmDfuDevice.cs
index 988f1b3a..2499a9e6 100644
--- a/nanoFirmwareFlasher/StmDfuDevice.cs
+++ b/nanoFirmwareFlasher/StmDfuDevice.cs
@@ -5,13 +5,14 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management;
+using System.Text;
namespace nanoFramework.Tools.FirmwareFlasher
{
-
// STSW-ST7009
// DFU Development Kit package (Device Firmware Upgrade).
@@ -24,20 +25,6 @@ internal class StmDfuDevice
private static Guid s_dfuGuid = new Guid("3FE809AB-FB91-4CB5-A643-69670D52366E");
private readonly string _deviceId;
- private readonly IntPtr _hDevice = IntPtr.Zero;
- private readonly StDfu.DfuFunctionalDescriptor _dfuDescriptor;
-
- private readonly uint _numberOfBlocks;
- //private readonly uint _startAddress;
-
- private readonly List _sectorMap;
-
- private int targetIndex = 0;
-
- ///
- /// Maximum size of a block of data for writing, this is set depending on the bootloader version
- ///
- private UInt16 _maxWriteBlockSize = 1024;
///
/// Property with option for performing mass erase on the connected device.
@@ -57,8 +44,6 @@ internal class StmDfuDevice
// that follows the pattern: USB\\VID_0483&PID_DF11\\3380386D3134
public string DeviceId => _deviceId?.Split('\\', ' ')[2];
- public StDfu.UsbDeviceDescriptor _usbDescriptor { get; }
-
///
/// Option to output progress messages.
/// Default is .
@@ -71,8 +56,6 @@ internal class StmDfuDevice
/// ID of the device to connect to.
public StmDfuDevice(string deviceId = null)
{
- uint returnValue;
-
ManagementObjectCollection usbDevicesCollection;
// build a managed object searcher to find USB devices with the ST DFU VID & PID along with the device description
@@ -98,81 +81,12 @@ public StmDfuDevice(string deviceId = null)
return;
}
- // store USB device ID
- _deviceId = deviceId;
-
- // ST DFU is expecting a device path in the WQL pattern:
+ // ST DFU is expecting a device path with the WQL pattern:
// "\\?\USB#VID_0483&PID_DF11#3380386D3134#{3FE809AB-FB91-4CB5-A643-69670D52366E}"
// The GUID there is for the USB interface declared by DFU devices
- string devicePath = @"\\?\" + deviceId.Replace(@"\", "#") + @"#{" + s_dfuGuid.ToString() + "}";
-
- // open device
- returnValue = StDfu.STDFU_Open(devicePath, out _hDevice); //this causes an error using x64 on .netCore 2.1 due to trying to access the Registry
- if (returnValue != StDfu.STDFU_NOERROR)
- {
- throw new CantOpenDfuDeviceException(returnValue);
- }
-
- // read USB descriptor
- StDfu.UsbDeviceDescriptor usbDescriptor = new StDfu.UsbDeviceDescriptor();
- returnValue = StDfu.STDFU_GetDeviceDescriptor(ref _hDevice, ref usbDescriptor);
-
- if (returnValue == StDfu.STDFU_NOERROR)
- {
- _usbDescriptor = usbDescriptor;
-
- // check protocol version
- // update max write block size
- switch (_usbDescriptor.bcdDevice)
- {
- case 0x011A:
- case 0x0200:
- _maxWriteBlockSize = 1024;
- break;
-
- case 0x02100:
- case 0x2200:
- _maxWriteBlockSize = 2048;
- break;
-
- default:
- throw new BadDfuProtocolVersionException(usbDescriptor.bcdDevice.ToString("X4"));
- }
- }
- else
- {
- throw new CantReadUsbDescriptorException(returnValue);
- }
-
- // read DFU descriptor
- var dfuDescriptor = new StDfu.DfuFunctionalDescriptor();
- uint interfaceIndex = 0, alternates = 0;
- returnValue = StDfu.STDFU_GetDFUDescriptor(ref _hDevice, ref interfaceIndex, ref alternates, ref dfuDescriptor);
-
- if (returnValue == StDfu.STDFU_NOERROR)
- {
- _dfuDescriptor = dfuDescriptor;
-
- // Enable and disable programming choice, bitManifestationTolerant
- if (_dfuDescriptor.wTransfertSize == 8)
- {
- // Low Speed Devices
- _numberOfBlocks = 8;
- }
- if (_dfuDescriptor.wTransfertSize == 128)
- {
- // Full Speed Devices
- _numberOfBlocks = 128;
- }
- }
- else
- {
- throw new CantReadDfuDescriptorException(returnValue);
- }
-
- // create sector mapping for device
- _sectorMap = StDfu.CreateMappingFromDevice(_hDevice, alternates, dfuDescriptor);
+ // store USB device ID
+ _deviceId = @"\\?\" + deviceId.Replace(@"\", "#") + @"#{" + s_dfuGuid.ToString() + "}";
}
///
@@ -187,20 +101,28 @@ public void FlashDfuFile(string filePath)
throw new DfuFileDoesNotExistException();
}
- // load DFU file
-
- StDfu.DfuFile dfuFile = StDfu.LoadDfuFile(filePath, Verbosity);
-
// erase flash
if (DoMassErase)
{
- if (Verbosity >= VerbosityLevel.Normal)
- {
- Console.Write("Mass erase device...");
- }
+ Console.WriteLine("WARNING: mass erase is not currently supported for DFU devices.");
+ }
- StDfu.MassErase(_hDevice, Verbosity >= VerbosityLevel.Normal);
+ if (Verbosity >= VerbosityLevel.Normal)
+ {
+ Console.Write("Flashing device...");
+ }
+
+ // write flash, verify, reboot
+ // DFU is picky about the device path: requires it to be lower caps
+ if (!RunDfuCommandTool($" -d \"{filePath}\" -D {_deviceId.ToLowerInvariant()} -v -r ", out string messages))
+ {
+ // something went wrong
+ throw new DfuOperationFailedException();
+ }
+ // check for successfull message
+ if (messages.Contains("Successfully left DFU mode !"))
+ {
if (Verbosity >= VerbosityLevel.Normal)
{
Console.WriteLine(" OK");
@@ -208,122 +130,106 @@ public void FlashDfuFile(string filePath)
}
else
{
- //erase only the sections we will program
- if (Verbosity >= VerbosityLevel.Normal)
- {
- Console.Write("Erasing sectors to program...");
- }
-
- StDfu.DfuTarget dfuTarErase = dfuFile.DfuTargets[0];
+ // something went wrong
+ throw new DfuOperationFailedException();
+ }
+ }
- for (int nIdxElem = 0; nIdxElem < dfuTarErase.DfuElements.Length; ++nIdxElem)
- {
- StDfu.DfuElement dfuElem = dfuTarErase.DfuElements[nIdxElem];
+ ///
+ /// Search connected DFU devices.
+ ///
+ /// A collection of connected DFU devices.
+ public static List ListDfuDevices()
+ {
+ ManagementObjectCollection usbDevicesCollection;
- StDfu.PartialErase(_hDevice, dfuElem.Address, (uint)dfuElem.Data.Length, _sectorMap, Verbosity >= VerbosityLevel.Detailed);
- }
+ // build a managed object searcher to find USB devices with the ST DFU VID & PID along with the device description
+ using (var searcher = new ManagementObjectSearcher(@"SELECT * FROM Win32_PnPEntity WHERE DeviceID Like ""USB\\VID_0483&PID_DF11%"" AND Description Like ""STM Device in DFU Mode"" "))
+ usbDevicesCollection = searcher.Get();
- if (Verbosity >= VerbosityLevel.Normal)
- {
- Console.WriteLine(" OK");
- }
- }
+ // the split bellow is to get only the ID part of the USB ID
+ // that follows the pattern: USB\\VID_0483&PID_DF11\\3380386D3134
+ return usbDevicesCollection.OfType().Select(mo => (mo.Properties["DeviceID"].Value as string).Split('\\', ' ')[2]).ToList();
+ }
- // flash the device
- StDfu.DfuTarget dfuTarget = dfuFile.DfuTargets[targetIndex];
+ ///
+ /// Run the esptool one time
+ ///
+ /// the esptool command (e.g. write_flash) incl. all arguments (if needed)
+ /// StandardOutput and StandardError messages that the esptool prints out
+ /// true if the esptool exit code was 0; false otherwise
+ private bool RunDfuCommandTool(
+ string commandWithArguments,
+ out string messages)
+ {
+ // create the process start info
- if (Verbosity >= VerbosityLevel.Normal)
+ // prepare the process start of the esptool
+ Process dfuCommandTool = new Process();
+ dfuCommandTool.StartInfo = new ProcessStartInfo(Path.Combine(Program.ExecutingPath, "stdfu", "qmk-dfuse.exe"), commandWithArguments)
{
- Console.Write("Flashing device...");
- }
+ WorkingDirectory = Path.Combine(Program.ExecutingPath, "stdfu"),
+ UseShellExecute = false,
+ RedirectStandardError = true,
+ RedirectStandardOutput = true
+ };
- // write flash
- for (int elementIndex = 0; elementIndex < dfuTarget.DfuElements.Length; ++elementIndex)
+ // start esptool and wait for exit
+ if (dfuCommandTool.Start())
{
- StDfu.DfuElement dfuElement = dfuTarget.DfuElements[elementIndex];
-
- // Write the data in MaxWriteBlockSize blocks
- for (uint blockNumber = 0; blockNumber <= (uint)dfuElement.Data.Length / _maxWriteBlockSize; blockNumber++)
+ // if no progress output needed wait unlimited time until comment exits
+ if (Verbosity < VerbosityLevel.Detailed)
{
- // grab data for write and store it into a 2048 byte buffer
- byte[] buffer = dfuElement.Data.Skip((int)(_maxWriteBlockSize * blockNumber)).Take(_maxWriteBlockSize).ToArray();
-
- StDfu.WriteBlock(_hDevice, dfuElement.Address, buffer, blockNumber);
+ dfuCommandTool.WaitForExit();
}
}
-
- if (Verbosity >= VerbosityLevel.Normal)
+ else
{
- Console.WriteLine(" OK");
+ throw new EspToolExecutionException("Error starting DfuSeCommand!");
}
- if (Verbosity >= VerbosityLevel.Normal)
- {
- Console.Write("Verifying flash...");
- }
+ StringBuilder messageBuilder = new StringBuilder();
- // read back for confirmation
- for (int elementIndex = 0; elementIndex < dfuTarget.DfuElements.Length; ++elementIndex)
+ // showing progress is a little bit tricky
+ if (Verbosity >= VerbosityLevel.Detailed)
{
- StDfu.DfuElement dfuElement = dfuTarget.DfuElements[elementIndex];
-
- // read the data in MaxWriteBlockSize blocks
- for (uint blockNumber = 0; blockNumber <= (uint)dfuElement.Data.Length / _maxWriteBlockSize; blockNumber++)
+ // loop until esptool exit
+ while (!dfuCommandTool.HasExited)
{
- byte[] readBuffer = new byte[_maxWriteBlockSize];
- StDfu.ReadBlock(_hDevice, dfuElement.Address, readBuffer, blockNumber);
-
- // get data for the current block
- byte[] buffer = dfuElement.Data.Skip((int)(_maxWriteBlockSize * blockNumber)).Take(_maxWriteBlockSize).ToArray();
-
- // exit condition has to be tied with the buffer length because the data for the last block
- // can be shorter than the block max size
- for(int index = 0; index < buffer.Length; index++)
+ // loop until there is no next char to read from standard output
+ while (true)
{
- if(readBuffer[index] != buffer[index])
+ int next = dfuCommandTool.StandardOutput.Read();
+ if (next != -1)
+ {
+ // append the char to the message buffer
+ char nextChar = (char)next;
+ messageBuilder.Append((char)next);
+ // print progress and set the cursor to the beginning of the line (\r)
+ Console.Write(nextChar);
+ }
+ else
{
- Console.WriteLine("");
- Console.WriteLine($"Error verifying flash write. Check failed for block address 0x{dfuElement.Address + blockNumber * _maxWriteBlockSize:X8}.");
- throw new DfuVerificationFailedException();
+ break;
}
}
}
- }
- if (Verbosity >= VerbosityLevel.Normal)
- {
- Console.WriteLine(" OK");
+ // collect any last messages
+ messageBuilder.AppendLine(dfuCommandTool.StandardOutput.ReadToEnd());
+ messageBuilder.Append(dfuCommandTool.StandardError.ReadToEnd());
}
-
- if (Verbosity >= VerbosityLevel.Normal)
+ else
{
- Console.Write("Launching nanoBooter...");
+ // collect all messages
+ messageBuilder.AppendLine(dfuCommandTool.StandardOutput.ReadToEnd());
+ messageBuilder.Append(dfuCommandTool.StandardError.ReadToEnd());
}
- // always reboot with nanoBooter
- StDfu.Detach(_hDevice, 0x08000000);
-
- if (Verbosity >= VerbosityLevel.Normal)
- {
- Console.WriteLine(" OK");
- }
- }
+ messages = messageBuilder.ToString();
- ///
- /// Search connected DFU devices.
- ///
- /// A collection of connected DFU devices.
- public static List ListDfuDevices()
- {
- ManagementObjectCollection usbDevicesCollection;
-
- // build a managed object searcher to find USB devices with the ST DFU VID & PID along with the device description
- using (var searcher = new ManagementObjectSearcher(@"SELECT * FROM Win32_PnPEntity WHERE DeviceID Like ""USB\\VID_0483&PID_DF11%"" AND Description Like ""STM Device in DFU Mode"" "))
- usbDevicesCollection = searcher.Get();
-
- // the split bellow is to get only the ID part of the USB ID
- // that follows the pattern: USB\\VID_0483&PID_DF11\\3380386D3134
- return usbDevicesCollection.OfType().Select(mo => (mo.Properties["DeviceID"].Value as string).Split('\\', ' ')[2]).ToList();
+ // true if exit code was 0 (success)
+ return dfuCommandTool.ExitCode == 0;
}
}
}
diff --git a/nanoFirmwareFlasher/nanoFirmwareFlasher.csproj b/nanoFirmwareFlasher/nanoFirmwareFlasher.csproj
index 47a882ef..0ff36aff 100644
--- a/nanoFirmwareFlasher/nanoFirmwareFlasher.csproj
+++ b/nanoFirmwareFlasher/nanoFirmwareFlasher.csproj
@@ -53,7 +53,7 @@
-
+
true
content\stdfu;contentFiles\stdfu