├── .github └── workflows │ ├── close-stale.yml │ ├── lock-closed.yml │ └── unlock-reopened.yml ├── .gitignore ├── LICENSE ├── README.md ├── doc ├── Linux.md ├── Module_Connections.md ├── New_Bootloader.md ├── Serial_Monitor.md └── Troubleshooting.md ├── img ├── cp2102.png ├── dfu-recovery.png ├── flash-multi.jpg ├── maple-dfu-no-driver.png ├── maple-dfu-with-driver.png ├── maple-dfu.jpg ├── maple-reset.jpg ├── maple-usb-no-bootloader.png ├── maple-usb.png ├── serial-monitor.jpg └── zadig.jpg ├── linux ├── bootloader │ ├── AtmegaMultiBoot.hex │ ├── StmMulti4in1_Legacy.bin │ └── StmMulti4in1_StickyDfu.bin ├── default.nix ├── flash-multi ├── multi-bootreloader └── tools │ ├── 32bit │ ├── avrdude │ ├── avrdude.conf │ ├── dfu-util │ ├── maple-reset │ └── stm32flash │ ├── 45-maple.rules │ ├── 64bit │ ├── avrdude │ ├── avrdude.conf │ ├── dfu-util │ ├── maple-reset │ └── stm32flash │ ├── BootReloader_Legacy.bin │ ├── BootReloader_StickyDfu.bin │ ├── install.sh │ ├── macos │ ├── avrdude │ ├── avrdude.conf │ ├── dfu-util │ ├── maple-reset │ └── stm32flash │ └── src │ └── maple-reset │ └── maple-reset.c └── src ├── Multi Logo Tall.bmp ├── Multi Logo.bmp ├── flash-multi.iss ├── flash-multi.nsi ├── flash-multi.sln ├── flash-multi ├── CenterWinDialog.cs ├── ComPort.cs ├── Devices │ ├── MapleDevice.cs │ ├── SerialDevice.cs │ └── UsbAspDevice.cs ├── Dialogs │ ├── DfuRecoveryDialog.Designer.cs │ ├── DfuRecoveryDialog.cs │ ├── DfuRecoveryDialog.resx │ ├── SerialMonitor.Designer.cs │ ├── SerialMonitor.cs │ ├── SerialMonitor.fr.resx │ ├── SerialMonitor.resx │ ├── UsbSupportErrorDialog.Designer.cs │ ├── UsbSupportErrorDialog.cs │ ├── UsbSupportErrorDialog.resx │ ├── UsbSupportWarningDialog.Designer.cs │ ├── UsbSupportWarningDialog.cs │ └── UsbSupportWarningDialog.resx ├── Eeprom │ ├── AtmegaEepromUtils.cs │ └── Stm32EepromUtils.cs ├── FileUtils.cs ├── FlashMulti.Designer.cs ├── FlashMulti.cs ├── FlashMulti.fr.resx ├── FlashMulti.resx ├── GPL.txt ├── Localization │ ├── Strings.Designer.cs │ └── Strings.resx ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── README.txt ├── RunCommand.cs ├── UpdateCheck.cs ├── UsbDeviceInfo.cs ├── UsbNotification.cs ├── app.config ├── flash-multi.csproj ├── icon.ico ├── license.txt ├── packages.config └── stylecop.json ├── make_release.bat ├── make_release.sh └── tools ├── bootloaders ├── AtmegaMultiBoot.hex ├── StmMulti4in1_Legacy.bin └── StmMulti4in1_StickyDfu.bin ├── drivers ├── install_drivers.bat └── wdi-simple.exe └── tools ├── BootReloader_Legacy.bin ├── BootReloader_StickyDfu.bin ├── avrdude.conf ├── avrdude.exe ├── dfu-util-multi.exe ├── erase1.bin ├── erase118.bin ├── erase120.bin ├── erase32.bin ├── libusb-1.0.dll ├── libusb0.dll ├── maple-reset.exe └── stm32flash.exe /.github/workflows/close-stale.yml: -------------------------------------------------------------------------------- 1 | # 2 | # close-stale.yml 3 | # Close open issues after a period of inactivity 4 | # 5 | 6 | name: Close Stale Issues 7 | 8 | on: 9 | schedule: 10 | - cron: '0 1,13 * * *' 11 | 12 | jobs: 13 | stale: 14 | name: Close Stale Issues 15 | if: github.repository == 'benlye/flash-multi' 16 | 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - uses: actions/stale@v3 21 | with: 22 | repo-token: ${{ secrets.GITHUB_TOKEN }} 23 | stale-issue-message: > 24 | This issue has been automatically marked as stale because it has not had any 25 | recent activity. Please add a reply if you want to keep this issue active, 26 | otherwise it will be automatically closed in 5 days. 27 | days-before-stale: 14 28 | days-before-close: 5 29 | exempt-issue-labels: 'enhancement,work-in-progress' 30 | -------------------------------------------------------------------------------- /.github/workflows/lock-closed.yml: -------------------------------------------------------------------------------- 1 | # 2 | # lock-closed.yml 3 | # Lock closed issues after a period of inactivity 4 | # 5 | 6 | name: Lock Closed Issues 7 | 8 | on: 9 | schedule: 10 | - cron: '0 1,13 * * *' 11 | 12 | jobs: 13 | lock: 14 | name: Lock Closed Issues 15 | if: github.repository == 'benlye/flash-multi' 16 | 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - uses: dessant/lock-threads@v2 21 | with: 22 | github-token: ${{ github.token }} 23 | process-only: 'issues' 24 | issue-lock-inactive-days: '21' 25 | issue-exclude-created-before: '' 26 | issue-exclude-labels: 'no-locking' 27 | issue-lock-labels: '' 28 | issue-lock-comment: > 29 | This issue has been automatically locked because there was no further activity 30 | after it was closed. Please open a new issue for any related problems. 31 | issue-lock-reason: '' 32 | -------------------------------------------------------------------------------- /.github/workflows/unlock-reopened.yml: -------------------------------------------------------------------------------- 1 | # 2 | # unlock-reopened.yml 3 | # Unlock an issue whenever it is re-opened 4 | # 5 | 6 | name: Unlock Reopened Issue 7 | 8 | on: 9 | issues: 10 | types: [reopened] 11 | 12 | jobs: 13 | unlock: 14 | name: Unlock Reopened Issues 15 | if: github.repository == 'benlye/flash-multi' 16 | 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - uses: OSDKDev/unlock-issues@v1.1 21 | with: 22 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | *.rptproj.bak 244 | 245 | # SQL Server files 246 | *.mdf 247 | *.ldf 248 | *.ndf 249 | 250 | # Business Intelligence projects 251 | *.rdl.data 252 | *.bim.layout 253 | *.bim_*.settings 254 | *.rptproj.rsuser 255 | 256 | # Microsoft Fakes 257 | FakesAssemblies/ 258 | 259 | # GhostDoc plugin setting file 260 | *.GhostDoc.xml 261 | 262 | # Node.js Tools for Visual Studio 263 | .ntvs_analysis.dat 264 | node_modules/ 265 | 266 | # Visual Studio 6 build log 267 | *.plg 268 | 269 | # Visual Studio 6 workspace options file 270 | *.opt 271 | 272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 273 | *.vbw 274 | 275 | # Visual Studio LightSwitch build output 276 | **/*.HTMLClient/GeneratedArtifacts 277 | **/*.DesktopClient/GeneratedArtifacts 278 | **/*.DesktopClient/ModelManifest.xml 279 | **/*.Server/GeneratedArtifacts 280 | **/*.Server/ModelManifest.xml 281 | _Pvt_Extensions 282 | 283 | # Paket dependency manager 284 | .paket/paket.exe 285 | paket-files/ 286 | 287 | # FAKE - F# Make 288 | .fake/ 289 | 290 | # JetBrains Rider 291 | .idea/ 292 | *.sln.iml 293 | 294 | # CodeRush 295 | .cr/ 296 | 297 | # Python Tools for Visual Studio (PTVS) 298 | __pycache__/ 299 | *.pyc 300 | 301 | # Cake - Uncomment if you are using it 302 | # tools/** 303 | # !tools/packages.config 304 | 305 | # Tabs Studio 306 | *.tss 307 | 308 | # Telerik's JustMock configuration file 309 | *.jmconfig 310 | 311 | # BizTalk build output 312 | *.btp.cs 313 | *.btm.cs 314 | *.odx.cs 315 | *.xsd.cs 316 | 317 | # OpenCover UI analysis results 318 | OpenCover/ 319 | 320 | # Azure Stream Analytics local run output 321 | ASALocalRun/ 322 | 323 | # MSBuild Binary and Structured Log 324 | *.binlog 325 | 326 | # NVidia Nsight GPU debugger configuration file 327 | *.nvuser 328 | 329 | # MFractors (Xamarin productivity tool) working folder 330 | .mfractor/ 331 | 332 | # Coverity 333 | cov-int/ 334 | cov-int.zip 335 | 336 | # nix stuff 337 | **/result 338 | -------------------------------------------------------------------------------- /doc/Linux.md: -------------------------------------------------------------------------------- 1 | # Flashing From Linux or Mac 2 | A bash script and toolchain is provided for flashing Multiprotocol modules from Linux and Mac operating systems. 3 | 4 | Like the Flash Multi Window application, the Linux and Mac script will automatically determine which upload method to use, will preserve the EEPROM data during flashes, and will write the bootloader as needed. 5 | 6 | ## Installing 7 | 1. Download and extract the latest Linux release, for example: 8 | 9 | ``` 10 | wget https://github.com/benlye/flash-multi/releases/download/0.6.0/flash-multi-0.6.0.tar.gz 11 | tar -xvzf flash-multi-0.6.0.tar.gz 12 | ``` 13 | 14 | 1. Change to the flash-multi directory, for example: 15 | 16 | `cd flash-multi-0.6.0` 17 | 18 | 1. Configure serial device permissions by running `tools/install.sh` as root to update the udev rules and add the current user to the dialout group, e.g.: 19 | 20 | `sudo ./tools/install.sh` 21 | 22 | If you prefer you can configure the permissions manually, for example: 23 | ``` 24 | sudo cp -v ./tools/45-maple.rules /etc/udev/rules.d/45-maple.rules 25 | sudo chown root:root /etc/udev/rules.d/45-maple.rules 26 | sudo chmod 644 /etc/udev/rules.d/45-maple.rules 27 | sudo udevadm control --reload-rules 28 | sudo usermod -a -G plugdev $USER 29 | sudo usermod -a -G dialout $USER 30 | ``` 31 | ### Mac 32 | macOS requires the libusb library to be installed. The easiest way to install the library is using the Homebrew package manager for macOS by running the two commands below in a Terminal. 33 | 34 | 1. Install Homebrew 35 | 36 | `/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"` 37 | 38 | 1. Use Homebrew to install libusb 39 | 40 | `brew install libusb` 41 | 42 | ## Use 43 | 1. Download the latest pre-compiled firmware from https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/releases 44 | 1. Plug in your Multiprotocol module 45 | 1. Run the flash-multi shell script, specifiying the serial device and firmware file: 46 | 47 | `./flash-multi -f [firmware file] -p [serial device]` 48 | 49 | For example: 50 | 51 | `./flash-multi -f /tmp/multi-stm-opentx-aetr-inv-v1.2.1.85.bin -p /dev/ttyUSB0 ` 52 | 53 | *Note: On OSX the device might be `/dev/tty.SLAB_USBtoUART` 54 | 55 | For firmware compiled from recent source code the ouput will look similar to what is shown below, firmware from older source will not display information about the firmware configuration: 56 | 57 | ``` 58 | ben@ben-ubuntu:~/flash-multi-0.4.3$ ./flash-multi -f /tmp/multi-stm-opentx-aetr-inv-v1.2.1.85.bin -p /dev/ttyUSB0 59 | flash-multi 0.4.3 60 | 61 | This program is Free Sofware and has NO WARRANTY. 62 | https://github.com/benlye/flash-multi/ 63 | 64 | Multi Firmware Version: 1.2.1.85 (STM32) 65 | Expected Channel Order: AETR 66 | Multi Telemetry Type: OpenTX 67 | Invert Telemetry Enabled: True 68 | Flash From Radio Enabled: True 69 | Bootloader Enabled: True 70 | Serial Debug Enabled: False 71 | 72 | Proceed with firmware update? [Y]es or [N]o:y 73 | 74 | Attempting serial upload using stm32flash 75 | 76 | [1/3] Erasing flash... 77 | ./tools/64bit/stm32flash -o -S 0x8000000:129024 -b 115200 "/dev/ttyUSB0" 78 | stm32flash Arduino_STM32_0.9 79 | 80 | http://github.com/rogerclarkmelbourne/arduino_stm32 81 | 82 | Interface serial_posix: 115200 8E1 83 | Version : 0x22 84 | Option 1 : 0x00 85 | Option 2 : 0x00 86 | Device ID : 0x0410 (Medium-density) 87 | - RAM : 20KiB (512b reserved by bootloader) 88 | - Flash : 128KiB (sector size: 4x1024) 89 | - Option RAM : 16b 90 | - System RAM : 2KiB 91 | Erasing flash 92 | 93 | [2/3] Writing bootloader... 94 | ./tools/64bit/stm32flash -v -e 0 -g 0x8000000 -b 115200 -w "./bootloader/StmMulti4in1.bin" "/dev/ttyUSB0" 95 | stm32flash Arduino_STM32_0.9 96 | 97 | http://github.com/rogerclarkmelbourne/arduino_stm32 98 | 99 | Using Parser : Raw BINARY 100 | Interface serial_posix: 115200 8E1 101 | Version : 0x22 102 | Option 1 : 0x00 103 | Option 2 : 0x00 104 | Device ID : 0x0410 (Medium-density) 105 | - RAM : 20KiB (512b reserved by bootloader) 106 | - Flash : 128KiB (sector size: 4x1024) 107 | - Option RAM : 16b 108 | - System RAM : 2KiB 109 | Write to memory 110 | Wrote and verified address 0x08001ff0 (100.00%) Done. 111 | 112 | Starting execution at address 0x08000000... done. 113 | 114 | [3/3] Writing firmware... 115 | ./tools/64bit/stm32flash -v -s 8 -e 0 -g 0x8002000 -b 115200 -w "/tmp/multi-stm-opentx-aetr-inv-v1.2.1.85.bin" "/dev/ttyUSB0" 116 | stm32flash Arduino_STM32_0.9 117 | 118 | http://github.com/rogerclarkmelbourne/arduino_stm32 119 | 120 | Using Parser : Raw BINARY 121 | Interface serial_posix: 115200 8E1 122 | Version : 0x22 123 | Option 1 : 0x00 124 | Option 2 : 0x00 125 | Device ID : 0x0410 (Medium-density) 126 | - RAM : 20KiB (512b reserved by bootloader) 127 | - Flash : 128KiB (sector size: 4x1024) 128 | - Option RAM : 16b 129 | - System RAM : 2KiB 130 | Write to memory 131 | Wrote and verified address 0x08018954 (100.00%) Done. 132 | 133 | Starting execution at address 0x08002000... done. 134 | 135 | Firmware flashed successfully. 136 | 137 | ``` 138 | 139 | # Using `nix` 140 | 141 | In case you happen to have [`nix`](https://nixos.org/explore.html) installed, 142 | you can simply use the `default.nix` file in the linux folder to build a 143 | compatible derivation of both `flash-multi` and `multi-bootreloader`. To 144 | install it in your users environment, simply run `nix-env -f . -i`. 145 | 146 | Beware: This does not alter udev rules, so you likely will run into permission 147 | problems with the DFU device and/or the serial device. Possible solution in 148 | descending level of recommendability: 149 | 150 | + install appropiate udev rules in your system 151 | + run the script in question as `root` user 152 | + run `while true; do sudo chown $USER /dev/bus/usb/*; done` while using the 153 | script. Afterwards run `sudo udevadm control --reload-rules && udevadm trigger` to 154 | reaply all udev rules in question. 155 | -------------------------------------------------------------------------------- /doc/Module_Connections.md: -------------------------------------------------------------------------------- 1 | # Connecting Your Multiprotocol Module 2 | There are three ways that a Multiprotocol module can be connected to a PC and knowing which you can (or should) use can be confusing. The purpose of this page is to help you to identify and use your device's connection(s). 3 | 4 | The three connection types are: 5 | * Native USB port 6 | * External USB-to-serial Adapter 7 | * Internal USB-to-serial Adapter 8 | 9 | The connections available to you will depend on the specific module you have. 10 | 11 | **Note:** 'FTDI' is commonly used as a synonym for USB-to-serial, but is in fact one specific chip used in USB-to-serial adapters. For the purpose of the Flash Multi documentation 'FTDI Adapter' means 'USB-to-serial Adapter' anywhere it may be used. 12 | 13 | ## Native USB Port 14 | The 'native' USB port (also known as the Maple port) is a USB port which interfaces directly with the STM32 micro-controller in the Multiprotocol module. 15 | 16 | Using the native port requires that, at a minimum, the USB bootloader has been flashed to the module. 17 | 18 | **Note:** Multiprotocol module manufacturers only recently started shipping their modules with the USB bootloader installed. You may have a module which has a native USB port, but does not have the bootloader installed. 19 | 20 | _**Tip:** Using the native USB port is the fastest way to flash your Multiprotocol module._ 21 | 22 | ### Drivers 23 | The native USB port requires two drivers, Maple Serial and Maple DFU, both of which are included with Flash Multi. 24 | 25 | ### Modes 26 | The native USB port has two modes, USB and DFU. DFU, or Device Firmware Update, mode is used when flashing the module. In USB mode the module appears as a serial (COM) port. 27 | 28 | Assuming the PC has the drivers installed, and the module has the correct (USB-enabled) firmware installed, when the module is plugged in it will briefly appear as a Maple DFU device and then reappear as a Maple Serial device (COM port). 29 | 30 | Flash Multi will automatically switch the module into DFU mode during the firmware flash process. 31 | 32 | ### How it Appears 33 | The native USB device has a device ID of `VID_1EAF&PID_0003` in DFU mode or `VID_1EAF&PID_0004` in USB mode. It can appear differently in Device Manager, depending on what firmware, bootloader, and drivers are installed. 34 | 35 | #### No Bootloader 36 | Windows will report an unrecognized and/or malfunctioning USB device. 37 | 38 | If there is no bootloader installed, it doesn't matter whether the module has firmware installed or not, or whether or not any installed firmware was built with or without USB support, Windows won't recognize the device and will probably tell you it's malfunctioning. 39 | 40 | **Note:** This will also happen if you forget to remove the `BOOT0` jumper before connecting the native USB port! 41 | 42 | #### No Drivers Installed 43 | Windows will detect the module as `Maple` under `Other devices`. There will be a yellow exclamation on the device and double-clicking it will tell you that the drivers are not installed. 44 | 45 | #### Drivers and Bootloader Installed, but firmware doesn't have USB support (or no firmware is present) 46 | Windows will detect the module as `Maple 003` under `Other devices`. 47 | 48 | #### Bootloader, Drivers, and Firmware Installed 49 | In USB mode, the module will appear as a serial (COM) port under `Ports (COM & LPT)`. In DFU mode, the module will appear as `Maple DFU` under `libusb-win32 devices`. Congratulations! 50 | 51 | ## External USB-to-serial Adapter 52 | An _external_ USB-to-serial adapter is a small USB device which provides a USB-to-serial interface. The adapter is used to connect to the serial pins on the STM32 micro-controller. Common USB-to-serial adapters use well-known chips such as `FTDI`, `FT232RL`, `CH340`, `CP2102`. 53 | 54 | Serial support is built into the STM32 and can _always_ be used to program the device. An external USB-to-serial adapter is a useful tool to have as it will ensure you can always recover your Multiprotocol module from a bad firmware flash, should one occur. 55 | 56 | Using an external USB-to-serial adapter to flash the module requires connecting a special pin on the board called `BOOT0` to 5V. There is usually a header, or connections for a header, for this on the board and the connection is made by placing a jumper on two pins to make the connection. 57 | 58 | ### Drivers 59 | Windows 10 includes drivers for many USB-to-serial adapters, but not all. Older version of Windows will typically need drivers installed manually. You should refer to your USB-to-serial adapter's instructions. 60 | 61 | ### How it Appears 62 | With the correct drivers installed, your USB-to-serial adapter should appear as a serial (COM) port in Device Manager. 63 | 64 | ## Internal USB-to-Serial Adapter 65 | The _internal_ USB-to-serial adapter is (at this time) unique to newer Jumper JP4IN1 modules, such as the module shipped with the Jumper T16. 66 | 67 | The _internal_ USB-to-serial adapter in the JP4IN1 is functionally the same as an _external_ USB-to-serial adapter except that it does not require manually connecting the `BOOT0` pin, because `BOOT0` is hard-wired to the USB port. 68 | 69 | ### Drivers 70 | The _internal_ USB-to-serial adapter in the JP4IN1 requires the Silicon Labs CP210x driver to be manually installed on all versions of Windows. The driver can be downloaded from https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers. 71 | 72 | ### How it Appears 73 | With the CP210x driver installed, the device will appear as a serial (COM) port in Device Manager. 74 | -------------------------------------------------------------------------------- /doc/New_Bootloader.md: -------------------------------------------------------------------------------- 1 | # New MULTI-Module Bootloader 2 | 3 | If you have: 4 | * A radio with an internal MULTI-Module (e.g. T16, T18, TX16S), or 5 | * A Jumper JP4IN1-SE or RadioBoss JP4IN1 MULTI-Module, or 6 | * Any other MULTI-Module which is identified as a CP2102 device when you plug it, or 7 | * Any Atmega32p-based MULTI-Module 8 | 9 | You can stop reading now - this does not matter to you. 10 | 11 | **If you have a Jumper JP4IN1, iRangeX IRX4, Banggood, or any other STM32 MULTI-Module, please read this information - if you use the USB port on your module, you will need to take action!** 12 | 13 | If you want to cut to the chase, skip to the [what you need to do](#what-you-need-to-do) section. 14 | 15 | ## Introduction 16 | The latest version of Flash Multi, v0.5.0, gives you the ability to flash a new bootloader to your MULTI-Module. 17 | 18 | The new bootloader changes the behaviour of the USB port on your MULTI-module when you plug the module into a computer. 19 | 20 | | Action | Old Bootloader (COM Port Mode) | New Bootloader (Sticky DFU Mode) | 21 | | --- | --- | --- | 22 | | Connect the module to the computer, radio is off | Module starts in DFU mode then switches to COM port mode | Module starts in DFU mode and stays in DFU mode | 23 | | Connect the module to the computer, radio is on | Computer will detect a USB COM port | Computer will detect an unidentified device | 24 | 25 | ## Reason for Change 26 | Historically, the MULTI-Module firmware has always included code to make the USB COM port work when the module is running. However, the USB COM port is only used in two ways: 27 | * Switching the module to firmware update (DFU) mode when it is being flashed by using Flash Multi or the Arduino IDE 28 | * Debug output when running a debug-enabled build (typically only used by developers) 29 | 30 | And, there is never need for an internal MULTI-Module to have the USB COM port code, but it was always included. When this decision was made the firmware was around 80KB, and we had plenty of free space in the 128KB available flash on the STM32 MCU. 31 | 32 | Fast-forward three years and we have all but run out of space in the STM32. In an effort to free some space up, we are removing USB support from the firmware. **This change saves 5KB of flash.** This may not seem like much, but it's room for several more protocols. 33 | 34 | **Firmware without USB support will start to be released later in 2020.** 35 | 36 | Because we're removing the mechanism that would allow flashing tools to put the module into DFU mode, we have to provide a different way to do that. 37 | 38 | This is where the new bootloader comes in - it keeps the module in DFU mode when it is plugged in via USB, removing the need to use the COM port to switch it into DFU mode. 39 | 40 | ## What you need to do 41 | **You will need to use Flash Multi to upgrade the bootloader on your MULTI-Module _before_ you flash firmware which does not have USB support.** 42 | 43 | ### Upgrading to the new bootloader 44 | There is a one-time process to update the bootloader on the module. After the bootloader upgrade you will need to flash new firmware to your module. 45 | 46 | 1. Launch Flash Multi 47 | 1. Tell Flash Multi to use the new bootloader (Flash Multi v0.5.x only; not required for v0.6.0 or higher): 48 | 1. Click **Advanced** -> **Settings** -> **USB Port Mode** -> **Sticky DFU Mode (New)** 49 | 1. Plug your module in 50 | 1. Ensure that the correct COM port is selected 51 | 1. Flash the new bootloader to your module: 52 | 1. Click **Advanced** -> **Actions** -> **Flash Module Bootloader** 53 | 1. Wait for the red LED to go out 54 | 1. Unplug the module 55 | 56 | **You must pay attention to the instructions. DO NOT unplug the module until the red LED has gone out for at least two seconds.** 57 | 58 | You will now need to write new MULTI-Module firmware to the module in the normal way: 59 | 1. Check that the COM port is set to **DFU Device** 60 | 1. Select the firmware file 61 | 1. Click **Write Module** 62 | 63 | You will get a warning reminding you that you needed to update the bootloader, you may check the box to stop the message showing again. 64 | 65 | Once you have written new firmware to your module, if you unplug it and plug it back in, the module should stay in DFU mode with the red LED blinking continuously. 66 | 67 | ## Frequently Asked Questions 68 | ## When should I update the bootloader? 69 | You can do it any time after the release of Flash Multi v0.5.0. The new bootloader works with all previous MULTI-Module firmware releases. 70 | 71 | ### If I only ever flash my MULTI-Module from the radio do I have to do the bootloader update? 72 | No, you don't have to do it. You can also wait and do it later if you want to. 73 | 74 | ### How do I know which bootloader my MULTI-Module has? 75 | Plug it in via USB 76 | * If the red LED blinks rapidly then starts to blink slowly and the green LED comes on you have the old bootloader 77 | * If the red LED blinks rapidly continuously you have the new bootloader 78 | * If the green LED comes on and the red LED stays off you have a module which does not use the bootloader for the USB port 79 | 80 | ### I flashed new firmware without USB support from the radio and now my USB port doesn't work, how do I fix it? 81 | You have the old bootloader. Use Flash Multi to flash the module bootloader, as explained above. You will have to unplug and replug the module when instructed. 82 | 83 | ### I have to unplug and re-plug my module every time I flash it, how do I fix it? 84 | You have the old bootloader. Use Flash Multi to flash the module bootloader, as explained above. You will have to unplug and replug the module when instructed. 85 | 86 | ### I'm trying to update but I get a message saying no DFU device was found, and unplugging and re-plugging the module does nothing, how do I fix it? 87 | You need to reinstall the MULTI-Module device drivers. 88 | * Reset the module by unplugging it and plugging it back in 89 | * Click **Advanced** -> **Actions** -> **Upgrade USB Drivers** 90 | 91 | See [this page](/doc/Troubleshooting.md#re-installing-the-maple-dfu-device-drivers) for more details. 92 | 93 | ### Why doesn't this apply to JP4IN1-SE or Radioboss modules? 94 | They use a different USB interface which does not use DFU mode to flash firmware. They will work happily with the old or new bootloaders and do not require updating this way. 95 | 96 | ### Why doesn't this apply to radios with internal modules? 97 | Because internal modules don't have USB ports they do not require any update to work properly with the new firmware which does not have USB support. 98 | -------------------------------------------------------------------------------- /doc/Serial_Monitor.md: -------------------------------------------------------------------------------- 1 | # Serial Monitor 2 | The Serial Monitor can be used to view debug information emitted by a Multimodule which has been flashed with firmware with `DEBUG_SERIAL` enabled. 3 | 4 | This can be useful when debugging complex firmware issues, or when capturing data using the Multimodule's [XN297L dump](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/blob/master/docs/Advanced_XN297Ldump.md) feature to capture data from new transmitters so that new protocols can be added. 5 | 6 |

7 | 8 |

9 | 10 | ## Use 11 | To use the Serial Monitor simply select the serial (COM) port that the Multimodule is connected to and click the **Serial Monitor** button. 12 | 13 | When the Serial Monitor window opens it will open the serial port connection automatically. Once the window is open the serial port connection can be closed and re-opened as needed. 14 | 15 | If a firmware upload is started while the Serial Monitor window is open the connection will be automatically closed to allow the upload to occur, then be re-opened when the upload is complete. 16 | 17 | Content of the Serial Monitor window can be saved to a log file by clicking the **Save** button 18 | -------------------------------------------------------------------------------- /doc/Troubleshooting.md: -------------------------------------------------------------------------------- 1 | # Troubleshooting 2 | Fortunately it is nearly impossible to 'brick' an STM32, so whatever state your Multiprotocol module is in, it should be possible to recover it. 3 | 4 | 1. [Re-installing the Maple DFU device drivers](#re-installing-the-maple-dfu-device-drivers) 5 | 1. [Flashing fails with JP4IN1 in the radio](#flashing-fails-when-flashing-a-jp4in1-in-the-radio) 6 | 1. [Module stuck in DFU mode after flashing](#module-stuck-in-dfu-mode-after-flashing-and-cannot-be-re-flashed) 7 | 8 | ## Re-installing the Maple DFU device drivers 9 | If reading or writing your MULTI-Module fails, and the verbose output is like the example below, you need to replace the Maple DFU device driver with a different one. 10 | 11 | ``` 12 | Filter on vendor = 0x1eaf product = 0x0003 13 | Opening DFU capable USB device... ID 1eaf:0003 14 | Run-time device DFU version 0110 15 | Found DFU: [1eaf:0003] devnum=0, cfg=1, intf=0, alt=2, name="UNDEFINED" 16 | Claiming USB DFU Interface... 17 | Cannot claim interface 18 | ``` 19 | ### Solution 1 20 | Use the latest version of Flash Multi to update the DFU drivers. 21 | 22 | 1. Download and install Flash Multi 0.4.0 or newer 23 | 1. Extract the files and fun `flash-multi.exe` 24 | 1. Plug your MULTI-Module into the computer 25 | 1. Ensure that the correct COM port is selected 26 | 1. Click Advanced -> Actions -> Upgrade USB Drivers 27 | 1. Follow the on screen prompts to upgrade the drivers 28 | 1. Disconnect and reconnect the MULTI-Module 29 | 30 | ### Solution 2 31 | Use Zadig to replace the DFU drivers. 32 | 33 | 1. Download and extract or install the latest version of Zadig from https://zadig.akeo.ie/ 34 | 1. Put the MULTI-Module into DFU mode 35 | 1. Open a **Command Prompt** 36 | 1. Change to the directory where you have installed or extracted Flash Multi 37 | 1. Plug your MULTI-Module in, noting the COM port which appears in Device Manager 38 | 1. Run this command, substituting `COMX` for your COM port 39 | 40 | `.\tools\maple-reset.exe COMX` 41 | 42 | ![Maple Reset Output](/img/maple-reset.jpg) 43 | 44 | 1. Device Manager should now show the Maple DFU device 45 | 46 | ![Maple DFU Device](/img/maple-dfu.jpg) 47 | 1. Use Zadig to replace the driver 48 | 1. Run **Zadig** from the location where you installed or extracted it 49 | 1. Click **Options** -> **List all Devices** 50 | 1. In the drop-down device list select `Maple 003` or `Maple DFU`, whichever is listed 51 | 1. Set the right-hand driver selector to `libusbK (v3.0.7.0)` 52 | 1. Click the **Replace Driver** button 53 | 54 | ![Zadig](/img/zadig.jpg) 55 | 56 | ## Flashing fails when flashing a JP4IN1 in the radio 57 | If the module is in the radio, make sure that the radio is **switched off**. The JP4IN1 will only go into 'flashing mode' (i.e. BOOT0 mode) when it is powered up from the USB port. 58 | 59 | ## Module stuck in DFU mode after flashing and cannot be re-flashed 60 | If your module isn't working, it shows up in Device Manager as **Maple DFU**, and attempting to re-flash it via the native USB port fails with verbose output like this: 61 | ``` 62 | .\tools\dfu-util.exe -R -a 2 -d 1EAF:0003 -D "C:\Temp\Multi-STM_FTDI_INV_OPENTX-v1.2.1.67.bin" 63 | 64 | Lost Device after reset, assuming prod_id was incremented by oneNo DFU capable USB device found 65 | dfu-util - (C) 2007-2008 by OpenMoko Inc. 66 | 67 | This program is Free Software and has ABSOLUTELY NO WARRANTY 68 | ``` 69 | 70 | Most likely you have flashed a non-USB enabled firmware over the USB port, making the USB port (and the module) inoperable. 71 | 72 | Luckily, the USB bootloader always starts the module up briefly in DFU mode, and we can take advantage of that to re-flash it. 73 | 74 | ### Solution 75 | 1. Download or compile the correct, **USB-enabled**, firmware 76 | 1. Open a **Command Prompt** and change to the 'tools' sub-folder in the Flash Multi folder 77 | 78 | E.g.: 79 | `cd "C:\Program Files (x86)\FlashMulti\tools"` 80 | 81 | 1. Prepare the `dfu-util.exe` flash command, but don't run it yet: 82 | 83 | `dfu-util.exe -R -a 2 -d 1EAF:0003 -D "[firmware_file]"` 84 | 85 | E.g.: `dfu-util.exe -R -a 2 -d 1EAF:0003 -D "C:\Temp\Multi-STM_TXFLASH_INV_OPENTX-v1.2.1.67.bin"` 86 | 87 | 1. Unplug the module 88 | 1. Plug the module in and watch the red LED - it blinks very rapidly, then blinks slightly slower, then goes out 89 | 1. Unplug the module again 90 | 1. Plug the module in and as soon as the red LED is in the second phase, hit **[Enter]** in the Command Prompt to run the flash command 91 | 92 | You have about 0.5s to run the `dfu-util.exe` flash command while the red LED is in the second phase. 93 | 94 | You may need to try it a few times, but if you can hit enter in the command prompt as soon as the red LED changes to the second phase you will be able to re-flash the module and it will be back to normal. Once you've got the hang of the timing you'll be able to do it easily. 95 | 96 |

97 | 98 | **Note:** `dfu-util.exe` always gives this error at the end: 99 | 100 | `error resetting after download: usb_reset: could not reset device, win error: The system cannot find the file specified.` 101 | 102 | You can ignore it. 103 | -------------------------------------------------------------------------------- /img/cp2102.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/img/cp2102.png -------------------------------------------------------------------------------- /img/dfu-recovery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/img/dfu-recovery.png -------------------------------------------------------------------------------- /img/flash-multi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/img/flash-multi.jpg -------------------------------------------------------------------------------- /img/maple-dfu-no-driver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/img/maple-dfu-no-driver.png -------------------------------------------------------------------------------- /img/maple-dfu-with-driver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/img/maple-dfu-with-driver.png -------------------------------------------------------------------------------- /img/maple-dfu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/img/maple-dfu.jpg -------------------------------------------------------------------------------- /img/maple-reset.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/img/maple-reset.jpg -------------------------------------------------------------------------------- /img/maple-usb-no-bootloader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/img/maple-usb-no-bootloader.png -------------------------------------------------------------------------------- /img/maple-usb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/img/maple-usb.png -------------------------------------------------------------------------------- /img/serial-monitor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/img/serial-monitor.jpg -------------------------------------------------------------------------------- /img/zadig.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/img/zadig.jpg -------------------------------------------------------------------------------- /linux/bootloader/AtmegaMultiBoot.hex: -------------------------------------------------------------------------------- 1 | :107E0000112484B714BE9FEF9BB99CE395B991E010 2 | :107E100098B98370A9F08AEF80938500109284004E 3 | :107E200085E08093810096BBB09BFECF10928100CD 4 | :107E300093B186B181709C73892B8D3109F0B3D0D9 5 | :107E400082E08093C00088E18093C10086E0809347 6 | :107E5000C20081E28093C400259AC0E0D0E093E0A4 7 | :107E6000F92EEE24E39425E0D22E31E1C32EA9D0E1 8 | :107E7000813481F4A6D08EBBABD08EB3823811F49E 9 | :107E800085E006C08EB3813811F484E001C083E040 10 | :107E900091D086C0823411F484E103C0853419F492 11 | :107EA00085E09DD07DC0853541F48BD0C82F89D029 12 | :107EB000D0E0D82BCC0FDD1F72C0863521F484E0D2 13 | :107EC0008ED080E0E5CF843609F03DC07AD079D0FD 14 | :107ED000B82E77D0C11520E7D20718F000E011E0E6 15 | :107EE00004C0FE01F7BEE895F9CF6BD0F80181938D 16 | :107EF0008F01BE12FACFCE01905781159E4018F423 17 | :107F0000FE01F7BEE89564D0C115FEE7DF0708F073 18 | :107F100047C007B600FCFDCFFE01A0E0B1E08D91A7 19 | :107F20009D910C01E7BEE89511243296A03821E01E 20 | :107F3000B207A9F7FE01D7BEE89507B600FCFDCF52 21 | :107F4000C7BEE8952DC08437B1F43BD03AD0B82EE7 22 | :107F500038D03ED0FE01AC2EAB0C8F010F5F1F4F0F 23 | :107F6000849128D0A01205C02196BA94CB0DD11DC2 24 | :107F700017C0F801F2CF853739F42AD08EE11AD034 25 | :107F800085E918D08FE084CF813549F421D080E194 26 | :107F900011D08091C00086FFFCCF05D001C018D061 27 | :107FA00080E108D064CFE0E0F0E084918F3F09F0F9 28 | :107FB000099408959091C00095FFFCCF8093C6006E 29 | :107FC00008958091C00087FFFCCF8091C60008957E 30 | :107FD000F8DF803211F085E1EDDF84E1EBCFCF9364 31 | :107FE000C82FEFDFC150E9F7CF91F2CFA8950895E0 32 | :0C7FF000E0E6F0E098E1908380830895C3 33 | :0400000300007E007B 34 | :00000001FF 35 | -------------------------------------------------------------------------------- /linux/bootloader/StmMulti4in1_Legacy.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/linux/bootloader/StmMulti4in1_Legacy.bin -------------------------------------------------------------------------------- /linux/bootloader/StmMulti4in1_StickyDfu.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/linux/bootloader/StmMulti4in1_StickyDfu.bin -------------------------------------------------------------------------------- /linux/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs ? import {} }: 2 | 3 | with pkgs; 4 | 5 | stdenv.mkDerivation rec { 6 | name = "flash-multi"; 7 | 8 | src = ./.; 9 | 10 | nativeBuildInputs = [ autoPatchelfHook ]; 11 | buildInputs = [ libusb ]; 12 | 13 | installPhase = '' 14 | runHook preInstall 15 | mkdir -p $out/{bin,${name}} 16 | mv * $out/${name}/ 17 | ln -s $out/${name}/flash-multi $out/bin/ 18 | ln -s $out/${name}/multi-bootreloader $out/bin/ 19 | runHook postInstall 20 | ''; 21 | } 22 | -------------------------------------------------------------------------------- /linux/multi-bootreloader: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | shopt -s extglob 3 | 4 | # ********************************************************************* 5 | # Copyright (C) 2019 Ben Lye 6 | 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 3 of the License, or 10 | # (at your option) any later version. 11 | 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program. If not, see . 19 | # ********************************************************************* 20 | 21 | # Define the script version 22 | VERSION=0.2.0 23 | 24 | # Write the script header 25 | printf "multi-bootreloader $VERSION\n\nThis program is Free Software and has NO WARRANTY.\nhttps://github.com/benlye/flash-multi/\n\n"; 26 | 27 | # Prepare simple help text to display when needed 28 | USAGE="Usage: multi-bootreloader [options] -p [serial device]\n\nOptions:\n -h Print this message and exit\n -l Install legacy bootloader\n\n" 29 | 30 | # Get the command line options 31 | while getopts ":f:p:hl" opt; do 32 | case $opt in 33 | f) FWFILE="$OPTARG" 34 | ;; 35 | p) PORT="$OPTARG" 36 | ;; 37 | l) LEGACY="True" 38 | ;; 39 | h) printf "$USAGE"; exit 1 40 | ;; 41 | \?) printf "Invalid argument -$OPTARG\n\n"; >&2 42 | ;; 43 | :) printf "Missing value for argument -$OPTARG\n\n"; >&2 44 | ;; 45 | esac 46 | done 47 | 48 | # Pick the bootreloader file 49 | if [[ $LEGACY == "True" ]]; then 50 | FWFILE=./tools/BootReloader_Legacy.bin 51 | else 52 | FWFILE=./tools/BootReloader_StickyDfu.bin 53 | fi 54 | 55 | # Die if the firmware file doesn't exist 56 | if [ ! -f "$FWFILE" ]; then 57 | printf "ERROR: $FWFILE does not exist!\n\n"; 58 | exit 2; 59 | fi 60 | 61 | # Die if the firmware file isn't readable 62 | if [ ! -r "$FWFILE" ]; then 63 | printf "ERROR: $FWFILE cannot be read!\n\n"; 64 | exit 2; 65 | fi 66 | 67 | function confirm() { 68 | while true; do 69 | read -p "$1 [Y]es or [N]o: " 70 | case $(echo $REPLY | tr '[A-Z]' '[a-z]') in 71 | y|yes) echo "yes"; return ;; 72 | n|no) echo "no" ; return ;; 73 | esac 74 | done 75 | } 76 | 77 | function list_usb() 78 | { 79 | while IFS=: read key value; do 80 | key="${key##+( )}" 81 | value="${value##+( )}" 82 | case "$key" in 83 | "Product ID") 84 | p="${value% *}" 85 | ;; 86 | "Vendor ID") 87 | v="${value%% *}" 88 | ;; 89 | "Manufacturer") 90 | m="${value}" 91 | ;; 92 | "Location ID") 93 | l="${value}" 94 | printf "%s:%s %s (%s)\n" "$v" "$p" "$l" "$m" 95 | ;; 96 | esac 97 | done < <( system_profiler SPUSBDataType ) 98 | } 99 | 100 | # Check to see if a native STM32 USB device (Maple device) 101 | uname -a | grep "Darwin" 2>&1 1>/dev/null 102 | if [ $? -eq 0 ]; then 103 | MAPLE_USB_DEVICES=$(echo "$(list_usb)" | grep "1eaf" | awk '{ print $1}') 104 | else 105 | MAPLE_USB_DEVICES=$(lsusb | grep "1eaf") 106 | fi 107 | 108 | # Determine the mode of and attached STM32 device - DFU, Native (USB serial), or Unknown (not found) 109 | case $MAPLE_USB_DEVICES in 110 | *?(0x)1eaf:?(0x)0003*) 111 | MAPLE_DEVICE=DFU 112 | ;; 113 | *?(0x)1eaf:?(0x)0004*) 114 | MAPLE_DEVICE=Native 115 | ;; 116 | *) 117 | MAPLE_DEVICE=Unknown 118 | ;; 119 | esac 120 | 121 | # Check if port exists for Maple USB serial - there is no port needed for DFU 122 | if [ $MAPLE_DEVICE == "Native" ] ; then 123 | # Die if a serial port wasn't specified 124 | if [ "x" == "x$PORT" ]; then 125 | printf "ERROR: No port specified and no DFU-mode device found!\n\n"; 126 | printf "$USAGE" 127 | exit 1 128 | fi 129 | 130 | # Die if the serial port doesn't exist 131 | if [ ! -c "$PORT" ]; then 132 | printf "ERROR: $PORT does not exist!\n\n"; 133 | exit 3; 134 | fi 135 | fi 136 | 137 | # Die if there isn't a Maple device attached 138 | if [[ $MAPLE_DEVICE == "Unknown" ]] 139 | then 140 | # No Maple device 141 | printf "ERROR: No compatible MULTI-Module detected.\n\n" 142 | exit 2 143 | fi 144 | 145 | # Get the directory where the script is running. 146 | # DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) 147 | DIR=$(dirname "$0") 148 | 149 | # Determine the binaries to use based on the platform architecture 150 | uname -a | grep "Darwin" 2>&1 1>/dev/null 151 | if [ $? -eq 0 ]; then 152 | TOOLS_DIR="$DIR/tools/macos" 153 | GREP_ARGS="" 154 | STAT_ARGS="-f %z" 155 | else 156 | uname -m | grep "x86_64" 2>&1 1>/dev/null 157 | if [ $? -eq 0 ]; then 158 | TOOLS_DIR="$DIR/tools/64bit" 159 | else 160 | TOOLS_DIR="$DIR/tools/32bit" 161 | fi 162 | 163 | GREP_ARGS="-Pa" 164 | STAT_ARGS="--printf=%s" 165 | fi 166 | 167 | RESET_UTIL="$TOOLS_DIR/maple-reset" 168 | DFU_UTIL="$TOOLS_DIR/dfu-util" 169 | 170 | if [ ! -x $RESET_UTIL ]; then 171 | printf "ERROR: Required tool $RESET_UTIL does not exist or is not executable!\n\n"; exit 3; 172 | fi 173 | 174 | if [ ! -x $DFU_UTIL ]; then 175 | printf "ERROR: Required tool $DFU_UTIL does not exist or is not executable!\n\n"; exit 3; 176 | fi 177 | 178 | # Show the instructions 179 | printf "The MULTI-Module firmware will be replaced by an application which will upgrade the module's bootloader."; 180 | printf "\nOnce begun, DO NOT interrupt the process, otherwise the bootloader will be corrupted and the module will not function."; 181 | printf "\nIf this happens a USB-to-serial (FTDI) adapter can be used to re-program the module."; 182 | printf "\n\nThe upgrade takes 4-5 seconds and will be complete once the LED goes off and remains off for at least 5 seconds.\n\n"; 183 | 184 | # Ask the user to confirm 185 | if [[ "no" == $(confirm "Proceed with writing the BootReloader app?") ]] 186 | then 187 | printf "\nBootReloader aborted.\n\n" 188 | exit 0 189 | fi 190 | echo 191 | 192 | # Write the BootReloader app to the module 193 | printf "Attempting USB upload using dfu-util\n\n" 194 | 195 | STEP=1; 196 | NUM_STEPS=1; 197 | 198 | if [[ $MAPLE_DEVICE == "Native" ]] ; then 199 | NUM_STEPS=2; 200 | 201 | printf "[$STEP/$NUM_STEPS] Resetting to DFU mode...\n" 202 | printf "$RESET_UTIL $PORT\n"; 203 | "${RESET_UTIL}" $PORT; 204 | [ $? -ne 0 ] && printf "ERROR: Failed to reset device!\n\n" && exit 4; 205 | 206 | # Give the board time to reset to DFU mode 207 | sleep 1 208 | 209 | STEP=$((STEP+1)) 210 | fi 211 | 212 | printf "[$STEP/$NUM_STEPS] Writing BootReloader app...\n" 213 | printf "${DFU_UTIL} -d 1eaf:0003 -a 2 -D \"$FWFILE\" -R\n"; 214 | "${DFU_UTIL}" -d 1eaf:0003 -a 2 -D "$FWFILE" -R; 215 | [ $? -ne 0 ] && printf "\nERROR: Failed to write BootReloader!\n\n" && exit 5; 216 | 217 | # printf "\n\n"; 218 | printf "\n###################################################"; 219 | printf "\n# MULTI-Module bootloader upgrade started #"; 220 | printf "\n###################################################"; 221 | printf "\n\nIMPORTANT: DO NOT UNPLUG THE MULTI-MODULE UNTIL THE LED GOES OFF!"; 222 | printf "\n\nYou may unplug the module once the LED goes off and remains off for at least 5 seconds."; 223 | printf "\n\nYou now need to:"; 224 | printf "\n\t1. Unplug then reconnect the MULTI-Module (after the LED goes off)"; 225 | printf "\n\t2. Write new firmware to the MULTI-Module\n\n"; 226 | -------------------------------------------------------------------------------- /linux/tools/32bit/avrdude: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/linux/tools/32bit/avrdude -------------------------------------------------------------------------------- /linux/tools/32bit/dfu-util: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/linux/tools/32bit/dfu-util -------------------------------------------------------------------------------- /linux/tools/32bit/maple-reset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/linux/tools/32bit/maple-reset -------------------------------------------------------------------------------- /linux/tools/32bit/stm32flash: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/linux/tools/32bit/stm32flash -------------------------------------------------------------------------------- /linux/tools/45-maple.rules: -------------------------------------------------------------------------------- 1 | ATTRS{idProduct}=="0003", ATTRS{idVendor}=="1eaf", MODE="664", GROUP="plugdev" SYMLINK+="maple", ENV{ID_MM_DEVICE_IGNORE}="1" 2 | ATTRS{idProduct}=="0004", ATTRS{idVendor}=="1eaf", MODE="664", GROUP="plugdev" SYMLINK+="maple", ENV{ID_MM_DEVICE_IGNORE}="1" 3 | -------------------------------------------------------------------------------- /linux/tools/64bit/avrdude: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/linux/tools/64bit/avrdude -------------------------------------------------------------------------------- /linux/tools/64bit/dfu-util: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/linux/tools/64bit/dfu-util -------------------------------------------------------------------------------- /linux/tools/64bit/maple-reset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/linux/tools/64bit/maple-reset -------------------------------------------------------------------------------- /linux/tools/64bit/stm32flash: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/linux/tools/64bit/stm32flash -------------------------------------------------------------------------------- /linux/tools/BootReloader_Legacy.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/linux/tools/BootReloader_Legacy.bin -------------------------------------------------------------------------------- /linux/tools/BootReloader_StickyDfu.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/linux/tools/BootReloader_StickyDfu.bin -------------------------------------------------------------------------------- /linux/tools/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if sudo [ -w /etc/udev/rules.d ]; then 4 | echo "Copying Maple-specific udev rules..." 5 | sudo cp -v $(dirname "$0")/45-maple.rules /etc/udev/rules.d/45-maple.rules 6 | sudo chown root:root /etc/udev/rules.d/45-maple.rules 7 | sudo chmod 644 /etc/udev/rules.d/45-maple.rules 8 | echo "Reloading udev rules" 9 | sudo udevadm control --reload-rules 10 | echo "Adding current user to dialout and plugdev groups" 11 | sudo usermod -a -G plugdev $USER 12 | sudo usermod -a -G dialout $USER 13 | else 14 | echo "Couldn't copy to /etc/udev/rules.d/; Did you run the script as root? Does your distribution of Linux include udev?" 15 | fi 16 | -------------------------------------------------------------------------------- /linux/tools/macos/avrdude: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/linux/tools/macos/avrdude -------------------------------------------------------------------------------- /linux/tools/macos/dfu-util: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/linux/tools/macos/dfu-util -------------------------------------------------------------------------------- /linux/tools/macos/maple-reset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/linux/tools/macos/maple-reset -------------------------------------------------------------------------------- /linux/tools/macos/stm32flash: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/linux/tools/macos/stm32flash -------------------------------------------------------------------------------- /linux/tools/src/maple-reset/maple-reset.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2019 Ben Lye 2 | * 3 | * This program is free software; you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation; either version 2 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * Utility to send the reset sequence on RTS and DTR and chars 9 | * which resets the libmaple and causes the bootloader to be run 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | /* Function prototypes (belong in a seperate header file) */ 23 | int openserial(char *devicename); 24 | void closeserial(void); 25 | int setDTR(unsigned short level); 26 | int setRTS(unsigned short level); 27 | 28 | /* Two globals for use by this module only */ 29 | static int fd; 30 | static struct termios oldterminfo; 31 | 32 | /* Opens the serial port and sets RTS and DTR to LOW */ 33 | /* Returns 1 on success or 0 on failure */ 34 | int openserial(char *devicename) 35 | { 36 | struct termios attr; 37 | 38 | if ((fd = open(devicename, O_RDWR)) == -1) return 0; /* Error */ 39 | atexit(closeserial); 40 | 41 | if (tcgetattr(fd, &oldterminfo) == -1) return 0; /* Error */ 42 | attr = oldterminfo; 43 | attr.c_cflag |= CRTSCTS | CLOCAL; 44 | attr.c_oflag = 0; 45 | if (tcflush(fd, TCIOFLUSH) == -1) return 0; /* Error */ 46 | if (tcsetattr(fd, TCSANOW, &attr) == -1) return 0; /* Error */ 47 | 48 | return setRTS(0) && setDTR(0); 49 | } 50 | 51 | /* Closes the serial port */ 52 | void closeserial(void) 53 | { 54 | tcsetattr(fd, TCSANOW, &oldterminfo); 55 | close(fd); 56 | } 57 | 58 | /* Sets RTS to LOW or HIGH */ 59 | /* Returns 1 on success or 0 on failure */ 60 | int setRTS(unsigned short level) 61 | { 62 | int status; 63 | 64 | if (ioctl(fd, TIOCMGET, &status) == -1) { 65 | perror("setRTS(): TIOCMGET"); 66 | return 0; 67 | } 68 | 69 | if (level) status |= TIOCM_RTS; 70 | else status &= ~TIOCM_RTS; 71 | 72 | if (ioctl(fd, TIOCMSET, &status) == -1) { 73 | perror("setRTS(): TIOCMSET"); 74 | return 0; 75 | } 76 | return 1; 77 | } 78 | 79 | /* Sets RTS to LOW or HIGH */ 80 | /* Returns 1 on success or 0 on failure */ 81 | int setDTR(unsigned short level) 82 | { 83 | int status; 84 | 85 | if (ioctl(fd, TIOCMGET, &status) == -1) { 86 | perror("setDTR(): TIOCMGET"); 87 | return 0; 88 | } 89 | if (level) status |= TIOCM_DTR; 90 | else status &= ~TIOCM_DTR; 91 | if (ioctl(fd, TIOCMSET, &status) == -1) { 92 | perror("setDTR: TIOCMSET"); 93 | return 0; 94 | } 95 | return 1; 96 | } 97 | 98 | /* Main function of the program */ 99 | int main(int argc, char *argv[]) 100 | { 101 | printf("maple-reset 0.1\n\n"); 102 | printf("This program is Free Sofware and has NO WARRANTY\n\n"); 103 | 104 | if (argc != 2) 105 | { 106 | printf("Usage: maple-reset [serial device]\n\n"); 107 | return 1; 108 | } 109 | 110 | if (openserial(argv[1])) 111 | { 112 | if (setDTR(true) == 0) 113 | { 114 | fprintf(stderr, "Failed to set DTR\n\n"); 115 | return 1; 116 | } 117 | 118 | usleep(50000L); 119 | 120 | if (setDTR(false) == 0) 121 | { 122 | fprintf(stderr, "Failed to set DTR\n\n"); 123 | return 2; 124 | } 125 | usleep(50000L); 126 | 127 | if(!write(fd,"1EAF",4)) 128 | { 129 | fprintf(stderr, "Could not send string to device.\n\n"); 130 | return 3; 131 | } 132 | 133 | closeserial(); 134 | fprintf(stdout, "Reset sequence sent to %s\n\n", argv[1]); 135 | return 0; 136 | } 137 | else 138 | { 139 | fprintf(stderr, "Could not open %s\n\n", argv[1]); 140 | return -1; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/Multi Logo Tall.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/src/Multi Logo Tall.bmp -------------------------------------------------------------------------------- /src/Multi Logo.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/src/Multi Logo.bmp -------------------------------------------------------------------------------- /src/flash-multi.iss: -------------------------------------------------------------------------------- 1 | [Setup] 2 | AppName=Flash Multi 3 | AppVersion={#MyAppVersion} 4 | AppPublisher=Ben Lye 5 | AppPublisherURL=https://github.com/benlye/flash-multi 6 | DefaultDirName={commonpf}\FlashMulti 7 | DefaultGroupName=Flash Multi 8 | UninstallDisplayIcon={app}\flash-multi.exe 9 | Compression=lzma2 10 | SolidCompression=yes 11 | OutputDir=flash-multi\bin 12 | OutputBaseFilename=flash-multi-{#MyAppVersion} 13 | InfoAfterFile=.\installer_infoafter.txt 14 | DisableWelcomePage=no 15 | LicenseFile=flash-multi\license.txt 16 | 17 | [Files] 18 | Source: "flash-multi\bin\Release\*"; Excludes: "*.pdb"; Flags: replacesameversion promptifolder recursesubdirs; DestDir: {app}; Components: main 19 | 20 | [InstallDelete] 21 | Type: filesandordirs; Name: "{app}\bin" 22 | 23 | [Icons] 24 | Name: "{group}\Flash Multi"; Filename: "{app}\flash-multi.exe"; IconFilename: "{app}\flash-multi.exe"; Components: main 25 | 26 | [Components] 27 | Name: "main"; Description: "Flash Multi Application"; Types: full compact custom; Flags: fixed 28 | Name: "drivers"; Description: "Run Maple USB Driver Installer"; Types: full 29 | 30 | [Run] 31 | ; Install the drivers - https://github.com/pbatard/libwdi/blob/master/examples/wdi-simple.iss 32 | Filename: "{app}\drivers\wdi-simple.exe"; Flags: "runhidden"; Parameters: " --vid 0x1EAF --pid 0x0003 --type 1 --name ""Maple DFU"" --dest ""{tmp}\maple-dfu"" --progressbar={wizardhwnd} --timeout 120000"; StatusMsg: "Installing Maple DFU device driver (this may take a few seconds) ..."; Components: drivers 33 | Filename: "{app}\drivers\wdi-simple.exe"; Flags: "runhidden"; Parameters: " --vid 0x1EAF --pid 0x0004 --type 3 --name ""Maple Serial"" --dest ""{tmp}\maple-serial"" --progressbar={wizardhwnd} --timeout 120000"; StatusMsg: "Installing Maple Serial device driver (this may take a few seconds) ..."; Components: drivers 34 | -------------------------------------------------------------------------------- /src/flash-multi.nsi: -------------------------------------------------------------------------------- 1 | 2 | ; Plugins to Include 3 | !include MUI2.nsh 4 | !include "FileFunc.nsh" 5 | !include "nsProcess.nsh" 6 | !include "StrFunc.nsh" 7 | 8 | ; The name of the installer 9 | Name "Flash Multi" 10 | 11 | ; The file to write 12 | OutFile "flash-multi\bin\flash-multi-${VERSION}.exe" 13 | 14 | ; Use Unicode 15 | Unicode True 16 | 17 | ; The default installation directory 18 | InstallDir $PROGRAMFILES\FlashMulti 19 | 20 | ; Get the previous installation path from the registry 21 | InstallDirRegKey HKLM "Software\FlashMulti" "InstallDir" 22 | 23 | ; Add/Remove programs registry key 24 | !define AddRemoveProgsReg "Software\Microsoft\Windows\CurrentVersion\Uninstall\FlashMulti" 25 | 26 | ; Request application privileges 27 | RequestExecutionLevel admin 28 | 29 | ;-------------------------------- 30 | ; Variables 31 | Var StartMenuFolder 32 | 33 | ;-------------------------------- 34 | ; 'Declare' functions used in StrFunc.nsh 35 | ${StrRep} 36 | 37 | ;-------------------------------- 38 | ;Interface Settings 39 | !define MUI_ABORTWARNING 40 | !define MUI_HEADERIMAGE 41 | !define MUI_HEADERIMAGE_BITMAP ".\Multi Logo.bmp" 42 | !define MUI_HEADERIMAGE_RIGHT 43 | !define MUI_HEADERIMAGE_UNBITMAP ".\Multi Logo.bmp" 44 | !define MUI_WELCOMEFINISHPAGE_BITMAP ".\Multi Logo Tall.bmp" 45 | !define MUI_UNWELCOMEFINISHPAGE_BITMAP ".\Multi Logo Tall.bmp" 46 | 47 | ;-------------------------------- 48 | ; Installer pages 49 | 50 | ; Welcome page 51 | !insertmacro MUI_PAGE_WELCOME 52 | 53 | ; License page 54 | !define MUI_LICENSEPAGE_RADIOBUTTONS 55 | !insertmacro MUI_PAGE_LICENSE ".\flash-multi\bin\Release\license.txt" 56 | 57 | ; Components page 58 | !define MUI_COMPONENTSPAGE_NODESC 59 | !insertmacro MUI_PAGE_COMPONENTS 60 | 61 | ; Directory page 62 | !insertmacro MUI_PAGE_DIRECTORY 63 | 64 | ; Start menu page 65 | !define MUI_STARTMENUPAGE_DEFAULTFOLDER "Flash Multi" 66 | !define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKLM" 67 | !define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\FlashMulti" 68 | !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "StartMenuFolder" 69 | !insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder 70 | 71 | ; Files page 72 | !insertmacro MUI_PAGE_INSTFILES 73 | 74 | ; Finish page 75 | !define MUI_FINISHPAGE_NOAUTOCLOSE 76 | !define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\README.txt" 77 | !define MUI_FINISHPAGE_RUN "$INSTDIR\flash-multi.exe" 78 | !define MUI_FINISHPAGE_LINK 'https://github.com/benlye/flash-multi/' 79 | !define MUI_FINISHPAGE_LINK_LOCATION https://github.com/benlye/flash-multi/ 80 | !insertmacro MUI_PAGE_FINISH 81 | 82 | ;-------------------------------- 83 | ; Uninstaller pages 84 | !insertmacro MUI_UNPAGE_CONFIRM 85 | !insertmacro MUI_UNPAGE_INSTFILES 86 | 87 | ;-------------------------------- 88 | ;Languages 89 | !insertmacro MUI_LANGUAGE "English" 90 | 91 | ;-------------------------------- 92 | ; The stuff to install 93 | Section "Flash Multi" "flash_multi" 94 | 95 | SectionIn RO 96 | 97 | ; Set output path to the installation directory. 98 | SetOutPath $INSTDIR 99 | 100 | ; Get the files 101 | File /r ".\flash-multi\bin\Release\bootloaders" 102 | File /r ".\flash-multi\bin\Release\drivers" 103 | File /r ".\flash-multi\bin\Release\tools" 104 | File ".\flash-multi\bin\Release\flash-multi.exe" 105 | File ".\flash-multi\bin\Release\flash-multi.exe.config" 106 | File ".\flash-multi\bin\Release\GPL.txt" 107 | File ".\flash-multi\bin\Release\license.txt" 108 | File ".\flash-multi\bin\Release\README.txt" 109 | 110 | ; Write the uninstaller 111 | WriteUninstaller "$INSTDIR\uninstall.exe" 112 | 113 | ; Write the installation path into the registry 114 | WriteRegStr HKLM SOFTWARE\FlashMulti "InstallDir" "$INSTDIR" 115 | 116 | ; Write a flag indicating the component selections 117 | WriteRegDWORD HKLM SOFTWARE\FlashMulti "InstallDrivers" "0" 118 | 119 | ; Write the uninstall keys for Windows 120 | ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 121 | IntFmt $0 "0x%08X" $0 122 | WriteRegDWORD HKLM "${AddRemoveProgsReg}" "EstimatedSize" "$0" 123 | 124 | WriteRegStr HKLM "${AddRemoveProgsReg}""Publisher" "Ben Lye" 125 | WriteRegStr HKLM "${AddRemoveProgsReg}""DisplayIcon" '"$INSTDIR\flash-multi.exe"' 126 | WriteRegStr HKLM "${AddRemoveProgsReg}""DisplayName" "Flash Multi ${VERSION}" 127 | WriteRegStr HKLM "${AddRemoveProgsReg}""DisplayVersion" "${VERSION}" 128 | WriteRegStr HKLM "${AddRemoveProgsReg}""URLInfoAbout" "https://github.com/benlye/flash-multi/" 129 | WriteRegStr HKLM "${AddRemoveProgsReg}""UninstallString" '"$INSTDIR\uninstall.exe"' 130 | WriteRegDWORD HKLM "${AddRemoveProgsReg}""NoModify" 1 131 | WriteRegDWORD HKLM "${AddRemoveProgsReg}""NoRepair" 1 132 | 133 | ; Create Start Menu shortcuts 134 | !insertmacro MUI_STARTMENU_WRITE_BEGIN Application 135 | CreateDirectory "$SMPROGRAMS\$StartMenuFolder" 136 | CreateShortcut "$SMPROGRAMS\$StartMenuFolder\Flash Multi.lnk" "$INSTDIR\flash-multi.exe" "" "$INSTDIR\flash-multi.exe" 0 137 | CreateShortcut "$SMPROGRAMS\$StartMenuFolder\Run Maple Driver Installer.lnk" "$INSTDIR\drivers\install_drivers.bat" 138 | CreateShortcut "$SMPROGRAMS\$StartMenuFolder\Uninstall Flash Multi.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 139 | !insertmacro MUI_STARTMENU_WRITE_END 140 | SectionEnd 141 | 142 | ; Optional section (can be disabled by the user) 143 | Section "Run the Maple USB driver installer" "install_drivers" 144 | ; Install the drivers - https://github.com/pbatard/libwdi/blob/master/examples/wdi-simple.iss 145 | 146 | SetDetailsPrint textonly ; or both 147 | DetailPrint 'Installing Maple USB driver ...' 148 | SetDetailsPrint none ; or listonly 149 | nsExec::Exec '"$INSTDIR\drivers\wdi-simple.exe" --vid 0x1EAF --pid 0x0003 --type 1 --name "Maple DFU" --dest "$TEMP\maple-dfu" --progressbar=$HWNDPARENT --timeout 120000"' 150 | 151 | SetDetailsPrint textonly ; or both 152 | DetailPrint 'Installing Maple Serial driver ...' 153 | SetDetailsPrint none ; or listonly 154 | nsExec::Exec '"$INSTDIR\drivers\wdi-simple.exe" --vid 0x1EAF --pid 0x0004 --type 3 --name "Maple Serial" --dest "$TEMP\maple-serial" --progressbar=$HWNDPARENT --timeout 120000"' 155 | 156 | ; Remember that drivers were selected 157 | WriteRegDWORD HKLM SOFTWARE\FlashMulti "InstallDrivers" "1" 158 | SectionEnd 159 | 160 | ;-------------------------------- 161 | ; Uninstaller 162 | Section "Uninstall" 163 | ; Get the start menu folder 164 | !insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder 165 | 166 | ; Remove registry keys 167 | DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\FlashMulti" 168 | DeleteRegKey HKLM SOFTWARE\FlashMulti 169 | 170 | ; Remove files 171 | Delete $INSTDIR\*.* 172 | 173 | ; Remove shortcuts, if any 174 | Delete "$SMPROGRAMS\$StartMenuFolder\*.*" 175 | 176 | ; Remove directories used 177 | RMDir "$SMPROGRAMS\$StartMenuFolder" 178 | RMDir /r "$INSTDIR" 179 | SectionEnd 180 | 181 | ; Installer initialization function - checks for previous installation 182 | Function .onInit 183 | ; Select/unselect the components based on previous selections 184 | ReadRegDWORD $0 HKLM "Software\FlashMulti" "InstallDrivers" 185 | ${If} $0 == 0 186 | SectionSetFlags ${install_drivers} 0 187 | ${Else} 188 | SectionSetFlags ${install_drivers} 1 189 | ${EndIf} 190 | 191 | ; Check for an NSIS uninstaller in the registry 192 | ReadRegStr $R0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\FlashMulti" "UninstallString" 193 | ${If} $R0 != "" 194 | StrCpy $0 $R0 195 | ${EndIf} 196 | 197 | ; Check for an InnoSetup uninstaller in the registry 198 | ReadRegStr $R1 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Flash Multi_is1" "UninstallString" 199 | ${If} $R1 != "" 200 | StrCpy $0 $R1 201 | ${EndIf} 202 | 203 | ; If we have an uninstaller, parse the path to find the installation directory 204 | ${If} $0 != "" 205 | ; Strip any double quotes from the uninstaller path 206 | ${StrRep} '$1' '$0' '$\"' '' 207 | 208 | ; Get the parent folder of the uninstaller executable 209 | ${GetParent} $1 $2 210 | 211 | ; If the uninstaller folder is not the same as the default install dir, update the install dir 212 | ${If} $2 != $INSTDIR 213 | StrCpy $INSTDIR $2 214 | ${EndIf} 215 | ${EndIf} 216 | 217 | ; Check if an uninstaller executable exists 218 | IfFileExists "$INSTDIR\unins000.exe" PreviousVersionWarn 219 | IfFileExists "$INSTDIR\uninstall.exe" PreviousVersionWarn 220 | Goto End 221 | 222 | PreviousVersionWarn: 223 | ; An uninstaller exists so ask the user if we should uninstall 224 | MessageBox MB_YESNO|MB_ICONQUESTION "Remove the existing installation of Flash Multi?$\n$\nAnswering $\"No$\" will abort the installation." /SD IDYES IDYES Uninstall 225 | Goto AbortInstall 226 | 227 | Uninstall: 228 | ; Check for InnoSetup uninstaller 229 | IfFileExists "$INSTDIR\unins000.exe" InnoUninstall 230 | ; Check for NSIS uninstaller 231 | IfFileExists "$INSTDIR\uninstall.exe" NsisUninstall 232 | Goto End 233 | 234 | InnoUninstall: 235 | ; Run the InnoSetup uninstaller silently 236 | ExecWait '"$INSTDIR\unins000.exe" /SILENT' 237 | Goto End 238 | 239 | NsisUninstall: 240 | ; Run the NSIS uninstaller silently 241 | ExecWait '"$INSTDIR\uninstall.exe" /S _=$INSTDIR' 242 | Goto End 243 | 244 | AbortInstall: 245 | abort 246 | 247 | End: 248 | FunctionEnd 249 | 250 | ; Uninstaller initialization function - checks for running program 251 | Function un.onInit 252 | ${nsProcess::FindProcess} "flash-multi.exe" $R0 253 | ${If} $R0 == 0 254 | MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "Flash Multi is running. Click OK to close it or Cancel to abort." /SD IDOK IDOK Close 255 | Abort 256 | ${Else} 257 | Goto End 258 | ${EndIf} 259 | 260 | Close: 261 | ${nsProcess::CloseProcess} "flash-multi.exe" $R0 262 | Goto End 263 | 264 | End: 265 | ${nsProcess::Unload} 266 | FunctionEnd -------------------------------------------------------------------------------- /src/flash-multi.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29102.190 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "flash-multi", "flash-multi\flash-multi.csproj", "{72D5A55C-CC93-422C-A12F-CCE99E1C7300}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {72D5A55C-CC93-422C-A12F-CCE99E1C7300}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {72D5A55C-CC93-422C-A12F-CCE99E1C7300}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {72D5A55C-CC93-422C-A12F-CCE99E1C7300}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {72D5A55C-CC93-422C-A12F-CCE99E1C7300}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {AB4E8D22-558E-49BF-9224-52161DC7D6C9} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /src/flash-multi/CenterWinDialog.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // 3 | // Copyright 2020 Ben Lye 4 | // 5 | // This file is part of Flash Multi. 6 | // 7 | // Flash Multi is free software: you can redistribute it and/or modify it under 8 | // the terms of the GNU General Public License as published by the Free Software 9 | // Foundation, either version 3 of the License, or(at your option) any later 10 | // version. 11 | // 12 | // Flash Multi is distributed in the hope that it will be useful, but WITHOUT 13 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License along with 17 | // Flash Multi. If not, see http://www.gnu.org/licenses/. 18 | // 19 | // ------------------------------------------------------------------------------- 20 | 21 | namespace Flash_Multi 22 | { 23 | using System; 24 | using System.Drawing; 25 | using System.Runtime.InteropServices; 26 | using System.Text; 27 | using System.Windows.Forms; 28 | 29 | /// 30 | /// Shows a messagebox centered on the parent window. 31 | /// 32 | internal class CenterWinDialog : IDisposable 33 | { 34 | private int mTries = 0; 35 | private Form mOwner; 36 | 37 | /// 38 | /// Initializes a new instance of the class. 39 | /// 40 | /// The form to center the messagebox over. 41 | public CenterWinDialog(Form owner) 42 | { 43 | this.mOwner = owner; 44 | owner.BeginInvoke(new MethodInvoker(this.FindDialog)); 45 | } 46 | 47 | // P/Invoke declarations 48 | private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp); 49 | 50 | /// 51 | /// Dispose. 52 | /// 53 | public void Dispose() 54 | { 55 | this.mTries = -1; 56 | } 57 | 58 | [DllImport("user32.dll")] 59 | private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp); 60 | 61 | [DllImport("kernel32.dll")] 62 | private static extern int GetCurrentThreadId(); 63 | 64 | [DllImport("user32.dll")] 65 | private static extern int GetClassName(IntPtr hWnd, StringBuilder buffer, int buflen); 66 | 67 | [DllImport("user32.dll")] 68 | private static extern bool GetWindowRect(IntPtr hWnd, out RECT rc); 69 | 70 | [DllImport("user32.dll")] 71 | private static extern bool MoveWindow(IntPtr hWnd, int x, int y, int w, int h, bool repaint); 72 | 73 | private void FindDialog() 74 | { 75 | // Enumerate windows to find the message box 76 | if (this.mTries < 0) 77 | { 78 | return; 79 | } 80 | 81 | EnumThreadWndProc callback = new EnumThreadWndProc(this.CheckWindow); 82 | if (EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero)) 83 | { 84 | if (++this.mTries < 10) 85 | { 86 | this.mOwner.BeginInvoke(new MethodInvoker(this.FindDialog)); 87 | } 88 | } 89 | } 90 | 91 | private bool CheckWindow(IntPtr hWnd, IntPtr lp) 92 | { 93 | // Checks if is a dialog 94 | StringBuilder sb = new StringBuilder(260); 95 | GetClassName(hWnd, sb, sb.Capacity); 96 | if (sb.ToString() != "#32770") 97 | { 98 | return true; 99 | } 100 | 101 | // Got it 102 | Rectangle frmRect = new Rectangle(this.mOwner.Location, this.mOwner.Size); 103 | RECT dlgRect; 104 | GetWindowRect(hWnd, out dlgRect); 105 | MoveWindow( 106 | hWnd, 107 | frmRect.Left + ((frmRect.Width - dlgRect.Right + dlgRect.Left) / 2), 108 | frmRect.Top + ((frmRect.Height - dlgRect.Bottom + dlgRect.Top) / 2), 109 | dlgRect.Right - dlgRect.Left, 110 | dlgRect.Bottom - dlgRect.Top, 111 | true); 112 | return false; 113 | } 114 | 115 | private struct RECT 116 | { 117 | public int Left; public int Top; public int Right; public int Bottom; 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/flash-multi/ComPort.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // 3 | // Copyright 2020 Ben Lye 4 | // 5 | // This file is part of Flash Multi. 6 | // 7 | // Flash Multi is free software: you can redistribute it and/or modify it under 8 | // the terms of the GNU General Public License as published by the Free Software 9 | // Foundation, either version 3 of the License, or(at your option) any later 10 | // version. 11 | // 12 | // Flash Multi is distributed in the hope that it will be useful, but WITHOUT 13 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License along with 17 | // Flash Multi. If not, see http://www.gnu.org/licenses/. 18 | // 19 | // ------------------------------------------------------------------------------- 20 | 21 | namespace Flash_Multi 22 | { 23 | using System; 24 | using System.Collections.Generic; 25 | using System.Diagnostics; 26 | using System.IO.Ports; 27 | using System.Linq; 28 | using System.Management; 29 | using System.Threading; 30 | 31 | /// 32 | /// Class for dealing with COM ports. 33 | /// 34 | internal class ComPort 35 | { 36 | /// 37 | /// Gets the name of the port. 38 | /// 39 | public string Name { get; private set; } 40 | 41 | /// 42 | /// Gets the description of the port. 43 | /// 44 | public string Description { get; private set; } 45 | 46 | /// 47 | /// Gets the displayname of the port (name + description). 48 | /// 49 | public string DisplayName { get; private set; } 50 | 51 | /// 52 | /// Enumerates the available COM ports. 53 | /// 54 | /// Returns an ordered array of COM port names. 55 | public static string[] EnumeratePorts() 56 | { 57 | // Get the list of COM port names 58 | List comPorts = SerialPort.GetPortNames().ToList(); 59 | 60 | // Sort the list of ports 61 | comPorts = comPorts.OrderBy(c => c.Length).ThenBy(c => c).ToList(); 62 | 63 | // Check if we there's a Maple DFU device plugged in and add it to the list 64 | if (MapleDevice.FindMaple().DeviceFound) 65 | { 66 | comPorts.Add("DFU Device"); 67 | } 68 | 69 | // Check if we there's a USBasp device plugged in and add it to the list 70 | if (UsbAspDevice.FindUsbAsp().DeviceFound) 71 | { 72 | comPorts.Add("USBasp"); 73 | } 74 | 75 | // Return an array of COM port names 76 | return comPorts.ToArray(); 77 | } 78 | 79 | /// 80 | /// Enumerates the available COM ports without using WMI. 81 | /// 82 | /// Returns an ordered list of ports . 83 | public static List EnumeratePortList() 84 | { 85 | // Get the start time so we can write how long this takes to the debug window 86 | DateTime start = DateTime.Now; 87 | Debug.WriteLine("Enumerating COM ports"); 88 | 89 | // Create a list to store the COM port names 90 | List comPorts = new List(); 91 | 92 | // Get all the COM port names 93 | string[] comPortNames = SerialPort.GetPortNames().Distinct().ToArray(); 94 | 95 | // Add all the COM ports to the list 96 | foreach (string portName in comPortNames) 97 | { 98 | // We only know the port name, so write that to all three properties 99 | ComPort thisPort = new ComPort 100 | { 101 | Name = portName, 102 | Description = portName, 103 | DisplayName = portName, 104 | }; 105 | comPorts.Add(thisPort); 106 | } 107 | 108 | // Sort the list of ports by name 109 | comPorts = comPorts.OrderBy(c => c.Name.Length).ThenBy(c => c.Name).ToList(); 110 | 111 | // Check if we there's a Maple DFU device plugged in and add it to the list 112 | if (MapleDevice.FindMaple().DfuMode) 113 | { 114 | ComPort dfuPort = new ComPort 115 | { 116 | Name = "DFU Device", 117 | Description = "DFU Device", 118 | DisplayName = "DFU Device", 119 | }; 120 | comPorts.Add(dfuPort); 121 | } 122 | 123 | // Check if we there's a USBasp device plugged in and add it to the list 124 | if (UsbAspDevice.FindUsbAsp().DeviceFound) 125 | { 126 | ComPort usbAsp = new ComPort 127 | { 128 | Name = "USBasp", 129 | Description = "USBasp", 130 | DisplayName = "USBasp", 131 | }; 132 | comPorts.Add(usbAsp); 133 | } 134 | 135 | // Get the time now and write how long that took 136 | DateTime end = DateTime.Now; 137 | Debug.WriteLine($"COM ports enumerated in {end - start}."); 138 | 139 | // Return the list of COM ports 140 | return comPorts; 141 | } 142 | 143 | /// 144 | /// Enumerates the available COM ports using WMI, including the device description. 145 | /// 146 | /// Returns an ordered list of ports . 147 | public static List EnumeratePortList2() 148 | { 149 | List comPorts = new List(); 150 | 151 | // Get all the COM ports using WMI 152 | using (ManagementObjectSearcher searcher = new ManagementObjectSearcher( 153 | "root\\cimv2", 154 | "SELECT * FROM Win32_PnPEntity WHERE ClassGuid=\"{4d36e978-e325-11ce-bfc1-08002be10318}\"")) 155 | { 156 | // Add all available ports to the list 157 | foreach (ManagementObject queryObj in searcher.Get()) 158 | { 159 | string portCaption = queryObj["Caption"].ToString(); 160 | 161 | if (portCaption.Contains("(COM")) 162 | { 163 | // Get the index number where "(COM" starts in the string 164 | int indexOfCom = portCaption.IndexOf("(COM"); 165 | string portName = portCaption.Substring(indexOfCom + 1, portCaption.Length - indexOfCom - 2); 166 | string portDescription = portCaption.Substring(0, indexOfCom - 1); 167 | 168 | ComPort thisPort = new ComPort 169 | { 170 | Name = portName, 171 | Description = portDescription, 172 | DisplayName = $"{portName} ({portDescription})", 173 | }; 174 | 175 | comPorts.Add(thisPort); 176 | } 177 | } 178 | } 179 | 180 | // Sort the list of ports 181 | comPorts = comPorts.OrderBy(c => c.Name.Length).ThenBy(c => c.Name).ToList(); 182 | 183 | // Check if we there's a Maple device in DFU mode plugged in 184 | if (MapleDevice.FindMaple().DfuMode) 185 | { 186 | ComPort dfuPort = new ComPort 187 | { 188 | Name = "DFU Device", 189 | Description = "Maple DFU Device", 190 | DisplayName = "DFU Device", 191 | }; 192 | comPorts.Add(dfuPort); 193 | } 194 | 195 | // Return a list of COM ports 196 | return comPorts; 197 | } 198 | 199 | /// 200 | /// Checks if the COM port can be opened. 201 | /// 202 | /// /// The name of the port to check. 203 | /// 204 | /// Boolean indicating whether the port could be opened. 205 | /// 206 | public static bool CheckPort(string port) 207 | { 208 | // Skip the check and return true if the selected port is 'DFU Device' 209 | if (port == "DFU Device") 210 | { 211 | return true; 212 | } 213 | 214 | bool result = false; 215 | 216 | // Try to open the serial port, catch an exception if we fail 217 | SerialPort serialPort = new SerialPort(port); 218 | try 219 | { 220 | serialPort.Open(); 221 | if (serialPort.IsOpen) 222 | { 223 | result = true; 224 | } 225 | } 226 | catch (Exception ex) 227 | { 228 | Debug.WriteLine(ex.Message); 229 | } 230 | finally 231 | { 232 | Thread.Sleep(50); 233 | serialPort.Close(); 234 | } 235 | 236 | return result; 237 | } 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /src/flash-multi/Dialogs/DfuRecoveryDialog.Designer.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // 3 | // Copyright 2019 Ben Lye 4 | // 5 | // This file is part of Flash Multi. 6 | // 7 | // Flash Multi is free software: you can redistribute it and/or modify it under 8 | // the terms of the GNU General Public License as published by the Free Software 9 | // Foundation, either version 3 of the License, or(at your option) any later 10 | // version. 11 | // 12 | // Flash Multi is distributed in the hope that it will be useful, but WITHOUT 13 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License along with 17 | // Flash Multi. If not, see http://www.gnu.org/licenses/. 18 | // 19 | // ------------------------------------------------------------------------------- 20 | 21 | namespace Flash_Multi 22 | { 23 | partial class DfuRecoveryDialog 24 | { 25 | /// 26 | /// Required designer variable. 27 | /// 28 | private System.ComponentModel.IContainer components = null; 29 | 30 | /// 31 | /// Clean up any resources being used. 32 | /// 33 | /// true if managed resources should be disposed; otherwise, false. 34 | protected override void Dispose(bool disposing) 35 | { 36 | if (disposing && (components != null)) 37 | { 38 | components.Dispose(); 39 | } 40 | base.Dispose(disposing); 41 | } 42 | 43 | #region Windows Form Designer generated code 44 | 45 | /// 46 | /// Required method for Designer support - do not modify 47 | /// the contents of this method with the code editor. 48 | /// 49 | private void InitializeComponent() 50 | { 51 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DfuRecoveryDialog)); 52 | this.dialogText = new System.Windows.Forms.Label(); 53 | this.buttonCancel = new System.Windows.Forms.Button(); 54 | this.warningIcon = new System.Windows.Forms.PictureBox(); 55 | this.panel2 = new System.Windows.Forms.Panel(); 56 | this.timerProgressBar = new System.Windows.Forms.ProgressBar(); 57 | ((System.ComponentModel.ISupportInitialize)(this.warningIcon)).BeginInit(); 58 | this.panel2.SuspendLayout(); 59 | this.SuspendLayout(); 60 | // 61 | // dialogText 62 | // 63 | resources.ApplyResources(this.dialogText, "dialogText"); 64 | this.dialogText.Name = "dialogText"; 65 | // 66 | // buttonCancel 67 | // 68 | resources.ApplyResources(this.buttonCancel, "buttonCancel"); 69 | this.buttonCancel.Name = "buttonCancel"; 70 | this.buttonCancel.TabStop = false; 71 | this.buttonCancel.UseVisualStyleBackColor = true; 72 | this.buttonCancel.Click += new System.EventHandler(this.ButtonCancel_Click); 73 | // 74 | // warningIcon 75 | // 76 | resources.ApplyResources(this.warningIcon, "warningIcon"); 77 | this.warningIcon.Name = "warningIcon"; 78 | this.warningIcon.TabStop = false; 79 | // 80 | // panel2 81 | // 82 | this.panel2.BackColor = System.Drawing.SystemColors.ControlLightLight; 83 | this.panel2.Controls.Add(this.timerProgressBar); 84 | this.panel2.Controls.Add(this.dialogText); 85 | this.panel2.Controls.Add(this.warningIcon); 86 | resources.ApplyResources(this.panel2, "panel2"); 87 | this.panel2.Name = "panel2"; 88 | // 89 | // timerProgressBar 90 | // 91 | resources.ApplyResources(this.timerProgressBar, "timerProgressBar"); 92 | this.timerProgressBar.Maximum = 30; 93 | this.timerProgressBar.Name = "timerProgressBar"; 94 | this.timerProgressBar.Step = 1; 95 | this.timerProgressBar.Value = 30; 96 | // 97 | // DfuRecoveryDialog 98 | // 99 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; 100 | resources.ApplyResources(this, "$this"); 101 | this.ControlBox = false; 102 | this.Controls.Add(this.buttonCancel); 103 | this.Controls.Add(this.panel2); 104 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; 105 | this.MaximizeBox = false; 106 | this.MinimizeBox = false; 107 | this.Name = "DfuRecoveryDialog"; 108 | ((System.ComponentModel.ISupportInitialize)(this.warningIcon)).EndInit(); 109 | this.panel2.ResumeLayout(false); 110 | this.ResumeLayout(false); 111 | 112 | } 113 | 114 | #endregion 115 | 116 | private System.Windows.Forms.Label dialogText; 117 | private System.Windows.Forms.Button buttonCancel; 118 | private System.Windows.Forms.PictureBox warningIcon; 119 | private System.Windows.Forms.Panel panel2; 120 | private System.Windows.Forms.ProgressBar timerProgressBar; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/flash-multi/Dialogs/DfuRecoveryDialog.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // 3 | // Copyright 2020 Ben Lye 4 | // 5 | // This file is part of Flash Multi. 6 | // 7 | // Flash Multi is free software: you can redistribute it and/or modify it under 8 | // the terms of the GNU General Public License as published by the Free Software 9 | // Foundation, either version 3 of the License, or(at your option) any later 10 | // version. 11 | // 12 | // Flash Multi is distributed in the hope that it will be useful, but WITHOUT 13 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License along with 17 | // Flash Multi. If not, see http://www.gnu.org/licenses/. 18 | // 19 | // ------------------------------------------------------------------------------- 20 | 21 | namespace Flash_Multi 22 | { 23 | using System; 24 | using System.Threading.Tasks; 25 | using System.Windows.Forms; 26 | 27 | /// 28 | /// Class for the DFU recovery dialog form. 29 | /// 30 | public partial class DfuRecoveryDialog : Form 31 | { 32 | private Timer progressTimer = new Timer(); 33 | private FlashMulti flashMulti; 34 | 35 | /// 36 | /// Initializes a new instance of the class. 37 | /// 38 | /// An instance of the form. 39 | public DfuRecoveryDialog(FlashMulti flashMulti) 40 | { 41 | this.InitializeComponent(); 42 | this.flashMulti = flashMulti; 43 | this.Load += this.DfuRecoveryDialog_Load; 44 | this.Shown += this.DfuRecoveryDialog_Shown; 45 | } 46 | 47 | /// 48 | /// Prompts the user to unplug / replug the module to get it into recovery mode. 49 | /// 50 | /// Event sender. 51 | /// Event arguments. 52 | private async void DfuRecoveryDialog_Shown(object sender, EventArgs e) 53 | { 54 | // Check if we have a DFU device we need to see unplugged 55 | bool dfuCheck = MapleDevice.FindMaple().DfuMode; 56 | 57 | if (dfuCheck) 58 | { 59 | this.flashMulti.AppendLog("Waiting for DFU device to disappear ..."); 60 | 61 | // Wait 30s for the DFU device to disappear and reappear 62 | await Task.Run(() => { dfuCheck = MapleDevice.WaitForDFU(30000, true); }); 63 | 64 | // Handle user cancelling DFU recovery 65 | if (this.DialogResult == DialogResult.Cancel) 66 | { 67 | return; 68 | } 69 | 70 | if (dfuCheck) 71 | { 72 | // Wait 30s for the DFU device to disappear 73 | await Task.Run(() => { dfuCheck = MapleDevice.WaitForDFU(30000, true); }); 74 | 75 | if (dfuCheck) 76 | { 77 | // The module was unplugged 78 | this.flashMulti.AppendLog(" gone.\r\n"); 79 | } 80 | else 81 | { 82 | // The module wasn't unplugged when the timer expired. 83 | this.flashMulti.AppendLog(" timed out!\r\n"); 84 | using (new CenterWinDialog(this.flashMulti)) 85 | { 86 | MessageBox.Show("DFU device was not unplugged in time.", "Firmware Update", MessageBoxButtons.OK, MessageBoxIcon.Error); 87 | } 88 | 89 | this.DialogResult = DialogResult.Cancel; 90 | this.Close(); 91 | return; 92 | } 93 | } 94 | } 95 | 96 | this.flashMulti.AppendLog("Waiting for DFU device to appear ..."); 97 | 98 | // Wait for the DFU device to appear 99 | await Task.Run(() => { dfuCheck = MapleDevice.WaitForDFU(30000 - (this.timerProgressBar.Value * 1000)); }); 100 | 101 | // Handle user cancelling DFU recovery 102 | if (this.DialogResult == DialogResult.Cancel) 103 | { 104 | return; 105 | } 106 | 107 | if (dfuCheck) 108 | { 109 | // The module was plugged in 110 | this.flashMulti.AppendLog(" got it.\r\n"); 111 | this.DialogResult = DialogResult.OK; 112 | this.Close(); 113 | return; 114 | } 115 | else 116 | { 117 | // The module wasn't plugged in when the timer expired 118 | this.flashMulti.AppendLog(" timed out!\r\n"); 119 | using (new CenterWinDialog(this)) 120 | { 121 | MessageBox.Show("DFU device was not plugged in in time.", "Firmware Update", MessageBoxButtons.OK, MessageBoxIcon.Error); 122 | } 123 | 124 | this.DialogResult = DialogResult.Abort; 125 | this.Close(); 126 | return; 127 | } 128 | } 129 | 130 | /// 131 | /// Handle the Cancel button being clicked. 132 | /// 133 | /// Event sender. 134 | /// Event argument. 135 | private void ButtonCancel_Click(object sender, System.EventArgs e) 136 | { 137 | this.flashMulti.AppendLog(" cancelled.\r\n"); 138 | this.DialogResult = DialogResult.Cancel; 139 | this.Close(); 140 | return; 141 | } 142 | 143 | /// 144 | /// Configure the timer when the form is loaded. 145 | /// 146 | /// Event sender. 147 | /// Event arguments. 148 | private void DfuRecoveryDialog_Load(object sender, EventArgs e) 149 | { 150 | // Configures the timer used to count the progress bar down 151 | this.progressTimer.Enabled = true; 152 | this.progressTimer.Interval = 1000; 153 | 154 | // Configure the progress bar 155 | this.timerProgressBar.Minimum = 0; 156 | this.timerProgressBar.Maximum = 30; 157 | this.timerProgressBar.Value = 0; 158 | this.progressTimer.Tick += new EventHandler(this.ProgressBarTimer_TickUp); 159 | 160 | // Start the timer to count the bar down 161 | this.progressTimer.Start(); 162 | } 163 | 164 | /// 165 | /// Increment the progress bar when the timer ticks. 166 | /// 167 | /// Event sender. 168 | /// Event arguments. 169 | private void ProgressBarTimer_TickUp(object sender, EventArgs e) 170 | { 171 | if (this.timerProgressBar.Value != this.timerProgressBar.Maximum) 172 | { 173 | this.timerProgressBar.Value++; 174 | } 175 | else 176 | { 177 | this.progressTimer.Stop(); 178 | } 179 | } 180 | 181 | /// 182 | /// Increment the progress bar when the timer ticks. 183 | /// 184 | /// Event sender. 185 | /// Event arguments. 186 | private void ProgressBarTimer_TickDown(object sender, EventArgs e) 187 | { 188 | if (this.timerProgressBar.Value != this.timerProgressBar.Minimum) 189 | { 190 | this.timerProgressBar.Value--; 191 | } 192 | else 193 | { 194 | this.progressTimer.Stop(); 195 | } 196 | } 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /src/flash-multi/Dialogs/SerialMonitor.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Flash_Multi 2 | { 3 | partial class SerialMonitor 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SerialMonitor)); 32 | this.serialOutput = new System.Windows.Forms.TextBox(); 33 | this.buttonClose = new System.Windows.Forms.Button(); 34 | this.buttonClear = new System.Windows.Forms.Button(); 35 | this.buttonSave = new System.Windows.Forms.Button(); 36 | this.buttonDisconnect = new System.Windows.Forms.Button(); 37 | this.buttonConnect = new System.Windows.Forms.Button(); 38 | this.checkBoxAutoScroll = new System.Windows.Forms.CheckBox(); 39 | this.SuspendLayout(); 40 | // 41 | // serialOutput 42 | // 43 | this.serialOutput.BackColor = System.Drawing.SystemColors.ControlLightLight; 44 | resources.ApplyResources(this.serialOutput, "serialOutput"); 45 | this.serialOutput.Name = "serialOutput"; 46 | this.serialOutput.ReadOnly = true; 47 | // 48 | // buttonClose 49 | // 50 | resources.ApplyResources(this.buttonClose, "buttonClose"); 51 | this.buttonClose.Name = "buttonClose"; 52 | this.buttonClose.UseVisualStyleBackColor = true; 53 | this.buttonClose.Click += new System.EventHandler(this.ButtonClose_Click); 54 | // 55 | // buttonClear 56 | // 57 | resources.ApplyResources(this.buttonClear, "buttonClear"); 58 | this.buttonClear.Name = "buttonClear"; 59 | this.buttonClear.UseVisualStyleBackColor = true; 60 | this.buttonClear.Click += new System.EventHandler(this.ButtonClear_Click); 61 | // 62 | // buttonSave 63 | // 64 | resources.ApplyResources(this.buttonSave, "buttonSave"); 65 | this.buttonSave.Name = "buttonSave"; 66 | this.buttonSave.UseVisualStyleBackColor = true; 67 | this.buttonSave.Click += new System.EventHandler(this.ButtonSave_Click); 68 | // 69 | // buttonDisconnect 70 | // 71 | resources.ApplyResources(this.buttonDisconnect, "buttonDisconnect"); 72 | this.buttonDisconnect.Name = "buttonDisconnect"; 73 | this.buttonDisconnect.UseVisualStyleBackColor = true; 74 | this.buttonDisconnect.Click += new System.EventHandler(this.ButtonDisconnect_Click); 75 | // 76 | // buttonConnect 77 | // 78 | resources.ApplyResources(this.buttonConnect, "buttonConnect"); 79 | this.buttonConnect.Name = "buttonConnect"; 80 | this.buttonConnect.UseVisualStyleBackColor = true; 81 | this.buttonConnect.Click += new System.EventHandler(this.ButtonConnect_Click); 82 | // 83 | // checkBoxAutoScroll 84 | // 85 | resources.ApplyResources(this.checkBoxAutoScroll, "checkBoxAutoScroll"); 86 | this.checkBoxAutoScroll.Checked = true; 87 | this.checkBoxAutoScroll.CheckState = System.Windows.Forms.CheckState.Checked; 88 | this.checkBoxAutoScroll.Name = "checkBoxAutoScroll"; 89 | this.checkBoxAutoScroll.UseVisualStyleBackColor = true; 90 | // 91 | // SerialMonitor 92 | // 93 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; 94 | resources.ApplyResources(this, "$this"); 95 | this.Controls.Add(this.checkBoxAutoScroll); 96 | this.Controls.Add(this.buttonConnect); 97 | this.Controls.Add(this.buttonDisconnect); 98 | this.Controls.Add(this.buttonSave); 99 | this.Controls.Add(this.buttonClear); 100 | this.Controls.Add(this.buttonClose); 101 | this.Controls.Add(this.serialOutput); 102 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow; 103 | this.MaximizeBox = false; 104 | this.MinimizeBox = false; 105 | this.Name = "SerialMonitor"; 106 | this.ResumeLayout(false); 107 | this.PerformLayout(); 108 | 109 | } 110 | 111 | #endregion 112 | 113 | private System.Windows.Forms.TextBox serialOutput; 114 | private System.Windows.Forms.Button buttonClose; 115 | private System.Windows.Forms.Button buttonClear; 116 | private System.Windows.Forms.Button buttonSave; 117 | private System.Windows.Forms.Button buttonDisconnect; 118 | private System.Windows.Forms.Button buttonConnect; 119 | private System.Windows.Forms.CheckBox checkBoxAutoScroll; 120 | } 121 | } -------------------------------------------------------------------------------- /src/flash-multi/Dialogs/UsbSupportErrorDialog.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Flash_Multi 2 | { 3 | partial class UsbSupportErrorDialog 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(UsbSupportErrorDialog)); 32 | this.panel2 = new System.Windows.Forms.Panel(); 33 | this.moreInfoLinkLabel = new System.Windows.Forms.LinkLabel(); 34 | this.dialogText = new System.Windows.Forms.Label(); 35 | this.errorIcon = new System.Windows.Forms.PictureBox(); 36 | this.buttonOK = new System.Windows.Forms.Button(); 37 | this.panel2.SuspendLayout(); 38 | ((System.ComponentModel.ISupportInitialize)(this.errorIcon)).BeginInit(); 39 | this.SuspendLayout(); 40 | // 41 | // panel2 42 | // 43 | this.panel2.BackColor = System.Drawing.SystemColors.ControlLightLight; 44 | this.panel2.Controls.Add(this.moreInfoLinkLabel); 45 | this.panel2.Controls.Add(this.dialogText); 46 | this.panel2.Controls.Add(this.errorIcon); 47 | this.panel2.Location = new System.Drawing.Point(0, 0); 48 | this.panel2.Name = "panel2"; 49 | this.panel2.Size = new System.Drawing.Size(405, 147); 50 | this.panel2.TabIndex = 6; 51 | // 52 | // moreInfoLinkLabel 53 | // 54 | this.moreInfoLinkLabel.AutoSize = true; 55 | this.moreInfoLinkLabel.LinkArea = new System.Windows.Forms.LinkArea(6, 4); 56 | this.moreInfoLinkLabel.Location = new System.Drawing.Point(57, 114); 57 | this.moreInfoLinkLabel.Name = "moreInfoLinkLabel"; 58 | this.moreInfoLinkLabel.Size = new System.Drawing.Size(178, 21); 59 | this.moreInfoLinkLabel.TabIndex = 3; 60 | this.moreInfoLinkLabel.TabStop = true; 61 | this.moreInfoLinkLabel.Text = "Click here for more information."; 62 | this.moreInfoLinkLabel.UseCompatibleTextRendering = true; 63 | this.moreInfoLinkLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.MoreInfoLinkLabel_LinkClicked); 64 | // 65 | // dialogText 66 | // 67 | this.dialogText.ImeMode = System.Windows.Forms.ImeMode.NoControl; 68 | this.dialogText.Location = new System.Drawing.Point(54, 13); 69 | this.dialogText.Name = "dialogText"; 70 | this.dialogText.Size = new System.Drawing.Size(306, 101); 71 | this.dialogText.TabIndex = 0; 72 | this.dialogText.Text = resources.GetString("dialogText.Text"); 73 | // 74 | // errorIcon 75 | // 76 | this.errorIcon.ImeMode = System.Windows.Forms.ImeMode.NoControl; 77 | this.errorIcon.Location = new System.Drawing.Point(13, 13); 78 | this.errorIcon.Name = "errorIcon"; 79 | this.errorIcon.Size = new System.Drawing.Size(34, 34); 80 | this.errorIcon.TabIndex = 2; 81 | this.errorIcon.TabStop = false; 82 | // 83 | // buttonOK 84 | // 85 | this.buttonOK.ImeMode = System.Windows.Forms.ImeMode.NoControl; 86 | this.buttonOK.Location = new System.Drawing.Point(325, 153); 87 | this.buttonOK.Name = "buttonOK"; 88 | this.buttonOK.Size = new System.Drawing.Size(67, 24); 89 | this.buttonOK.TabIndex = 7; 90 | this.buttonOK.TabStop = false; 91 | this.buttonOK.Text = "OK"; 92 | this.buttonOK.UseVisualStyleBackColor = true; 93 | this.buttonOK.Click += new System.EventHandler(this.ButtonOK_Click); 94 | // 95 | // UsbSupportErrorDialog 96 | // 97 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; 98 | this.ClientSize = new System.Drawing.Size(404, 187); 99 | this.ControlBox = false; 100 | this.Controls.Add(this.buttonOK); 101 | this.Controls.Add(this.panel2); 102 | this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 103 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; 104 | this.MaximizeBox = false; 105 | this.MinimizeBox = false; 106 | this.Name = "UsbSupportErrorDialog"; 107 | this.ShowInTaskbar = false; 108 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 109 | this.Text = "USB Support Error"; 110 | this.panel2.ResumeLayout(false); 111 | this.panel2.PerformLayout(); 112 | ((System.ComponentModel.ISupportInitialize)(this.errorIcon)).EndInit(); 113 | this.ResumeLayout(false); 114 | 115 | } 116 | 117 | #endregion 118 | private System.Windows.Forms.Panel panel2; 119 | private System.Windows.Forms.Label dialogText; 120 | private System.Windows.Forms.PictureBox errorIcon; 121 | private System.Windows.Forms.Button buttonOK; 122 | private System.Windows.Forms.LinkLabel moreInfoLinkLabel; 123 | } 124 | } -------------------------------------------------------------------------------- /src/flash-multi/Dialogs/UsbSupportErrorDialog.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // 3 | // Copyright 2020 Ben Lye 4 | // 5 | // This file is part of Flash Multi. 6 | // 7 | // Flash Multi is free software: you can redistribute it and/or modify it under 8 | // the terms of the GNU General Public License as published by the Free Software 9 | // Foundation, either version 3 of the License, or(at your option) any later 10 | // version. 11 | // 12 | // Flash Multi is distributed in the hope that it will be useful, but WITHOUT 13 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License along with 17 | // Flash Multi. If not, see http://www.gnu.org/licenses/. 18 | // 19 | // ------------------------------------------------------------------------------- 20 | 21 | namespace Flash_Multi 22 | { 23 | using System; 24 | using System.Diagnostics; 25 | using System.Windows.Forms; 26 | 27 | /// 28 | /// Class for the USB Support warning dialog. 29 | /// 30 | public partial class UsbSupportErrorDialog : Form 31 | { 32 | /// 33 | /// Initializes a new instance of the class. 34 | /// 35 | public UsbSupportErrorDialog() 36 | { 37 | this.InitializeComponent(); 38 | } 39 | 40 | /// 41 | /// Set the icon when the dialog is loaded. 42 | /// 43 | protected override void OnShown(EventArgs e) 44 | { 45 | this.errorIcon.Image = System.Drawing.SystemIcons.Error.ToBitmap(); 46 | base.OnShown(e); 47 | } 48 | 49 | /// 50 | /// Handles the Cancel button being clicked. 51 | /// 52 | private void ButtonCancel_Click(object sender, EventArgs e) 53 | { 54 | // Return Cancel 55 | this.DialogResult = DialogResult.Cancel; 56 | this.Close(); 57 | return; 58 | } 59 | 60 | /// 61 | /// Handles the OK button being clicked. 62 | /// 63 | private void ButtonOK_Click(object sender, EventArgs e) 64 | { 65 | // Return OK 66 | this.DialogResult = DialogResult.OK; 67 | this.Close(); 68 | return; 69 | } 70 | 71 | /// 72 | /// Opens a URL in the default browser. 73 | /// 74 | /// The URL to open. 75 | private void OpenLink(string url) 76 | { 77 | try 78 | { 79 | System.Diagnostics.Process.Start(url); 80 | } 81 | catch (Exception ex) 82 | { 83 | Debug.WriteLine(ex.Message); 84 | } 85 | } 86 | 87 | private void MoreInfoLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 88 | { 89 | this.OpenLink("https://github.com/benlye/flash-multi/blob/master/doc/New_Bootloader.md"); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/flash-multi/Dialogs/UsbSupportErrorDialog.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | The selected firmware file was compiled without USB serial support and the 'USB Port Mode' setting is set to 'COM Port (Legacy)'. 122 | 123 | The MULTI-Module bootloader must be updated and the 'USB Port Mode' setting set to 'Sticky DFU Mode (New)' in order to write this firmware. 124 | 125 | -------------------------------------------------------------------------------- /src/flash-multi/Dialogs/UsbSupportWarningDialog.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Flash_Multi 2 | { 3 | partial class UsbSupportWarningDialog 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(UsbSupportWarningDialog)); 32 | this.buttonCancel = new System.Windows.Forms.Button(); 33 | this.panel2 = new System.Windows.Forms.Panel(); 34 | this.dialogText = new System.Windows.Forms.Label(); 35 | this.warningIcon = new System.Windows.Forms.PictureBox(); 36 | this.buttonOK = new System.Windows.Forms.Button(); 37 | this.disableUsbWarning = new System.Windows.Forms.CheckBox(); 38 | this.panel2.SuspendLayout(); 39 | ((System.ComponentModel.ISupportInitialize)(this.warningIcon)).BeginInit(); 40 | this.SuspendLayout(); 41 | // 42 | // buttonCancel 43 | // 44 | this.buttonCancel.ImeMode = System.Windows.Forms.ImeMode.NoControl; 45 | this.buttonCancel.Location = new System.Drawing.Point(322, 121); 46 | this.buttonCancel.Name = "buttonCancel"; 47 | this.buttonCancel.Size = new System.Drawing.Size(67, 24); 48 | this.buttonCancel.TabIndex = 6; 49 | this.buttonCancel.Text = "Cancel"; 50 | this.buttonCancel.UseVisualStyleBackColor = true; 51 | this.buttonCancel.Click += new System.EventHandler(this.ButtonCancel_Click); 52 | // 53 | // panel2 54 | // 55 | this.panel2.BackColor = System.Drawing.SystemColors.ControlLightLight; 56 | this.panel2.Controls.Add(this.dialogText); 57 | this.panel2.Controls.Add(this.warningIcon); 58 | this.panel2.Location = new System.Drawing.Point(0, 0); 59 | this.panel2.Name = "panel2"; 60 | this.panel2.Size = new System.Drawing.Size(405, 113); 61 | this.panel2.TabIndex = 6; 62 | // 63 | // dialogText 64 | // 65 | this.dialogText.ImeMode = System.Windows.Forms.ImeMode.NoControl; 66 | this.dialogText.Location = new System.Drawing.Point(54, 13); 67 | this.dialogText.Name = "dialogText"; 68 | this.dialogText.Size = new System.Drawing.Size(306, 96); 69 | this.dialogText.TabIndex = 0; 70 | this.dialogText.Text = "The selected firmware file was compiled without USB serial support. The MULTI-Mod" + 71 | "ule bootloader should be updated before writing this firmware.\r\n\r\nClick OK to wr" + 72 | "ite the firmware."; 73 | // 74 | // warningIcon 75 | // 76 | this.warningIcon.Image = ((System.Drawing.Image)(resources.GetObject("warningIcon.Image"))); 77 | this.warningIcon.ImeMode = System.Windows.Forms.ImeMode.NoControl; 78 | this.warningIcon.Location = new System.Drawing.Point(13, 13); 79 | this.warningIcon.Name = "warningIcon"; 80 | this.warningIcon.Size = new System.Drawing.Size(34, 34); 81 | this.warningIcon.TabIndex = 2; 82 | this.warningIcon.TabStop = false; 83 | // 84 | // buttonOK 85 | // 86 | this.buttonOK.ImeMode = System.Windows.Forms.ImeMode.NoControl; 87 | this.buttonOK.Location = new System.Drawing.Point(249, 121); 88 | this.buttonOK.Name = "buttonOK"; 89 | this.buttonOK.Size = new System.Drawing.Size(67, 24); 90 | this.buttonOK.TabIndex = 5; 91 | this.buttonOK.Text = "OK"; 92 | this.buttonOK.UseVisualStyleBackColor = true; 93 | this.buttonOK.Click += new System.EventHandler(this.ButtonOK_Click); 94 | // 95 | // disableUsbWarning 96 | // 97 | this.disableUsbWarning.AutoSize = true; 98 | this.disableUsbWarning.Location = new System.Drawing.Point(13, 121); 99 | this.disableUsbWarning.Name = "disableUsbWarning"; 100 | this.disableUsbWarning.Size = new System.Drawing.Size(196, 19); 101 | this.disableUsbWarning.TabIndex = 4; 102 | this.disableUsbWarning.Text = "Do not show this message again"; 103 | this.disableUsbWarning.UseVisualStyleBackColor = true; 104 | // 105 | // UsbSupportWarningDialog 106 | // 107 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; 108 | this.ClientSize = new System.Drawing.Size(404, 152); 109 | this.ControlBox = false; 110 | this.Controls.Add(this.disableUsbWarning); 111 | this.Controls.Add(this.buttonOK); 112 | this.Controls.Add(this.buttonCancel); 113 | this.Controls.Add(this.panel2); 114 | this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 115 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; 116 | this.MaximizeBox = false; 117 | this.MinimizeBox = false; 118 | this.Name = "UsbSupportWarningDialog"; 119 | this.ShowInTaskbar = false; 120 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 121 | this.Text = "USB Support Warning"; 122 | this.panel2.ResumeLayout(false); 123 | ((System.ComponentModel.ISupportInitialize)(this.warningIcon)).EndInit(); 124 | this.ResumeLayout(false); 125 | this.PerformLayout(); 126 | 127 | } 128 | 129 | #endregion 130 | 131 | private System.Windows.Forms.Button buttonCancel; 132 | private System.Windows.Forms.Panel panel2; 133 | private System.Windows.Forms.Label dialogText; 134 | private System.Windows.Forms.PictureBox warningIcon; 135 | private System.Windows.Forms.Button buttonOK; 136 | private System.Windows.Forms.CheckBox disableUsbWarning; 137 | } 138 | } -------------------------------------------------------------------------------- /src/flash-multi/Dialogs/UsbSupportWarningDialog.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // 3 | // Copyright 2020 Ben Lye 4 | // 5 | // This file is part of Flash Multi. 6 | // 7 | // Flash Multi is free software: you can redistribute it and/or modify it under 8 | // the terms of the GNU General Public License as published by the Free Software 9 | // Foundation, either version 3 of the License, or(at your option) any later 10 | // version. 11 | // 12 | // Flash Multi is distributed in the hope that it will be useful, but WITHOUT 13 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License along with 17 | // Flash Multi. If not, see http://www.gnu.org/licenses/. 18 | // 19 | // ------------------------------------------------------------------------------- 20 | 21 | namespace Flash_Multi 22 | { 23 | using System; 24 | using System.Diagnostics; 25 | using System.Windows.Forms; 26 | 27 | /// 28 | /// Class for the USB Support warning dialog. 29 | /// 30 | public partial class UsbSupportWarningDialog : Form 31 | { 32 | /// 33 | /// Initializes a new instance of the class. 34 | /// 35 | public UsbSupportWarningDialog() 36 | { 37 | this.InitializeComponent(); 38 | } 39 | 40 | /// 41 | /// Set the icon when the dialog is loaded. 42 | /// 43 | protected override void OnShown(EventArgs e) 44 | { 45 | this.warningIcon.Image = System.Drawing.SystemIcons.Warning.ToBitmap(); 46 | base.OnShown(e); 47 | } 48 | 49 | /// 50 | /// Handles the Cancel button being clicked. 51 | /// 52 | private void ButtonCancel_Click(object sender, EventArgs e) 53 | { 54 | // Return Cancel 55 | this.DialogResult = DialogResult.Cancel; 56 | this.Close(); 57 | return; 58 | } 59 | 60 | /// 61 | /// Handles the OK button being clicked. 62 | /// 63 | private void ButtonOK_Click(object sender, EventArgs e) 64 | { 65 | // Disable the warning if the box was checked 66 | if (this.disableUsbWarning.Checked == true) 67 | { 68 | Properties.Settings.Default.WarnIfNoUSB = false; 69 | } 70 | 71 | // Return OK 72 | this.DialogResult = DialogResult.OK; 73 | this.Close(); 74 | return; 75 | } 76 | 77 | /// 78 | /// Opens a URL in the default browser. 79 | /// 80 | /// The URL to open. 81 | private void OpenLink(string url) 82 | { 83 | try 84 | { 85 | System.Diagnostics.Process.Start(url); 86 | } 87 | catch (Exception ex) 88 | { 89 | Debug.WriteLine(ex.Message); 90 | } 91 | } 92 | 93 | private void MoreInfoLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 94 | { 95 | this.OpenLink("https://github.com/benlye/flash-multi/blob/master/doc/New_Bootloader.md"); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/flash-multi/Dialogs/UsbSupportWarningDialog.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | 123 | iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO 124 | wwAADsMBx2+oZAAABt1JREFUWEftVntMW9cdvkBtEiqWpVvSZGwJA5SGPqZVTVuSjqxLQqXSpdmUpZ2S 125 | JZXa0EjTUrVaknV/bOv+mbqQFwb72hjbsXkFDMYmBhtsZuJXsA0mvAkpyrJAIDYYO5hg1rTffte+Wztt 126 | Uro2qTZpn/TpXN9zzu/7ve45Zv6P/0nIlQpBk8HwXmND47tyueK7/OsvDyqVcpvB0DJnaXeAHCiWSNhk 127 | fur+g2Ul36yuqbtms5lgtzfAYDAtyWTlP+On7z8UCvnxRp0N5ubDuGheB4vFDLVG202ZeIhfcv8glbLP 128 | aLXNUZ2uAcPulZi4IoS1YSdazD5QFn7PL7s/YFk2pbKySmc02tFavxsAE2df51fQYT4LbYP5xqlTJx/j 129 | l997UPQ/bW7uuNPaWoPx7tR/OICPGFhqtsLhHKYsKAjKJH7LvYNEIl5ZU1M35nAMUsoLE8KLPMmBfuuD 130 | 8DoqYDK7YzKpbDu/7d5BJpMda2u7iAs2Flc8qZCKn8KRd3bg6JFt+N1vCvCBPx3Ohifh7hpATW19e3m5 131 | PJXf+sUhFos36vUtgR6/H+7WfPw1yuDw4SIUFf0WB4vexYEDR+A0rceENx2u1l/D1TX0cUmJ6HV++xcD 132 | NV6yWq0uHxr+Cy46T+DPA0Iszafg2NF9OHToHXLi59h/4HW4TZlAaBk6Kx/D1I1pNOlNwywrzeDNfH6I 133 | xaXft1hdt7s8LozYv0X1TsKdqIDS/2Ps3fcmXnl1H3a+vAseE80FVuGGOw127UFMBxZAZXifN/P5QKlP 134 | ra6u9U7fvAWH6U3MTwiBhYcQm0nD228VoPClV1Dwwkt4/vkfwGNcA1z/GpZGlsGhycBY/5/Q6fDepAx+ 135 | hzf3n4OO3CK7w3/H4zFg3P0wEF5BXItYMA2/OLQFz+btIH4PW/O3wGdcBYynY3HgQUy0pcBW9SJmQ7eh 136 | Vldp6J5I4U1+dlDqMxp1zdemb87B1rSLhNMpxd8AZjIQm05H0YEnkPtoHjY9/RxeKMhHv2klcFmIhW4B 137 | Fn0M/JVCdLWegMc3EhWJRC/yZj87FAqVZnBoAhcdClx1fh0IrsFHExnAxBosjKzE7sJVWLZ8Ndatz0H+ 138 | c0+it1GAD0k47CBeILYxaC3Jpl4Ioa6+yUHH9Are9N1BtX/c0GyeGR0dgaNxOzApRGwsDdGBZEoxgzkP 139 | g4LNDGgphKkrsCUvFz01SViwMZg1E43kANHPCqkhfwXfpXFIWekbCet3ATWNQKXSWEcvT6JdW4QZTzKi 140 | PWTQyyDkZjDfxeAWjTvzEw48vDYLu3flY6AuCdF2Em8mGhjM6GnUMTAXr4bPZYFO3zJKpbj7Z0mNt8vY 141 | YrtjNjegT5eO2yTORTxHoiEnibsY3Kbf+ws5Bx5AZs7T2LtnBwbPkQNc9CQ808Qg2EAj8bIsBS2Sl+H2 142 | jYHOhT/yMv8eEonkq1XV50acrj60Vf8IgQvJmKOIQyTKiYfsRK6+nXQDqhmcf58uoRIGXjmDSW0i8iBF 143 | HSDhQB2D6Vp6d46BvViINu1JnDd1hqVS6SZe7l9RLq842Wb1oUV/BkM6IcKcODXV34VnO4gWygKxR8ng 144 | zNsM3isSovU4gyjVPEhOcMIBEp2qIVYRKxl8IE2B4cQzsLsGoFKp63m5fwZFn1l7TjdpMplhqd6OoC05 145 | ETUJh6i5Qpw41XiOGKXnY3u5EgiwOuMpHNybhysaWsNFTuJc5HFxnkFyxkVZMCiPoqXduURNvpOX/QRK 146 | pUpnNDlxnrp2VC+kZhMg7KIsOGjkStGZhLA1Ib5AJdizjXMgDZs278Br+19FXwXtOc+V4AGqvwABrTDO 147 | oFZAvSDENU0KlSwbVosNZzW1zjOnz3zyWVLj5dVr9fOGprNwaAvw8eVsxAZyEbu0ETH/I4j1bMBidw5i 148 | PnrvzQL8mfBo1uGH23Ow5yeFUPxhK2bM38aifSPmO3Jxq+NRzNs45sYZJS7ZH0Gfai30soNoNtoglrBv 149 | 8fIMo9FUWkzmTvqb9Ut0V2XCV7kBPjVRRVTmfIrZ8Cqz4vQTndIsWE6vh0tKDsmz0SXfgK5ynvTs+RS9 150 | xG7aY5U8i3ajHrV1umunTp3OSjhQWdXn8Xajv9eDgV4v0YfB3h4M9fkx3N+L8bFhXL86jsDUDYSCAczN 151 | cgwizDEUjD9znA1MYWryOqYmruPq2ChGB/vi+zk7nL0Bf8LuJX8vrNbOD/PyNhfEHSg+XlwmlcpmRaKy 152 | iEgkSbBUEiktYyNlEjYiYWURlq2IsNKKiLRCEamoUCaoUEXoyI6P9DvMkebDtC7MsvKwhJWGy8RsmOyE 153 | yV64RCQOi4ilpZyOqGf58rTMuAM8uGvzy+Z/Axjmb16JL+4sqeK+AAAAAElFTkSuQmCC 154 | 155 | 156 | -------------------------------------------------------------------------------- /src/flash-multi/Eeprom/AtmegaEepromUtils.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // 3 | // Copyright 2020 Ben Lye 4 | // 5 | // This file is part of Flash Multi. 6 | // 7 | // Flash Multi is free software: you can redistribute it and/or modify it under 8 | // the terms of the GNU General Public License as published by the Free Software 9 | // Foundation, either version 3 of the License, or(at your option) any later 10 | // version. 11 | // 12 | // Flash Multi is distributed in the hope that it will be useful, but WITHOUT 13 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License along with 17 | // Flash Multi. If not, see http://www.gnu.org/licenses/. 18 | // 19 | // ------------------------------------------------------------------------------- 20 | 21 | namespace Flash_Multi 22 | { 23 | using System; 24 | using System.Diagnostics; 25 | using System.IO; 26 | 27 | /// 28 | /// Functions for working with the EEPROM of an Atmega328p-based MULTI-Module. 29 | /// 30 | internal class AtmegaEepromUtils 31 | { 32 | /// 33 | /// EEPROM page size; 1024 bytes on the STM32F103. 34 | /// 35 | private const int EepromSize = 0x400; 36 | 37 | /// 38 | /// Extract the EEPROM data from an EEPROM backup file. 39 | /// 40 | /// The name of the backup file to parse. 41 | /// The EEPROM data. 42 | internal static byte[] GetEepromDataFromBackup(string filename) 43 | { 44 | byte[] eepromData; 45 | 46 | // Get the file size 47 | long length = new System.IO.FileInfo(filename).Length; 48 | 49 | // File is not the right size to contain EEPROM data 50 | if (length != 1024) 51 | { 52 | return null; 53 | } 54 | 55 | // Read the binary file 56 | using (BinaryReader b = new BinaryReader(File.Open(filename, FileMode.Open, FileAccess.Read))) 57 | { 58 | eepromData = b.ReadBytes(EepromSize); 59 | } 60 | 61 | return eepromData; 62 | } 63 | 64 | /// 65 | /// Read a single address from the EEPROM data and retun the value. 66 | /// 67 | /// The virtual address to read. 68 | /// A byte array containing the EEPROM data. 69 | /// The variable value or -1 if the address was not found. 70 | internal static int ReadEepromVariable(int address, byte[] eepromData) 71 | { 72 | if (address >= 0 && address < EepromSize) 73 | { 74 | return eepromData[address]; 75 | } 76 | else 77 | { 78 | return -1; 79 | } 80 | } 81 | 82 | /// 83 | /// Retrieves the Global ID from the EEPROM data. 84 | /// 85 | /// A byte array containing the EEPROM data. 86 | /// The Global ID. 87 | internal static uint ReadGlobalId(byte[] eepromData) 88 | { 89 | uint id = 0; 90 | 91 | // Read the four EEPROM variables containing the Global ID 92 | for (int i = 3; i >= 0; i--) 93 | { 94 | // Get the variable data 95 | int var = ReadEepromVariable(10 + i, eepromData); 96 | if (var < 0) 97 | { 98 | return 0; 99 | } 100 | 101 | // Shift the ID left 8 bits for the next value 102 | id <<= 8; 103 | 104 | // OR the variables together 105 | id |= (uint)var; 106 | } 107 | 108 | return id; 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/flash-multi/Eeprom/Stm32EepromUtils.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // 3 | // Copyright 2020 Ben Lye 4 | // 5 | // This file is part of Flash Multi. 6 | // 7 | // Flash Multi is free software: you can redistribute it and/or modify it under 8 | // the terms of the GNU General Public License as published by the Free Software 9 | // Foundation, either version 3 of the License, or(at your option) any later 10 | // version. 11 | // 12 | // Flash Multi is distributed in the hope that it will be useful, but WITHOUT 13 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License along with 17 | // Flash Multi. If not, see http://www.gnu.org/licenses/. 18 | // 19 | // ------------------------------------------------------------------------------- 20 | 21 | namespace Flash_Multi 22 | { 23 | using System; 24 | using System.Diagnostics; 25 | using System.IO; 26 | using System.Linq; 27 | 28 | /// 29 | /// Functions for working with the emulated EEPROM of the STM32F103. 30 | /// 31 | internal class Stm32EepromUtils 32 | { 33 | /// 34 | /// EEPROM page size; 1024 bytes on the STM32F103. 35 | /// 36 | private const int PageSize = 0x400; 37 | 38 | /// 39 | /// Base address of EEPROM page 0. 40 | /// 41 | private const int PageBase0 = 0; 42 | 43 | /// 44 | /// Base address of EEPROM page 1. 45 | /// 46 | private const int PageBase1 = 0x400; 47 | 48 | /// 49 | /// Page header of an erased EEPROM page. 50 | /// 51 | private const int EepromPageErased = 0xFFFF; 52 | 53 | /// 54 | /// Page header of a valid EEPROM page. 55 | /// 56 | private const int EepromPageValid = 0x0000; 57 | 58 | /// 59 | /// Extract the EEPROM data from a backup file. 60 | /// The EEPROM data is the last 2048 bytes of the file. 61 | /// 62 | /// The name of the backup file to parse. 63 | /// The EEPROM data. 64 | internal static byte[] GetEepromDataFromBackup(string filename) 65 | { 66 | byte[] eepromData; 67 | 68 | // Get the file size 69 | long length = new System.IO.FileInfo(filename).Length; 70 | 71 | // File is too small to contain EEPROM data 72 | if (length < 2048) 73 | { 74 | return null; 75 | } 76 | 77 | // Read the last 2048 bytes of the binary file 78 | using (BinaryReader b = new BinaryReader(File.Open(filename, FileMode.Open, FileAccess.Read))) 79 | { 80 | long offset = new System.IO.FileInfo(filename).Length - 2048; 81 | 82 | // Seek to our required position. 83 | b.BaseStream.Seek(offset, SeekOrigin.Begin); 84 | 85 | // Read the next 2048 bytes. 86 | eepromData = b.ReadBytes(2048); 87 | } 88 | 89 | return eepromData; 90 | } 91 | 92 | /// 93 | /// Find the valid page in the EEPROM data. 94 | /// 95 | /// A byte array containing the EEPROM data. 96 | /// The start address of the valid page. 97 | internal static int FindValidPage(byte[] eepromData) 98 | { 99 | if (eepromData != null) 100 | { 101 | // Get the status page bytes 102 | byte[] status0Bytes = { eepromData[PageBase0 + 1], eepromData[PageBase0] }; 103 | byte[] status1Bytes = { eepromData[PageBase1 + 1], eepromData[PageBase1] }; 104 | 105 | // Convert the bytes to integers 106 | int status0 = System.Convert.ToInt32(BitConverter.ToString(status0Bytes).Replace("-", string.Empty), 16); 107 | int status1 = System.Convert.ToInt32(BitConverter.ToString(status1Bytes).Replace("-", string.Empty), 16); 108 | 109 | // Compare the page status values to determine the valid page 110 | if (status0 == EepromPageValid && status1 == EepromPageErased) 111 | { 112 | return PageBase0; 113 | } 114 | 115 | if (status0 == EepromPageErased && status1 == EepromPageValid) 116 | { 117 | return PageBase1; 118 | } 119 | } 120 | 121 | Debug.WriteLine($"No valid EEPROM page found!"); 122 | return -1; 123 | } 124 | 125 | /// 126 | /// Read a single address from the EEPROM data and retun the value. 127 | /// 128 | /// The virtual address to read. 129 | /// A byte array containing the EEPROM data. 130 | /// The variable value or -1 if the address was not found. 131 | internal static int ReadEepromVariable(int address, byte[] eepromData) 132 | { 133 | int pageBase = FindValidPage(eepromData); 134 | 135 | if (pageBase < 0) 136 | { 137 | return -1; 138 | } 139 | 140 | int pageEnd = pageBase + PageSize - 2; 141 | 142 | for (pageBase += 6; pageEnd >= pageBase; pageEnd -= 4) 143 | { 144 | byte[] addressBytes = { eepromData[pageEnd + 1], eepromData[pageEnd] }; 145 | int addressValue = System.Convert.ToInt32(BitConverter.ToString(addressBytes).Replace("-", string.Empty), 16); 146 | 147 | if (addressValue == address) 148 | { 149 | byte[] dataBytes = { eepromData[pageEnd - 1], eepromData[pageEnd - 2] }; 150 | int dataValue = System.Convert.ToInt32(BitConverter.ToString(dataBytes).Replace("-", string.Empty), 16); 151 | return dataValue; 152 | } 153 | } 154 | 155 | return -1; 156 | } 157 | 158 | /// 159 | /// Retrieves the Global ID from the EEPROM data. 160 | /// 161 | /// A byte array containing the EEPROM data. 162 | /// The Global ID. 163 | internal static uint ReadGlobalId(byte[] eepromData) 164 | { 165 | uint id = 0; 166 | 167 | // Read the four EEPROM variables containing the Global ID 168 | for (int i = 3; i >= 0; i--) 169 | { 170 | // Get the variable data 171 | int var = ReadEepromVariable(10 + i, eepromData); 172 | if (var < 0) 173 | { 174 | return 0; 175 | } 176 | 177 | // Shift the ID left 8 bits for the next value 178 | id <<= 8; 179 | 180 | // OR the variables together 181 | id |= (uint)var; 182 | } 183 | 184 | return id; 185 | } 186 | 187 | /// 188 | /// Check if the firmware section of the flash memory is empty (contains all 0xFF). 189 | /// 190 | /// The name of the firmware backup file to evaluate. 191 | /// A boolean indicating whether or not the firmware data is empty. 192 | internal static bool FirmwareIsEmpty(string filename) 193 | { 194 | long filesize = new System.IO.FileInfo(filename).Length; 195 | using (BinaryReader b = new BinaryReader(File.Open(filename, FileMode.Open, FileAccess.Read))) 196 | { 197 | // Read the file, excluding the EEPROM data 198 | b.BaseStream.Seek(0, SeekOrigin.Begin); 199 | byte[] data = b.ReadBytes((int)filesize - 2048); 200 | 201 | return data.Distinct().Count() == 1 && data.Distinct().FirstOrDefault() == 255; 202 | } 203 | } 204 | 205 | /// 206 | /// Check if the EEPROM section of the flash memory is empty (contains all 0xFF). 207 | /// 208 | /// The name of the firmware backup file to evaluate. 209 | /// A boolean indicating whether or not the EEPROM data is empty. 210 | internal static bool EepromIsEmpty(string filename) 211 | { 212 | byte[] data = GetEepromDataFromBackup(filename); 213 | if (data != null) 214 | { 215 | return data.Distinct().Count() == 1 && data.Distinct().FirstOrDefault() == 255; 216 | } 217 | else 218 | { 219 | return true; 220 | } 221 | } 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /src/flash-multi/Program.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // 3 | // Copyright 2020 Ben Lye 4 | // 5 | // This file is part of Flash Multi. 6 | // 7 | // Flash Multi is free software: you can redistribute it and/or modify it under 8 | // the terms of the GNU General Public License as published by the Free Software 9 | // Foundation, either version 3 of the License, or(at your option) any later 10 | // version. 11 | // 12 | // Flash Multi is distributed in the hope that it will be useful, but WITHOUT 13 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License along with 17 | // Flash Multi. If not, see http://www.gnu.org/licenses/. 18 | // 19 | // ------------------------------------------------------------------------------- 20 | 21 | namespace Flash_Multi 22 | { 23 | using System; 24 | using System.Windows.Forms; 25 | 26 | /// 27 | /// The main class. 28 | /// 29 | public static class Program 30 | { 31 | /// 32 | /// The main entry point for the application. 33 | /// 34 | [STAThread] 35 | private static void Main() 36 | { 37 | Application.EnableVisualStyles(); 38 | Application.SetCompatibleTextRenderingDefault(false); 39 | Application.Run(new FlashMulti()); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/flash-multi/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // 3 | // Copyright 2020 Ben Lye 4 | // 5 | // This file is part of Flash Multi. 6 | // 7 | // Flash Multi is free software: you can redistribute it and/or modify it under 8 | // the terms of the GNU General Public License as published by the Free Software 9 | // Foundation, either version 3 of the License, or(at your option) any later 10 | // version. 11 | // 12 | // Flash Multi is distributed in the hope that it will be useful, but WITHOUT 13 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License along with 17 | // Flash Multi. If not, see http://www.gnu.org/licenses/. 18 | // 19 | // ------------------------------------------------------------------------------- 20 | 21 | using System.Reflection; 22 | using System.Runtime.InteropServices; 23 | 24 | // General Information about an assembly is controlled through the following 25 | // set of attributes. Change these attribute values to modify the information 26 | // associated with an assembly. 27 | [assembly: AssemblyTitle("flash-multi")] 28 | [assembly: AssemblyDescription("MULTI-Module firmware updater")] 29 | [assembly: AssemblyConfiguration("")] 30 | [assembly: AssemblyCompany("Ben Lye")] 31 | [assembly: AssemblyProduct("flash-multi")] 32 | [assembly: AssemblyCopyright("Copyright © 2020")] 33 | [assembly: AssemblyTrademark("")] 34 | [assembly: AssemblyCulture("")] 35 | 36 | // Setting ComVisible to false makes the types in this assembly not visible 37 | // to COM components. If you need to access a type in this assembly from 38 | // COM, set the ComVisible attribute to true on that type. 39 | [assembly: ComVisible(false)] 40 | 41 | // The following GUID is for the ID of the typelib if this project is exposed to COM 42 | [assembly: Guid("72d5a55c-cc93-422c-a12f-cce99e1c7300")] 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("0.6.2")] 55 | [assembly: AssemblyFileVersion("0.6.2")] 56 | -------------------------------------------------------------------------------- /src/flash-multi/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Flash_Multi.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Flash_Multi.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/flash-multi/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /src/flash-multi/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Flash_Multi.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.7.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | 26 | [global::System.Configuration.UserScopedSettingAttribute()] 27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 28 | [global::System.Configuration.DefaultSettingValueAttribute("-1, -1")] 29 | public global::System.Drawing.Point WindowLocation { 30 | get { 31 | return ((global::System.Drawing.Point)(this["WindowLocation"])); 32 | } 33 | set { 34 | this["WindowLocation"] = value; 35 | } 36 | } 37 | 38 | [global::System.Configuration.UserScopedSettingAttribute()] 39 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 40 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 41 | public bool CheckForUpdates { 42 | get { 43 | return ((bool)(this["CheckForUpdates"])); 44 | } 45 | set { 46 | this["CheckForUpdates"] = value; 47 | } 48 | } 49 | 50 | [global::System.Configuration.UserScopedSettingAttribute()] 51 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 52 | [global::System.Configuration.DefaultSettingValueAttribute("115200")] 53 | public int SerialBaudRate { 54 | get { 55 | return ((int)(this["SerialBaudRate"])); 56 | } 57 | set { 58 | this["SerialBaudRate"] = value; 59 | } 60 | } 61 | 62 | [global::System.Configuration.UserScopedSettingAttribute()] 63 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 64 | [global::System.Configuration.DefaultSettingValueAttribute("-1, -1")] 65 | public global::System.Drawing.Point SerialMonitorWindowLocation { 66 | get { 67 | return ((global::System.Drawing.Point)(this["SerialMonitorWindowLocation"])); 68 | } 69 | set { 70 | this["SerialMonitorWindowLocation"] = value; 71 | } 72 | } 73 | 74 | [global::System.Configuration.UserScopedSettingAttribute()] 75 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 76 | [global::System.Configuration.DefaultSettingValueAttribute("en-US")] 77 | public string Language { 78 | get { 79 | return ((string)(this["Language"])); 80 | } 81 | set { 82 | this["Language"] = value; 83 | } 84 | } 85 | 86 | [global::System.Configuration.UserScopedSettingAttribute()] 87 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 88 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 89 | public bool RunAfterUpload { 90 | get { 91 | return ((bool)(this["RunAfterUpload"])); 92 | } 93 | set { 94 | this["RunAfterUpload"] = value; 95 | } 96 | } 97 | 98 | [global::System.Configuration.UserScopedSettingAttribute()] 99 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 100 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 101 | public bool EnableDeviceDetection { 102 | get { 103 | return ((bool)(this["EnableDeviceDetection"])); 104 | } 105 | set { 106 | this["EnableDeviceDetection"] = value; 107 | } 108 | } 109 | 110 | [global::System.Configuration.UserScopedSettingAttribute()] 111 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 112 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 113 | public bool ErrorIfNoUSB { 114 | get { 115 | return ((bool)(this["ErrorIfNoUSB"])); 116 | } 117 | set { 118 | this["ErrorIfNoUSB"] = value; 119 | } 120 | } 121 | 122 | [global::System.Configuration.UserScopedSettingAttribute()] 123 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 124 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 125 | public bool WarnIfNoUSB { 126 | get { 127 | return ((bool)(this["WarnIfNoUSB"])); 128 | } 129 | set { 130 | this["WarnIfNoUSB"] = value; 131 | } 132 | } 133 | 134 | [global::System.Configuration.UserScopedSettingAttribute()] 135 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 136 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 137 | public bool DisableFlashVerification { 138 | get { 139 | return ((bool)(this["DisableFlashVerification"])); 140 | } 141 | set { 142 | this["DisableFlashVerification"] = value; 143 | } 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/flash-multi/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -1, -1 7 | 8 | 9 | True 10 | 11 | 12 | 115200 13 | 14 | 15 | -1, -1 16 | 17 | 18 | en-US 19 | 20 | 21 | False 22 | 23 | 24 | True 25 | 26 | 27 | False 28 | 29 | 30 | True 31 | 32 | 33 | False 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/flash-multi/README.txt: -------------------------------------------------------------------------------- 1 | 2 | Flash Multi Readme 3 | ============================== 4 | 5 | 1. MULTI-Module Drivers 6 | 7 | The Flash Multi installer only installs USB and DFU mode drivers for 8 | the native 'Maple' serial port (if they are selected). 9 | 10 | If your version of Windows requires additional serial port drivers 11 | for your MULTI-Module, you will need to install those manually. 12 | 13 | See the Flash Multi documentation for more information. 14 | https://github.com/benlye/flash-multi/ 15 | -------------------------------------------------------------------------------- /src/flash-multi/RunCommand.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // 3 | // Copyright 2020 Ben Lye 4 | // 5 | // This file is part of Flash Multi. 6 | // 7 | // Flash Multi is free software: you can redistribute it and/or modify it under 8 | // the terms of the GNU General Public License as published by the Free Software 9 | // Foundation, either version 3 of the License, or(at your option) any later 10 | // version. 11 | // 12 | // Flash Multi is distributed in the hope that it will be useful, but WITHOUT 13 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License along with 17 | // Flash Multi. If not, see http://www.gnu.org/licenses/. 18 | // 19 | // ------------------------------------------------------------------------------- 20 | 21 | namespace Flash_Multi 22 | { 23 | using System.Diagnostics; 24 | using System.IO; 25 | 26 | /// 27 | /// Class for running commands. 28 | /// 29 | internal class RunCommand 30 | { 31 | /// 32 | /// Runs a command with arguments. 33 | /// 34 | /// An instance of the class. 35 | /// The command to run. 36 | /// Arguments for the command. 37 | /// The exit code returned by the command. 38 | public static int Run(FlashMulti flashMulti, string command, string args) 39 | { 40 | Debug.WriteLine("\n" + command + " " + args + "\n"); 41 | flashMulti.AppendVerbose(command + " " + args + "\r\n"); 42 | 43 | // Check if the file exists 44 | if (!File.Exists(command)) 45 | { 46 | flashMulti.AppendVerbose(string.Format("{0} does not exist", command)); 47 | return -1; 48 | } 49 | 50 | Process myProcess = new Process(); 51 | 52 | // Process process = new Process(); 53 | myProcess.StartInfo.FileName = command; 54 | myProcess.StartInfo.Arguments = args; 55 | myProcess.StartInfo.UseShellExecute = false; 56 | myProcess.StartInfo.RedirectStandardOutput = true; 57 | myProcess.StartInfo.RedirectStandardError = true; 58 | myProcess.StartInfo.CreateNoWindow = true; 59 | 60 | // avrdude sends all output to stderr, so reverse the sync/async processing 61 | if (command.EndsWith("avrdude.exe")) 62 | { 63 | // Handle standard output asynchronously 64 | myProcess.OutputDataReceived += new DataReceivedEventHandler(flashMulti.OutputHandler); 65 | 66 | // Start process and handlers 67 | myProcess.Start(); 68 | 69 | // Read the standard output asynchronously, handle it by line 70 | myProcess.BeginOutputReadLine(); 71 | 72 | // Read the error output synchronously, handle it character-by-character 73 | while (!myProcess.StandardError.EndOfStream) 74 | { 75 | var data = myProcess.StandardError.Read(); 76 | flashMulti.CharOutputHandler((char)data); 77 | } 78 | } 79 | else 80 | { 81 | // Hande error output asynchronously 82 | myProcess.ErrorDataReceived += new DataReceivedEventHandler(flashMulti.OutputHandler); 83 | 84 | // Start process and handlers 85 | myProcess.Start(); 86 | 87 | // Read the error output asynchronously, handle it by line 88 | myProcess.BeginErrorReadLine(); 89 | 90 | // Read the standard output synchronously, handle it character-by-character 91 | while (!myProcess.StandardOutput.EndOfStream) 92 | { 93 | var data = myProcess.StandardOutput.Read(); 94 | flashMulti.CharOutputHandler((char)data); 95 | } 96 | } 97 | 98 | // Loop until the process finishes 99 | myProcess.WaitForExit(); 100 | 101 | int returnCode = myProcess.ExitCode; 102 | myProcess.Dispose(); 103 | 104 | // Return the exit code from the process 105 | return returnCode; 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/flash-multi/UpdateCheck.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // 3 | // Copyright 2020 Ben Lye 4 | // 5 | // This file is part of Flash Multi. 6 | // 7 | // Flash Multi is free software: you can redistribute it and/or modify it under 8 | // the terms of the GNU General Public License as published by the Free Software 9 | // Foundation, either version 3 of the License, or(at your option) any later 10 | // version. 11 | // 12 | // Flash Multi is distributed in the hope that it will be useful, but WITHOUT 13 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License along with 17 | // Flash Multi. If not, see http://www.gnu.org/licenses/. 18 | // 19 | // ------------------------------------------------------------------------------- 20 | 21 | namespace Flash_Multi 22 | { 23 | using System; 24 | using System.Diagnostics; 25 | using System.IO; 26 | using System.Net; 27 | using System.Text.RegularExpressions; 28 | using System.Threading.Tasks; 29 | using System.Windows.Forms; 30 | 31 | /// 32 | /// Class for performing application update checks. 33 | /// 34 | internal class UpdateCheck 35 | { 36 | /// 37 | /// Gets a value indicating whether or not the Github version check succeeded. 38 | /// 39 | public bool CheckSuccess { get; private set; } 40 | 41 | /// 42 | /// Gets a containing the version of the latest release. 43 | /// 44 | public Version LatestVersion { get; private set; } 45 | 46 | /// 47 | /// Gets a string containing the URL of the latest release. 48 | /// 49 | public string ReleaseUrl { get; private set; } 50 | 51 | /// 52 | /// Prompt the user if a newer version is available. 53 | /// 54 | /// An instance of the class. 55 | /// Indicate whether or not to show a message if there is no update. 56 | public static async void DoCheck(FlashMulti flashMulti, bool showNoUpdate = false) 57 | { 58 | // Get check for the latest version on Github 59 | UpdateCheck check = new UpdateCheck(); 60 | await Task.Run(() => { check = GetLatestVersion(); }); 61 | 62 | // If the check completed successfully 63 | if (check.CheckSuccess) 64 | { 65 | // Get the current version 66 | Version currentVersion = Version.Parse(Application.ProductVersion); 67 | 68 | // Get the version available on Github 69 | Version latestVersion = check.LatestVersion; 70 | 71 | // Check if the current version is older than the latest Github release version 72 | if (currentVersion.CompareTo(latestVersion) == -1) 73 | { 74 | // A newer version is available to show the user a prompt 75 | Debug.WriteLine($"App version is older than latest version: {currentVersion} < {latestVersion}"); 76 | 77 | DialogResult showUpdate; 78 | using (new CenterWinDialog(flashMulti)) 79 | { 80 | showUpdate = MessageBox.Show( 81 | $"{Strings.updatePromptPart1} v{currentVersion} {Strings.updatePromptPart2} v{latestVersion} {Strings.updatePromptPart3}", 82 | Strings.dialogTitleUpdateCheck, 83 | MessageBoxButtons.YesNo, 84 | MessageBoxIcon.Information); 85 | } 86 | 87 | // Show the Github release page for the new version if the user clicked Yes 88 | if (showUpdate == DialogResult.Yes) 89 | { 90 | flashMulti.OpenLink(check.ReleaseUrl); 91 | } 92 | } 93 | else 94 | { 95 | if (showNoUpdate) 96 | { 97 | using (new CenterWinDialog(flashMulti)) 98 | { 99 | MessageBox.Show(Strings.updateNoUpdate, Strings.dialogTitleUpdateCheck, MessageBoxButtons.OK); 100 | } 101 | } 102 | } 103 | } 104 | else 105 | { 106 | if (showNoUpdate) 107 | { 108 | using (new CenterWinDialog(flashMulti)) 109 | { 110 | MessageBox.Show(Strings.updateCheckFailed, Strings.dialogTitleUpdateCheck, MessageBoxButtons.OK); 111 | } 112 | } 113 | } 114 | } 115 | 116 | /// 117 | /// Gets the latest release tag from Github. 118 | /// 119 | /// Returns an . 120 | private static UpdateCheck GetLatestVersion() 121 | { 122 | // Somewhere to store the results 123 | UpdateCheck results = new UpdateCheck 124 | { 125 | CheckSuccess = false, 126 | }; 127 | 128 | try 129 | { 130 | // The API URL to check for the latest release 131 | // Returns a JSON payload containing all the details of the latest release 132 | string releasesUrl = "https://api.github.com/repos/benlye/flash-multi/releases/latest"; 133 | 134 | // Set TLS1.2, as required by the Github API 135 | System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; 136 | 137 | // Create the WebRequest 138 | HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(releasesUrl); 139 | 140 | // Set the UserAgent, as required by the Github API 141 | webRequest.UserAgent = $"flash-multi-{Application.ProductVersion}"; 142 | 143 | // Disable keepalive so we don't hold a connection open 144 | webRequest.KeepAlive = false; 145 | 146 | // Get the response and read it 147 | using (WebResponse myResponse = webRequest.GetResponse()) 148 | using (StreamReader sr = new StreamReader(myResponse.GetResponseStream(), System.Text.Encoding.UTF8)) 149 | { 150 | // Read all of the output from the StreamReader 151 | string result = sr.ReadToEnd(); 152 | 153 | // Parse the release tag out of the JSON 154 | // This contains the version string 155 | int tagStart = result.IndexOf("\"tag_name\":"); 156 | int tagEnd = result.IndexOf(",", tagStart); 157 | string tagLine = result.Substring(tagStart, tagEnd - tagStart); 158 | string tag = tagLine.Split('"')[3]; 159 | 160 | // Add the release tag to the results 161 | results.LatestVersion = Version.Parse(tag); 162 | 163 | // Parse the release URL out of the JSON 164 | // This is the URL of the Github page containing details of the latest release 165 | int urlStart = result.IndexOf("\"html_url\":"); 166 | int urlEnd = result.IndexOf(",", urlStart); 167 | string urlLine = result.Substring(urlStart, urlEnd - urlStart); 168 | string url = urlLine.Split('"')[3]; 169 | 170 | // Add the release URL to the results 171 | results.ReleaseUrl = url; 172 | } 173 | 174 | // Define a regular expression to test the version number looks how we expect it to 175 | Regex versionRegex = new Regex(@"\d+\.\d+\.\d+"); 176 | 177 | // Check that the URL and version number are as we expect 178 | if (results.ReleaseUrl.StartsWith("https://github.com/benlye/flash-multi/releases/") && versionRegex.Match(results.LatestVersion.ToString()).Success) 179 | { 180 | // All looks good; the check succeeded 181 | Debug.WriteLine($"Update check succeeded. Latest version is {results.LatestVersion}"); 182 | results.CheckSuccess = true; 183 | } 184 | } 185 | catch (Exception ex) 186 | { 187 | Debug.WriteLine($"Error getting latest version: {ex.Message}"); 188 | } 189 | 190 | // Return the results 191 | return results; 192 | } 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /src/flash-multi/UsbDeviceInfo.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // 3 | // Copyright 2020 Ben Lye 4 | // 5 | // This file is part of Flash Multi. 6 | // 7 | // Flash Multi is free software: you can redistribute it and/or modify it under 8 | // the terms of the GNU General Public License as published by the Free Software 9 | // Foundation, either version 3 of the License, or(at your option) any later 10 | // version. 11 | // 12 | // Flash Multi is distributed in the hope that it will be useful, but WITHOUT 13 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License along with 17 | // Flash Multi. If not, see http://www.gnu.org/licenses/. 18 | // 19 | // ------------------------------------------------------------------------------- 20 | 21 | namespace Flash_Multi 22 | { 23 | using System.Collections.Generic; 24 | using System.Management; 25 | 26 | /// 27 | /// Class for retrieving information about connected USB devices. 28 | /// 29 | internal class UsbDeviceInfo 30 | { 31 | /// 32 | /// Initializes a new instance of the class. 33 | /// 34 | /// The USB device ID. 35 | /// The PNP Device ID. 36 | /// Description of the device. 37 | /// Device manufacturer. 38 | /// Device name. 39 | /// Device status. 40 | public UsbDeviceInfo(string deviceID, string pnpDeviceID, string description, string manufacturer, string name, string status) 41 | { 42 | this.DeviceID = deviceID; 43 | this.PnpDeviceID = pnpDeviceID; 44 | this.Description = description; 45 | this.Manufacturer = manufacturer; 46 | this.Name = name; 47 | this.Status = status; 48 | } 49 | 50 | /// 51 | /// Gets the device ID. 52 | /// 53 | public string DeviceID { get; private set; } 54 | 55 | /// 56 | /// Gets the PnP device ID. 57 | /// 58 | public string PnpDeviceID { get; private set; } 59 | 60 | /// 61 | /// Gets the device description. 62 | /// 63 | public string Description { get; private set; } 64 | 65 | /// 66 | /// Gets the device manufacturer. 67 | /// 68 | public string Manufacturer { get; private set; } 69 | 70 | /// 71 | /// Gets the device name. 72 | /// 73 | public string Name { get; private set; } 74 | 75 | /// 76 | /// Gets the device status. 77 | /// 78 | public string Status { get; private set; } 79 | 80 | /// 81 | /// Gets a list of devices matching the Maple DeviceID. 82 | /// 83 | /// Returns a list of devices. 84 | public static List GetUSBDevices() 85 | { 86 | // Create a list to store the output 87 | List devices = new List(); 88 | 89 | // Use WMI to find all the Maple devices 90 | ManagementObjectCollection collection; 91 | using (var searcher = new ManagementObjectSearcher(@"Select * From Win32_PnPEntity WHERE DeviceID like '%VID_1EAF&%' OR DeviceID like '%VID_16C0%'")) 92 | using (collection = searcher.Get()) 93 | { 94 | foreach (var device in collection) 95 | { 96 | devices.Add(new UsbDeviceInfo( 97 | (string)device.GetPropertyValue("DeviceID"), 98 | (string)device.GetPropertyValue("PNPDeviceID"), 99 | (string)device.GetPropertyValue("Description"), 100 | (string)device.GetPropertyValue("Manufacturer"), 101 | (string)device.GetPropertyValue("Name"), 102 | (string)device.GetPropertyValue("Status"))); 103 | } 104 | } 105 | 106 | // Return the list of devices 107 | return devices; 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/flash-multi/UsbNotification.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // 3 | // Copyright 2020 Ben Lye 4 | // 5 | // This file is part of Flash Multi. 6 | // 7 | // Flash Multi is free software: you can redistribute it and/or modify it under 8 | // the terms of the GNU General Public License as published by the Free Software 9 | // Foundation, either version 3 of the License, or(at your option) any later 10 | // version. 11 | // 12 | // Flash Multi is distributed in the hope that it will be useful, but WITHOUT 13 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License along with 17 | // Flash Multi. If not, see http://www.gnu.org/licenses/. 18 | // 19 | // ------------------------------------------------------------------------------- 20 | 21 | namespace Flash_Multi 22 | { 23 | using System; 24 | using System.Runtime.InteropServices; 25 | 26 | /// 27 | /// Class for handling USB devices being plugged / unplugged. 28 | /// 29 | internal static class UsbNotification 30 | { 31 | /// 32 | /// Constant indicating a new device. 33 | /// 34 | public const int DbtDevicearrival = 0x8000; // system detected a new device 35 | 36 | /// 37 | /// Constant indicating a device has been removed. 38 | /// 39 | public const int DbtDeviceremovecomplete = 0x8004; 40 | 41 | /// 42 | /// Constant indicating a device change event. 43 | /// 44 | public const int WmDevicechange = 0x0219; 45 | 46 | /// 47 | /// Device type. 48 | /// 49 | private const int DbtDevtypDeviceinterface = 5; 50 | 51 | /// 52 | /// GUID for USB devices. 53 | /// 54 | private static readonly Guid GuidDevinterfaceUSBDevice = new Guid("A5DCBF10-6530-11D2-901F-00C04FB951ED"); 55 | private static IntPtr notificationHandle; 56 | 57 | /// 58 | /// Registers a window to receive notifications when USB devices are plugged or unplugged. 59 | /// 60 | /// Handle to the window receiving notifications. 61 | public static void RegisterUsbDeviceNotification(IntPtr windowHandle) 62 | { 63 | DevBroadcastDeviceinterface dbi = new DevBroadcastDeviceinterface 64 | { 65 | DeviceType = DbtDevtypDeviceinterface, 66 | Reserved = 0, 67 | ClassGuid = GuidDevinterfaceUSBDevice, 68 | Name = 0, 69 | }; 70 | 71 | dbi.Size = Marshal.SizeOf(dbi); 72 | IntPtr buffer = Marshal.AllocHGlobal(dbi.Size); 73 | Marshal.StructureToPtr(dbi, buffer, true); 74 | 75 | notificationHandle = RegisterDeviceNotification(windowHandle, buffer, 0); 76 | } 77 | 78 | /// 79 | /// Unregisters the window for USB device notifications. 80 | /// 81 | public static void UnregisterUsbDeviceNotification() 82 | { 83 | UnregisterDeviceNotification(notificationHandle); 84 | } 85 | 86 | [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 87 | private static extern IntPtr RegisterDeviceNotification(IntPtr recipient, IntPtr notificationFilter, int flags); 88 | 89 | [DllImport("user32.dll")] 90 | private static extern bool UnregisterDeviceNotification(IntPtr handle); 91 | 92 | [StructLayout(LayoutKind.Sequential)] 93 | private struct DevBroadcastDeviceinterface 94 | { 95 | internal int Size; 96 | internal int DeviceType; 97 | internal int Reserved; 98 | internal Guid ClassGuid; 99 | internal short Name; 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/flash-multi/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | -1, -1 12 | 13 | 14 | True 15 | 16 | 17 | 115200 18 | 19 | 20 | -1, -1 21 | 22 | 23 | en-US 24 | 25 | 26 | False 27 | 28 | 29 | True 30 | 31 | 32 | False 33 | 34 | 35 | True 36 | 37 | 38 | False 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/flash-multi/flash-multi.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {72D5A55C-CC93-422C-A12F-CCE99E1C7300} 8 | WinExe 9 | Flash_Multi 10 | flash-multi 11 | v4.5 12 | 512 13 | true 14 | 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | false 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | false 36 | 37 | 38 | icon.ico 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | Form 57 | 58 | 59 | UsbSupportErrorDialog.cs 60 | 61 | 62 | Form 63 | 64 | 65 | UsbSupportWarningDialog.cs 66 | 67 | 68 | 69 | 70 | Form 71 | 72 | 73 | DfuRecoveryDialog.cs 74 | 75 | 76 | 77 | 78 | Form 79 | 80 | 81 | FlashMulti.cs 82 | 83 | 84 | 85 | 86 | 87 | True 88 | True 89 | Resources.resx 90 | 91 | 92 | 93 | 94 | Form 95 | 96 | 97 | SerialMonitor.cs 98 | 99 | 100 | True 101 | True 102 | Strings.resx 103 | 104 | 105 | 106 | 107 | 108 | 109 | DfuRecoveryDialog.cs 110 | 111 | 112 | SerialMonitor.cs 113 | 114 | 115 | UsbSupportErrorDialog.cs 116 | 117 | 118 | UsbSupportWarningDialog.cs 119 | 120 | 121 | FlashMulti.cs 122 | 123 | 124 | FlashMulti.cs 125 | 126 | 127 | SerialMonitor.cs 128 | 129 | 130 | ResXFileCodeGenerator 131 | Strings.Designer.cs 132 | Flash_Multi 133 | 134 | 135 | ResXFileCodeGenerator 136 | Resources.Designer.cs 137 | 138 | 139 | 140 | 141 | SettingsSingleFileGenerator 142 | Settings.Designer.cs 143 | 144 | 145 | True 146 | Settings.settings 147 | True 148 | 149 | 150 | 151 | 152 | 153 | Always 154 | 155 | 156 | 157 | Always 158 | 159 | 160 | Always 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | XCOPY "$(SolutionDir)tools\*.*" "$(TargetDir)" /S /Y 171 | 172 | -------------------------------------------------------------------------------- /src/flash-multi/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/src/flash-multi/icon.ico -------------------------------------------------------------------------------- /src/flash-multi/license.txt: -------------------------------------------------------------------------------- 1 | Copyright 2019 Ben Lye 2 | 3 | Flash Multi is free software: you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation, either version 3 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with Flash Multi. If not, see . 15 | -------------------------------------------------------------------------------- /src/flash-multi/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/flash-multi/stylecop.json: -------------------------------------------------------------------------------- 1 | { 2 | // ACTION REQUIRED: This file was automatically added to your project, but it 3 | // will not take effect until additional steps are taken to enable it. See the 4 | // following page for additional information: 5 | // 6 | // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md 7 | 8 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", 9 | "settings": { 10 | "documentationRules": { 11 | "companyName": "Ben Lye", 12 | "copyrightText": "Copyright 2020 Ben Lye\n\nThis file is part of Flash Multi.\n\nFlash Multi is free software: you can redistribute it and/or modify it under\nthe terms of the GNU General Public License as published by the Free Software\nFoundation, either version 3 of the License, or(at your option) any later\nversion.\n\nFlash Multi is distributed in the hope that it will be useful, but WITHOUT\nANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\nFOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nFlash Multi. If not, see http://www.gnu.org/licenses/.", 13 | "headerDecoration": "-------------------------------------------------------------------------------" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/make_release.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Import the Visual Studio command line build environment, remembering the current working directory 4 | PUSHD %cd% 5 | IF EXIST "%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Professional\Common7\Tools\VsMSBuildCmd.bat" ( 6 | CALL "%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Professional\Common7\Tools\VsDevCmd.bat" 7 | POPD 8 | GOTO BUILD 9 | ) 10 | IF EXIST "%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Professional\Common7\Tools\VsMSBuildCmd.bat" ( 11 | CALL "%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Professional\Common7\Tools\VsMSBuildCmd.bat" 12 | POPD 13 | GOTO BUILD 14 | ) 15 | 16 | ECHO Couldn't find Visual Studio tools 17 | GOTO :EOF 18 | 19 | :BUILD 20 | REM Delete any existing build output 21 | rmdir /s /q .\flash-multi\bin 22 | 23 | REM Run the build command 24 | msbuild /t:Clean /p:Configuration=Release 25 | msbuild /t:Build /p:Configuration=Release 26 | 27 | REM Get the version 28 | FOR /F "USEBACKQ" %%F IN (`powershell -NoLogo -NoProfile -Command ^(Get-Item ".\flash-multi\bin\Release\flash-multi.exe"^).VersionInfo.FileVersion`) DO (SET fileVersion=%%F) 29 | echo File version: %fileVersion% 30 | 31 | REM Create the zip archive 32 | "C:\Program Files\7-Zip\7z.exe" a -r -x!*.pdb .\flash-multi\bin\flash-multi-%fileVersion%.zip .\flash-multi\bin\Release 33 | 34 | REM Rename the root folder in the zip 35 | "C:\Program Files\7-Zip\7z.exe" rn .\flash-multi\bin\flash-multi-%fileVersion%.zip Release\ flash-multi-%fileVersion%\ 36 | 37 | REM Create the installer package 38 | REM "C:\Program Files (x86)\Inno Setup 6\iscc.exe" /Qp /DMyAppVersion=%fileVersion% flash-multi.iss 39 | REM "C:\Program Files (x86)\NSIS\Bin\makensis.exe" /DVERSION=%fileVersion% flash-multi.nsi 40 | 41 | REM Get the SH256 hashes from the files 42 | ECHO. 43 | FOR /F "USEBACKQ" %%F IN (`powershell -NoLogo -NoProfile -Command ^(Get-FileHash ".\flash-multi\bin\flash-multi-%fileVersion%.zip"^).Hash`) DO (SET fileHash=%%F) 44 | ECHO flash-multi-%fileVersion%.zip: %fileHash% 45 | 46 | REM FOR /F "USEBACKQ" %%F IN (`powershell -NoLogo -NoProfile -Command ^(Get-FileHash ".\flash-multi\bin\flash-multi-%fileVersion%.exe"^).Hash`) DO (SET fileHash=%%F) 47 | REM ECHO flash-multi-%fileVersion%.exe: %fileHash% 48 | -------------------------------------------------------------------------------- /src/make_release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | VERSION=$(grep "^VERSION=[0-9].[0-9].[0-9]" "../linux/flash-multi" | awk -F = '{ print $2 }') 4 | 5 | echo 6 | echo "Version: $VERSION" 7 | echo "Creating archive 'flash-multi-$VERSION.tar.gz'" 8 | tar -czf /tmp/flash-multi-$VERSION.tar.gz --transform s/linux/flash-multi-$VERSION/ ../linux/* 9 | sleep 1s 10 | 11 | SHA=`(sha256sum /tmp/flash-multi-$VERSION.tar.gz | awk -v N=1 '{print $N}')` 12 | 13 | echo 14 | echo "Package: flash-multi-$VERSION.tar.gz" 15 | echo "SHA256: ${SHA^^}" 16 | echo "Size: `(ls -al /tmp/flash-multi-$VERSION.tar.gz | awk -v N=5 '{print $N}')`" 17 | echo 18 | -------------------------------------------------------------------------------- /src/tools/bootloaders/AtmegaMultiBoot.hex: -------------------------------------------------------------------------------- 1 | :107E0000112484B714BE9FEF9BB99CE395B991E010 2 | :107E100098B98370A9F08AEF80938500109284004E 3 | :107E200085E08093810096BBB09BFECF10928100CD 4 | :107E300093B186B181709C73892B8D3109F0B3D0D9 5 | :107E400082E08093C00088E18093C10086E0809347 6 | :107E5000C20081E28093C400259AC0E0D0E093E0A4 7 | :107E6000F92EEE24E39425E0D22E31E1C32EA9D0E1 8 | :107E7000813481F4A6D08EBBABD08EB3823811F49E 9 | :107E800085E006C08EB3813811F484E001C083E040 10 | :107E900091D086C0823411F484E103C0853419F492 11 | :107EA00085E09DD07DC0853541F48BD0C82F89D029 12 | :107EB000D0E0D82BCC0FDD1F72C0863521F484E0D2 13 | :107EC0008ED080E0E5CF843609F03DC07AD079D0FD 14 | :107ED000B82E77D0C11520E7D20718F000E011E0E6 15 | :107EE00004C0FE01F7BEE895F9CF6BD0F80181938D 16 | :107EF0008F01BE12FACFCE01905781159E4018F423 17 | :107F0000FE01F7BEE89564D0C115FEE7DF0708F073 18 | :107F100047C007B600FCFDCFFE01A0E0B1E08D91A7 19 | :107F20009D910C01E7BEE89511243296A03821E01E 20 | :107F3000B207A9F7FE01D7BEE89507B600FCFDCF52 21 | :107F4000C7BEE8952DC08437B1F43BD03AD0B82EE7 22 | :107F500038D03ED0FE01AC2EAB0C8F010F5F1F4F0F 23 | :107F6000849128D0A01205C02196BA94CB0DD11DC2 24 | :107F700017C0F801F2CF853739F42AD08EE11AD034 25 | :107F800085E918D08FE084CF813549F421D080E194 26 | :107F900011D08091C00086FFFCCF05D001C018D061 27 | :107FA00080E108D064CFE0E0F0E084918F3F09F0F9 28 | :107FB000099408959091C00095FFFCCF8093C6006E 29 | :107FC00008958091C00087FFFCCF8091C60008957E 30 | :107FD000F8DF803211F085E1EDDF84E1EBCFCF9364 31 | :107FE000C82FEFDFC150E9F7CF91F2CFA8950895E0 32 | :0C7FF000E0E6F0E098E1908380830895C3 33 | :0400000300007E007B 34 | :00000001FF 35 | -------------------------------------------------------------------------------- /src/tools/bootloaders/StmMulti4in1_Legacy.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/src/tools/bootloaders/StmMulti4in1_Legacy.bin -------------------------------------------------------------------------------- /src/tools/bootloaders/StmMulti4in1_StickyDfu.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/src/tools/bootloaders/StmMulti4in1_StickyDfu.bin -------------------------------------------------------------------------------- /src/tools/drivers/install_drivers.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | echo Installing MULTI-Module DFU Bootloader Driver... 4 | "%~dp0wdi-simple" --vid 0x1EAF --pid 0x0003 --type 2 --name "MULTI-Module DFU Bootloader" --dest "%~dp0MULTI-DFU-Bootloader" -b 5 | echo. 6 | 7 | echo Installing MULTI-Module USB Serial Driver... 8 | "%~dp0wdi-simple" --vid 0x1EAF --pid 0x0004 --type 3 --name "MULTI-Module USB Serial" --dest "%~dp0MULTI-USB-Serial" -b 9 | echo. 10 | -------------------------------------------------------------------------------- /src/tools/drivers/wdi-simple.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/src/tools/drivers/wdi-simple.exe -------------------------------------------------------------------------------- /src/tools/tools/BootReloader_Legacy.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/src/tools/tools/BootReloader_Legacy.bin -------------------------------------------------------------------------------- /src/tools/tools/BootReloader_StickyDfu.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/src/tools/tools/BootReloader_StickyDfu.bin -------------------------------------------------------------------------------- /src/tools/tools/avrdude.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/src/tools/tools/avrdude.exe -------------------------------------------------------------------------------- /src/tools/tools/dfu-util-multi.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/src/tools/tools/dfu-util-multi.exe -------------------------------------------------------------------------------- /src/tools/tools/erase1.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/src/tools/tools/erase1.bin -------------------------------------------------------------------------------- /src/tools/tools/erase118.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/src/tools/tools/erase118.bin -------------------------------------------------------------------------------- /src/tools/tools/erase120.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/src/tools/tools/erase120.bin -------------------------------------------------------------------------------- /src/tools/tools/erase32.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/src/tools/tools/erase32.bin -------------------------------------------------------------------------------- /src/tools/tools/libusb-1.0.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/src/tools/tools/libusb-1.0.dll -------------------------------------------------------------------------------- /src/tools/tools/libusb0.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/src/tools/tools/libusb0.dll -------------------------------------------------------------------------------- /src/tools/tools/maple-reset.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/src/tools/tools/maple-reset.exe -------------------------------------------------------------------------------- /src/tools/tools/stm32flash.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlye/flash-multi/5baf34d055c91859dfa03f79b8408d7714492f8b/src/tools/tools/stm32flash.exe --------------------------------------------------------------------------------