From a1d963959d0163bf7644ffcfb7bb5f2c4c620389 Mon Sep 17 00:00:00 2001 From: fauxpark Date: Thu, 10 Mar 2022 20:32:51 +1100 Subject: [PATCH 1/9] [Windows] USB detection and flashing rework --- windows/QMK Toolbox/Flashing.cs | 384 ------------------ .../Helpers/EmbeddedResourceHelper.cs | 13 +- windows/QMK Toolbox/MainWindow.cs | 273 +++++-------- windows/QMK Toolbox/QMK Toolbox.csproj | 20 +- windows/QMK Toolbox/USB.cs | 324 --------------- .../Usb/Bootloader/Apm32DfuDevice.cs | 30 ++ .../Usb/Bootloader/AtmelDfuDevice.cs | 50 +++ .../Usb/Bootloader/AtmelSamBaDevice.cs | 43 ++ .../Usb/Bootloader/AvrIspDevice.cs | 29 ++ .../Usb/Bootloader/BootloadHidDevice.cs | 19 + .../Usb/Bootloader/BootloaderDevice.cs | 134 ++++++ .../Usb/Bootloader/BootloaderType.cs | 21 + .../Usb/Bootloader/CaterinaDevice.cs | 43 ++ .../Usb/Bootloader/HalfKayDevice.cs | 19 + .../Usb/Bootloader/KiibohdDfuDevice.cs | 30 ++ .../Usb/Bootloader/LufaMsDevice.cs | 91 +++++ .../Usb/Bootloader/Stm32DfuDevice.cs | 30 ++ .../Usb/Bootloader/Stm32DuinoDevice.cs | 27 ++ .../Usb/Bootloader/UsbAspDevice.cs | 19 + .../Usb/Bootloader/UsbTinyIspDevice.cs | 19 + windows/QMK Toolbox/Usb/IUsbDevice.cs | 21 + windows/QMK Toolbox/Usb/UsbDevice.cs | 83 ++++ windows/QMK Toolbox/Usb/UsbListener.cs | 301 ++++++++++++++ 23 files changed, 1145 insertions(+), 878 deletions(-) delete mode 100644 windows/QMK Toolbox/Flashing.cs delete mode 100644 windows/QMK Toolbox/USB.cs create mode 100644 windows/QMK Toolbox/Usb/Bootloader/Apm32DfuDevice.cs create mode 100644 windows/QMK Toolbox/Usb/Bootloader/AtmelDfuDevice.cs create mode 100644 windows/QMK Toolbox/Usb/Bootloader/AtmelSamBaDevice.cs create mode 100644 windows/QMK Toolbox/Usb/Bootloader/AvrIspDevice.cs create mode 100644 windows/QMK Toolbox/Usb/Bootloader/BootloadHidDevice.cs create mode 100644 windows/QMK Toolbox/Usb/Bootloader/BootloaderDevice.cs create mode 100644 windows/QMK Toolbox/Usb/Bootloader/BootloaderType.cs create mode 100644 windows/QMK Toolbox/Usb/Bootloader/CaterinaDevice.cs create mode 100644 windows/QMK Toolbox/Usb/Bootloader/HalfKayDevice.cs create mode 100644 windows/QMK Toolbox/Usb/Bootloader/KiibohdDfuDevice.cs create mode 100644 windows/QMK Toolbox/Usb/Bootloader/LufaMsDevice.cs create mode 100644 windows/QMK Toolbox/Usb/Bootloader/Stm32DfuDevice.cs create mode 100644 windows/QMK Toolbox/Usb/Bootloader/Stm32DuinoDevice.cs create mode 100644 windows/QMK Toolbox/Usb/Bootloader/UsbAspDevice.cs create mode 100644 windows/QMK Toolbox/Usb/Bootloader/UsbTinyIspDevice.cs create mode 100644 windows/QMK Toolbox/Usb/IUsbDevice.cs create mode 100644 windows/QMK Toolbox/Usb/UsbDevice.cs create mode 100644 windows/QMK Toolbox/Usb/UsbListener.cs diff --git a/windows/QMK Toolbox/Flashing.cs b/windows/QMK Toolbox/Flashing.cs deleted file mode 100644 index b5e985a18e..0000000000 --- a/windows/QMK Toolbox/Flashing.cs +++ /dev/null @@ -1,384 +0,0 @@ -using QMK_Toolbox.Helpers; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Threading; -using System.Windows.Forms; - -namespace QMK_Toolbox -{ - public enum Chipset - { - Apm32Dfu, - AtmelDfu, - AtmelSamBa, - AvrIsp, - BootloadHid, - Caterina, - Halfkay, - Kiibohd, - LufaMs, - QmkDfu, - Stm32Dfu, - Stm32Duino, - UsbAsp, - UsbTiny, - NumberOfChipsets - }; - - public class Flashing : EventArgs - { - private readonly Process _process; - private readonly ProcessStartInfo _startInfo; - - public string ComPort = ""; - public string MountPoint = ""; - - private readonly Printing _printer; - public Usb Usb; - - private readonly string[] _resources = { - "avrdude.conf", - "reset.eep", - "reset_left.eep", - "reset_right.eep", - "avrdude.exe", - "bootloadHID.exe", - "dfu-programmer.exe", - "dfu-util.exe", - "mdloader.exe", - "teensy_loader_cli.exe", - "libftdi1.dll", - "libusb0.dll", - "libusb-0-1-4.dll", - "libusb-1.0.dll", - "libwinpthread-1.dll" - }; - - public Flashing(Printing printer) - { - _printer = printer; - EmbeddedResourceHelper.ExtractResources(_resources); - - _process = new Process(); - _startInfo = new ProcessStartInfo - { - UseShellExecute = false, - RedirectStandardError = true, - RedirectStandardOutput = true, - RedirectStandardInput = true, - CreateNoWindow = true - }; - } - - private void OnOutputDataReceived(object sender, DataReceivedEventArgs e) - { - Debug.Write(e.Data); - _printer.PrintResponse(e.Data, MessageType.Info); - } - - private void OnErrorDataReceived(object sender, DataReceivedEventArgs e) - { - Debug.Write(e.Data); - _printer.PrintResponse(e.Data, MessageType.Info); - } - - private void ProcessOutput(object streamReader) - { - StreamReader _stream = (StreamReader)streamReader; - string output; - - while (!_stream.EndOfStream) - { - output = _stream.ReadLine() + "\n"; - _printer.PrintResponse(output, MessageType.Info); - - if (output.Contains("Bootloader and code overlap.") || // DFU - output.Contains("exceeds remaining flash size!") || // BootloadHID - output.Contains("Not enough bytes in device info report")) // BootloadHID - { - _printer.Print("File is too large for device", MessageType.Error); - } - } - } - private void RunProcess(string command, string args) - { - _printer.Print($"{command} {args}", MessageType.Command); - _startInfo.WorkingDirectory = Application.LocalUserAppDataPath; - _startInfo.FileName = Path.Combine(Application.LocalUserAppDataPath, command); - _startInfo.Arguments = args; - _startInfo.RedirectStandardOutput = true; - _startInfo.RedirectStandardError = true; - _startInfo.UseShellExecute = false; - _process.StartInfo = _startInfo; - - _process.Start(); - - // Thread that handles STDOUT - Thread _ThreadProcessOutput = new Thread(ProcessOutput); - _ThreadProcessOutput.Start(_process.StandardOutput); - - // Thread that handles STDERR - _ThreadProcessOutput = new Thread(ProcessOutput); - _ThreadProcessOutput.Start(_process.StandardError); - - _process.WaitForExit(); - } - - public void Flash(string mcu, string file) - { - if (Usb.CanFlash(Chipset.AtmelDfu) || Usb.CanFlash(Chipset.QmkDfu)) - FlashAtmelDfu(mcu, file); - if (Usb.CanFlash(Chipset.Caterina)) - FlashCaterina(mcu, file); - if (Usb.CanFlash(Chipset.Halfkay)) - FlashHalfkay(mcu, file); - if (Usb.CanFlash(Chipset.Stm32Dfu)) - FlashStm32Dfu(file); - if (Usb.CanFlash(Chipset.Apm32Dfu)) - FlashApm32Dfu(file); - if (Usb.CanFlash(Chipset.Kiibohd)) - FlashKiibohd(file); - if (Usb.CanFlash(Chipset.LufaMs)) - FlashLufaMs(file); - if (Usb.CanFlash(Chipset.AvrIsp)) - FlashAvrIsp(mcu, file); - if (Usb.CanFlash(Chipset.UsbAsp)) - FlashUsbAsp(mcu, file); - if (Usb.CanFlash(Chipset.UsbTiny)) - FlashUsbTiny(mcu, file); - if (Usb.CanFlash(Chipset.BootloadHid)) - FlashBootloadHid(file); - if (Usb.CanFlash(Chipset.AtmelSamBa)) - FlashAtmelSamBa(file); - if (Usb.CanFlash(Chipset.Stm32Duino)) - FlashStm32Duino(file); - } - - public void Reset(string mcu) - { - if (Usb.CanFlash(Chipset.AtmelDfu) || Usb.CanFlash(Chipset.QmkDfu)) - ResetAtmelDfu(mcu); - if (Usb.CanFlash(Chipset.Halfkay)) - ResetHalfkay(mcu); - if (Usb.CanFlash(Chipset.BootloadHid)) - ResetBootloadHid(); - if (Usb.CanFlash(Chipset.AtmelSamBa)) - ResetAtmelSamBa(); - } - - public void ClearEeprom(string mcu) - { - if (Usb.CanFlash(Chipset.AtmelDfu) || Usb.CanFlash(Chipset.QmkDfu)) - ClearEepromAtmelDfu(mcu, !Usb.CanFlash(Chipset.QmkDfu)); - if (Usb.CanFlash(Chipset.Caterina)) - ClearEepromCaterina(mcu); - if (Usb.CanFlash(Chipset.UsbAsp)) - ClearEepromUsbAsp(mcu); - } - - public void SetHandedness(string mcu, bool rightHand) - { - if (Usb.CanFlash(Chipset.AtmelDfu) || Usb.CanFlash(Chipset.QmkDfu)) - SetHandednessAtmelDfu(mcu, rightHand, !Usb.CanFlash(Chipset.QmkDfu)); - if (Usb.CanFlash(Chipset.Caterina)) - SetHandednessCaterina(mcu, rightHand); - if (Usb.CanFlash(Chipset.UsbAsp)) - SetHandednessUsbAsp(mcu, rightHand); - } - - public bool CanFlash() => Usb.AreDevicesAvailable(); - - public bool CanReset() - { - var resettable = new List { - Chipset.AtmelDfu, - Chipset.AtmelSamBa, - Chipset.BootloadHid, - Chipset.Halfkay, - Chipset.QmkDfu - }; - foreach (Chipset chipset in resettable) - { - if (Usb.CanFlash(chipset)) - return true; - } - return false; - } - - public bool CanClearEeprom() - { - var clearable = new List - { - Chipset.AtmelDfu, - Chipset.Caterina, - Chipset.QmkDfu, - Chipset.UsbAsp - }; - foreach (Chipset chipset in clearable) - { - if (Usb.CanFlash(chipset)) - return true; - } - return false; - } - - private void FlashApm32Dfu(string file) - { - if (Path.GetExtension(file)?.ToLower() == ".bin") - { - RunProcess("dfu-util.exe", $"-a 0 -d 314B:0106 -s 0x08000000:leave -D \"{file}\""); - } - else - { - _printer.Print("Only firmware files in .bin format can be flashed with dfu-util!", MessageType.Error); - } - } - - private void FlashAtmelDfu(string mcu, string file) - { - RunProcess("dfu-programmer.exe", $"{mcu} erase --force"); - RunProcess("dfu-programmer.exe", $"{mcu} flash --force \"{file}\""); - RunProcess("dfu-programmer.exe", $"{mcu} reset"); - } - - private void ResetAtmelDfu(string mcu) => RunProcess("dfu-programmer.exe", $"{mcu} reset"); - - private void ClearEepromAtmelDfu(string mcu, bool erase) - { - if (erase) - { - RunProcess("dfu-programmer.exe", $"{mcu} erase --force"); - } - RunProcess("dfu-programmer.exe", $"{mcu} flash --force --suppress-validation --eeprom reset.eep"); - if (erase) - { - _printer.Print("Please reflash device with firmware now", MessageType.Bootloader); - } - } - - private void SetHandednessAtmelDfu(string mcu, bool rightHand, bool erase) - { - if (erase) - { - RunProcess("dfu-programmer.exe", $"{mcu} erase --force"); - } - RunProcess("dfu-programmer.exe", $"{mcu} flash --force --suppress-validation --eeprom reset_{(rightHand ? "right" : "left")}.eep"); - if (erase) - { - _printer.Print("Please reflash device with firmware now", MessageType.Bootloader); - } - } - - private void FlashAtmelSamBa(string file) => RunProcess("mdloader.exe", $"-p {ComPort} -D \"{file}\" --restart"); - - private void ResetAtmelSamBa() => RunProcess("mdloader.exe", $"-p {ComPort} --restart"); - - private void FlashAvrIsp(string mcu, string file) - { - RunProcess("avrdude.exe", $"-p {mcu} -c avrisp -U flash:w:\"{file}\":i -P {ComPort}"); - _printer.Print("Flash complete", MessageType.Bootloader); - } - - private void FlashBootloadHid(string file) => RunProcess("bootloadHID.exe", $"-r \"{file}\""); - - private void ResetBootloadHid() => RunProcess("bootloadHID.exe", $"-r"); - - private void FlashCaterina(string mcu, string file) => RunProcess("avrdude.exe", $"-p {mcu} -c avr109 -U flash:w:\"{file}\":i -P {ComPort}"); - - private void ClearEepromCaterina(string mcu) => RunProcess("avrdude.exe", $"-p {mcu} -c avr109 -U eeprom:w:reset.eep:i -P {ComPort}"); - - private void SetHandednessCaterina(string mcu, bool rightHand) => RunProcess("avrdude.exe", $"-p {mcu} -c avr109 -U eeprom:w:reset_{(rightHand ? "right" : "left")}.eep:i -P {ComPort}"); - - private void FlashHalfkay(string mcu, string file) => RunProcess("teensy_loader_cli.exe", $"-mmcu={mcu} \"{file}\" -v"); - - private void ResetHalfkay(string mcu) => RunProcess("teensy_loader_cli.exe", $"-mmcu={mcu} -bv"); - - private void FlashKiibohd(string file) - { - if (Path.GetExtension(file)?.ToLower() == ".bin") - { - RunProcess("dfu-util.exe", $"-D \"{file}\""); - } - else - { - _printer.Print("Only firmware files in .bin format can be flashed with dfu-util!", MessageType.Error); - } - } - - private void FlashLufaMs(string file) - { - if (MountPoint != null) - { - if (Path.GetExtension(file)?.ToLower() == ".bin") - { - var destFile = $"{MountPoint}\\FLASH.BIN"; - - try - { - _printer.Print($"Deleting {destFile}...", MessageType.Command); - File.Delete(destFile); - - _printer.Print($"Copying {file} to {destFile}...", MessageType.Command); - File.Copy(file, destFile); - - _printer.Print("Done, please eject drive now.", MessageType.Info); - } - catch (IOException e) - { - _printer.Print($"IO ERROR: {e.Message}", MessageType.Error); - } - } - else - { - _printer.Print("Only firmware files in .bin format can be flashed with this bootloader!", MessageType.Error); - } - } - else - { - _printer.Print("Could not find drive letter for device!", MessageType.Error); - } - } - - private void FlashStm32Dfu(string file) - { - if (Path.GetExtension(file)?.ToLower() == ".bin") - { - RunProcess("dfu-util.exe", $"-a 0 -d 0483:DF11 -s 0x08000000:leave -D \"{file}\""); - } - else - { - _printer.Print("Only firmware files in .bin format can be flashed with dfu-util!", MessageType.Error); - } - } - - private void FlashStm32Duino(string file) - { - if (Path.GetExtension(file)?.ToLower() == ".bin") - { - RunProcess("dfu-util.exe", $"-a 2 -d 1EAF:0003 -R -D \"{file}\""); - } - else - { - _printer.Print("Only firmware files in .bin format can be flashed with dfu-util!", MessageType.Error); - } - } - - private void FlashUsbAsp(string mcu, string file) - { - RunProcess("avrdude.exe", $"-p {mcu} -c usbasp -U flash:w:\"{file}\":i"); - _printer.Print("Flash complete", MessageType.Bootloader); - } - - private void ClearEepromUsbAsp(string mcu) => RunProcess("avrdude.exe", $"-p {mcu} -c usbasp -U eeprom:w:reset.eep:i"); - - private void SetHandednessUsbAsp(string mcu, bool rightHand) => RunProcess("avrdude.exe", $"-p {mcu} -c usbasp -U eeprom:w:reset_{(rightHand ? "right" : "left")}.eep:i"); - - private void FlashUsbTiny(string mcu, string file) - { - RunProcess("avrdude.exe", $"-p {mcu} -c usbtiny -U flash:w:\"{file}\":i"); - _printer.Print("Flash complete", MessageType.Bootloader); - } - } -} diff --git a/windows/QMK Toolbox/Helpers/EmbeddedResourceHelper.cs b/windows/QMK Toolbox/Helpers/EmbeddedResourceHelper.cs index 16c107b2e5..0cbf432bee 100644 --- a/windows/QMK Toolbox/Helpers/EmbeddedResourceHelper.cs +++ b/windows/QMK Toolbox/Helpers/EmbeddedResourceHelper.cs @@ -9,10 +9,17 @@ public static class EmbeddedResourceHelper { public static void ExtractResource(string file) { - using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"QMK_Toolbox.Resources.{file}")) - using (var filestream = new FileStream(Path.Combine(Application.LocalUserAppDataPath, file), FileMode.Create)) + var destPath = Path.Combine(Application.LocalUserAppDataPath, file); + + if (!File.Exists(destPath)) { - stream?.CopyTo(filestream); + using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"QMK_Toolbox.Resources.{file}")) + { + using (var filestream = new FileStream(destPath, FileMode.Create)) + { + stream?.CopyTo(filestream); + } + } } } diff --git a/windows/QMK Toolbox/MainWindow.cs b/windows/QMK Toolbox/MainWindow.cs index bb681939f0..dee260d244 100644 --- a/windows/QMK Toolbox/MainWindow.cs +++ b/windows/QMK Toolbox/MainWindow.cs @@ -2,13 +2,14 @@ using QMK_Toolbox.HidConsole; using QMK_Toolbox.KeyTester; using QMK_Toolbox.Properties; +using QMK_Toolbox.Usb; +using QMK_Toolbox.Usb.Bootloader; using System; using System.ComponentModel; using System.IO; using System.IO.Compression; using System.Linq; using System.Security.Permissions; -using System.Threading; using System.Windows.Forms; namespace QMK_Toolbox @@ -16,7 +17,7 @@ namespace QMK_Toolbox using Newtonsoft.Json; using Syroot.Windows.IO; using System.Collections; - using System.Management; + using System.Collections.Generic; using System.Net; public partial class MainWindow : Form @@ -25,8 +26,6 @@ public partial class MainWindow : Form private readonly Printing _printer; - private readonly Flashing _flasher; - private readonly string _filePassedIn = string.Empty; #region Window Events @@ -51,11 +50,6 @@ public MainWindow(string path) : this() } _printer = new Printing(logTextBox); - _flasher = new Flashing(_printer); - _usb = new Usb(_flasher, _printer); - _flasher.Usb = _usb; - - _usb.StartListeningForDeviceEvents(DeviceEvent); } private void MainWindow_Load(object sender, EventArgs e) @@ -84,14 +78,12 @@ private void MainWindow_Load(object sender, EventArgs e) _printer.PrintResponse(" - USBasp (AVR ISP)\n", MessageType.Info); _printer.PrintResponse(" - USBTiny (AVR Pocket)\n", MessageType.Info); - ManagementObjectCollection collection; - using (var searcher = new ManagementObjectSearcher(@"SELECT * FROM Win32_PnPEntity WHERE DeviceID LIKE 'USB%'")) - { - collection = searcher.Get(); - } - - _usb.DetectBootloaderFromCollection(collection); - EnableUI(); + //usbListener.usbDeviceConnected += UsbDeviceConnected; + //usbListener.usbDeviceDisconnected += UsbDeviceDisconnected; + usbListener.bootloaderDeviceConnected += BootloaderDeviceConnected; + usbListener.bootloaderDeviceDisconnected += BootloaderDeviceDisconnected; + usbListener.outputReceived += BootloaderCommandOutputReceived; + usbListener.Start(); consoleListener.consoleDeviceConnected += ConsoleDeviceConnected; consoleListener.consoleDeviceDisconnected += ConsoleDeviceDisconnected; @@ -102,6 +94,8 @@ private void MainWindow_Load(object sender, EventArgs e) { SetFilePath(_filePassedIn); } + + EnableUI(); } private void MainWindow_Shown(object sender, EventArgs e) @@ -175,7 +169,7 @@ private void MainWindow_FormClosing(object sender, FormClosingEventArgs e) Settings.Default.targetSetting = (string)mcuBox.SelectedValue; Settings.Default.Save(); - _usb.StopListeningForDeviceEvents(); + usbListener.Dispose(); consoleListener.Dispose(); } @@ -254,35 +248,36 @@ private void UpdateConsoleList() #endregion HID Console #region USB Devices & Bootloaders - private readonly Usb _usb; + private readonly UsbListener usbListener = new UsbListener(); - private void DeviceEvent(object sender, EventArrivedEventArgs e) + private void BootloaderDeviceConnected(BootloaderDevice device) { - (sender as ManagementEventWatcher)?.Stop(); + _printer.Print($"{device.Name} device connected ({device.Driver}): {device}", MessageType.Bootloader); - if (!(e.NewEvent["TargetInstance"] is ManagementBaseObject instance)) - { - return; - } - - var deviceDisconnected = e.NewEvent.ClassPath.ClassName.Equals("__InstanceDeletionEvent"); + Invoke(new Action(EnableUI)); + } - if (deviceDisconnected) - { - _usb.DetectBootloader(instance, false); - } - else if (_usb.DetectBootloader(instance) && windowState.AutoFlashEnabled) - { - FlashButton_Click(sender, e); - } + private void BootloaderDeviceDisconnected(BootloaderDevice device) + { + _printer.Print($"{device.Name} device disconnected ({device.Driver}): {device}", MessageType.Bootloader); - (sender as ManagementEventWatcher)?.Start(); + Invoke(new Action(EnableUI)); + } - if (!windowState.AutoFlashEnabled) - { - Invoke(new Action(EnableUI)); - } + private void BootloaderCommandOutputReceived(BootloaderDevice device, string data, MessageType type) + { + _printer.PrintResponse($"{data}\n", type); } + + //private void UsbDeviceConnected(UsbDevice device) + //{ + // _printer.Print($"USB device connected ({device.Driver}): {device}", MessageType.Info); + //} + + //private void UsbDeviceDisconnected(UsbDevice device) + //{ + // _printer.Print($"USB device disconnected ({device.Driver}): {device}", MessageType.Info); + //} #endregion #region UI Interaction @@ -303,167 +298,114 @@ private void AutoFlashEnabledChanged(object sender, PropertyChangedEventArgs e) } } - private void FlashButton_Click(object sender, EventArgs e) + private async void FlashButton_Click(object sender, EventArgs e) { - if (!InvokeRequired) + string selectedMcu = (string)mcuBox.SelectedValue; + string filePath = filepathBox.Text; + + if (filePath.Length == 0) { - var mcu = (string)mcuBox.SelectedValue; - var filePath = filepathBox.Text; + _printer.Print("Please select a file", MessageType.Error); + return; + } - // Keep the form responsive during firmware flashing - new Thread(() => - { - if (_usb.AreDevicesAvailable()) - { - if (mcu.Length > 0) - { - if (filePath.Length > 0) - { - if (!windowState.AutoFlashEnabled) - { - Invoke(new Action(DisableUI)); - } - - _printer.Print("Attempting to flash, please don't remove device", MessageType.Bootloader); - _flasher.Flash(mcu, filePath); - - if (!windowState.AutoFlashEnabled) - { - Invoke(new Action(EnableUI)); - } - } - else - { - _printer.Print("Please select a file", MessageType.Error); - } - } - else - { - _printer.Print("Please select a microcontroller", MessageType.Error); - } - } - else - { - _printer.Print("There are no devices available", MessageType.Error); - } - }).Start(); + if (!windowState.AutoFlashEnabled) + { + Invoke(new Action(DisableUI)); } - else + + foreach (BootloaderDevice b in FindBootloaders()) { - Invoke(new Action(FlashButton_Click), sender, e); + _printer.Print("Attempting to flash, please don't remove device", MessageType.Bootloader); + await b.Flash(selectedMcu, filePath); + _printer.Print("Flash complete", MessageType.Bootloader); + } + + if (!windowState.AutoFlashEnabled) + { + Invoke(new Action(EnableUI)); } } - private void ResetButton_Click(object sender, EventArgs e) + private async void ResetButton_Click(object sender, EventArgs e) { - if (!InvokeRequired) - { - if (_usb.AreDevicesAvailable()) - { - if (mcuBox.SelectedIndex >= 0) - { - if (!windowState.AutoFlashEnabled) - { - Invoke(new Action(DisableUI)); - } + string selectedMcu = (string)mcuBox.SelectedValue; - _flasher.Reset((string)mcuBox.SelectedValue); + if (!windowState.AutoFlashEnabled) + { + Invoke(new Action(DisableUI)); + } - if (!windowState.AutoFlashEnabled) - { - Invoke(new Action(EnableUI)); - } - } - else - { - _printer.Print("Please select a microcontroller", MessageType.Error); - } - } - else + foreach (BootloaderDevice b in FindBootloaders()) + { + if (b.IsResettable) { - _printer.Print("There are no devices available", MessageType.Error); + await b.Reset(selectedMcu); } } - else + + if (!windowState.AutoFlashEnabled) { - Invoke(new Action(ResetButton_Click), sender, e); + Invoke(new Action(EnableUI)); } } - private void ClearEepromButton_Click(object sender, EventArgs e) + private async void ClearEepromButton_Click(object sender, EventArgs e) { - if (!InvokeRequired) - { - if (_usb.AreDevicesAvailable()) - { - if (mcuBox.SelectedIndex >= 0) - { - if (!windowState.AutoFlashEnabled) - { - Invoke(new Action(DisableUI)); - } + string selectedMcu = (string)mcuBox.SelectedValue; - _flasher.ClearEeprom((string)mcuBox.SelectedValue); + if (!windowState.AutoFlashEnabled) + { + Invoke(new Action(DisableUI)); + } - if (!windowState.AutoFlashEnabled) - { - Invoke(new Action(EnableUI)); - } - } - else - { - _printer.Print("Please select a microcontroller", MessageType.Error); - } - } - else + foreach (BootloaderDevice b in FindBootloaders()) + { + if (b.IsEepromFlashable) { - _printer.Print("There are no devices available", MessageType.Error); + _printer.Print("Attempting to clear EEPROM, please don't remove device", MessageType.Bootloader); + await b.FlashEeprom(selectedMcu, "reset.eep"); + _printer.Print("EEPROM clear complete", MessageType.Bootloader); } } - else + + if (!windowState.AutoFlashEnabled) { - Invoke(new Action(ClearEepromButton_Click), sender, e); + Invoke(new Action(EnableUI)); } } - private void SetHandednessButton_Click(object sender, EventArgs e) + private async void SetHandednessButton_Click(object sender, EventArgs e) { + string selectedMcu = (string)mcuBox.SelectedValue; + string file = sender == eepromLeftToolStripMenuItem ? "left.eep" : "right.eep"; - if (!InvokeRequired) + if (!windowState.AutoFlashEnabled) { - if (_usb.AreDevicesAvailable()) - { - if (mcuBox.SelectedIndex >= 0) - { - if (!windowState.AutoFlashEnabled) - { - Invoke(new Action(DisableUI)); - } - - ToolStripMenuItem item = sender as ToolStripMenuItem; - _flasher.SetHandedness((string)mcuBox.SelectedValue, (string)item.Tag == "right"); + Invoke(new Action(DisableUI)); + } - if (!windowState.AutoFlashEnabled) - { - Invoke(new Action(EnableUI)); - } - } - else - { - _printer.Print("Please select a microcontroller", MessageType.Error); - } - } - else + foreach (BootloaderDevice b in FindBootloaders()) + { + if (b.IsEepromFlashable) { - _printer.Print("There are no devices available", MessageType.Error); + _printer.Print("Attempting to set handedness, please don't remove device", MessageType.Bootloader); + await b.FlashEeprom(selectedMcu, file); + _printer.Print("EEPROM write complete", MessageType.Bootloader); } } - else + + if (!windowState.AutoFlashEnabled) { - Invoke(new Action(SetHandednessButton_Click), sender, e); + Invoke(new Action(EnableUI)); } } + private List FindBootloaders() + { + return usbListener.Devices.Where(d => d is BootloaderDevice).Select(b => b as BootloaderDevice).ToList(); + } + private void OpenFileButton_Click(object sender, EventArgs e) { if (openFileDialog.ShowDialog() == DialogResult.OK) @@ -591,9 +533,10 @@ private void DisableUI() private void EnableUI() { - windowState.CanFlash = _flasher.CanFlash(); - windowState.CanReset = _flasher.CanReset(); - windowState.CanClearEeprom = _flasher.CanClearEeprom(); + List bootloaders = FindBootloaders(); + windowState.CanFlash = bootloaders.Any(); + windowState.CanReset = bootloaders.Any(b => b.IsResettable); + windowState.CanClearEeprom = bootloaders.Any(b => b.IsEepromFlashable); } private void ExitMenuItem_Click(object sender, EventArgs e) diff --git a/windows/QMK Toolbox/QMK Toolbox.csproj b/windows/QMK Toolbox/QMK Toolbox.csproj index 2fb4899b41..2010b94e1e 100644 --- a/windows/QMK Toolbox/QMK Toolbox.csproj +++ b/windows/QMK Toolbox/QMK Toolbox.csproj @@ -73,7 +73,6 @@ Component - @@ -103,10 +102,27 @@ - Component + + + + + + + + + + + + + + + + + + AboutBox.cs diff --git a/windows/QMK Toolbox/USB.cs b/windows/QMK Toolbox/USB.cs deleted file mode 100644 index 471e88af58..0000000000 --- a/windows/QMK Toolbox/USB.cs +++ /dev/null @@ -1,324 +0,0 @@ -using System; -using System.Linq; -using System.Management; -using System.Text.RegularExpressions; - -namespace QMK_Toolbox -{ - public class Usb - { - private readonly int[] _devicesAvailable = new int[(int)Chipset.NumberOfChipsets]; - private readonly Flashing _flasher; - private readonly Printing _printer; - private readonly Regex DeviceIdRegex = new Regex(@"USB\\VID_([0-9A-F]+).*PID_([0-9A-F]+).*REV_([0-9A-F]+).*"); - - private ManagementEventWatcher deviceConnectedWatcher; - private ManagementEventWatcher deviceDisconnectedWatcher; - - public Usb(Flashing flasher, Printing printer) - { - _flasher = flasher; - _printer = printer; - } - - public void StartListeningForDeviceEvents(EventArrivedEventHandler handler) - { - if (deviceConnectedWatcher == null) - { - deviceConnectedWatcher = StartManagementEventWatcher("__InstanceCreationEvent", handler); - } - - if (deviceDisconnectedWatcher == null) - { - deviceDisconnectedWatcher = StartManagementEventWatcher("__InstanceDeletionEvent", handler); - } - } - - public void StopListeningForDeviceEvents() - { - if (deviceConnectedWatcher != null) - { - deviceConnectedWatcher.Stop(); - } - - if (deviceDisconnectedWatcher != null) - { - deviceDisconnectedWatcher.Stop(); - } - } - - private ManagementEventWatcher StartManagementEventWatcher(string eventType, EventArrivedEventHandler handler) - { - var watcher = new ManagementEventWatcher($"SELECT * FROM {eventType} WITHIN 2 WHERE TargetInstance ISA 'Win32_PnPEntity' AND TargetInstance.DeviceID LIKE 'USB%'"); - watcher.EventArrived += handler; - watcher.Start(); - return watcher; - } - - public bool DetectBootloaderFromCollection(ManagementObjectCollection collection, bool connected = true) - { - var found = false; - foreach (var instance in collection) - { - found = DetectBootloader(instance, connected); - } - return found; - } - - private static readonly ushort[] caterinaVids = - { - 0x1B4F, // Spark Fun Electronics - 0x1FFB, // Pololu Electronics - 0x2341, // Arduino SA - 0x239A, // Adafruit Industries LLC - 0x2A03 // dog hunter AG - }; - - private static readonly ushort[] caterinaPids = - { - // Adafruit Industries LLC - 0x000C, // Feather 32U4 - 0x000D, // ItsyBitsy 32U4 3V3/8MHz - 0x000E, // ItsyBitsy 32U4 5V/16MHz - // Arduino SA / dog hunter AG - 0x0036, // Leonardo - 0x0037, // Micro - // Pololu Electronics - 0x0101, // A-Star 32U4 - // Spark Fun Electronics - 0x9203, // Pro Micro 3V3/8MHz - 0x9205, // Pro Micro 5V/16MHz - 0x9207 // LilyPad 3V3/8MHz (and some Pro Micro clones) - }; - - private static readonly ushort[] atmelDfuPids = - { - 0x2FEF, // ATmega16U2 - 0x2FF0, // ATmega32U2 - 0x2FF3, // ATmega16U4 - 0x2FF4, // ATmega32U4 - 0x2FF9, // AT90USB64 - 0x2FFA, // AT90USB162 - 0x2FFB // AT90USB128 - }; - - public bool DetectBootloader(ManagementBaseObject instance, bool connected = true) - { - var deviceId = GetHardwareId(instance); - - var vpr = DeviceIdRegex.Match(deviceId); - if (vpr.Success) - { - var vendorId = Convert.ToUInt16(vpr.Groups[1].ToString(), 16); - var productId = Convert.ToUInt16(vpr.Groups[2].ToString(), 16); - var revisionBcd = Convert.ToUInt16(vpr.Groups[3].ToString(), 16); - - string deviceName; - string comPort = null; - string mountPoint = null; - string driverName = GetDriverName(instance); - Chipset deviceType; - - if (IsSerialDevice(instance)) - { - if (vendorId == 0x03EB && productId == 0x6124) // Atmel SAM-BA - { - deviceName = "Atmel SAM-BA"; - deviceType = Chipset.AtmelSamBa; - } - else if (caterinaVids.Contains(vendorId) && caterinaPids.Contains(productId)) // Caterina - { - deviceName = "Caterina"; - deviceType = Chipset.Caterina; - } - else if (vendorId == 0x16C0 && productId == 0x0483) // ArduinoISP/AVRISP - { - deviceName = "AVRISP"; - deviceType = Chipset.AvrIsp; - } - else - { - return false; - } - - comPort = GetComPort(instance); - _flasher.ComPort = comPort; - } - else if (vendorId == 0x03EB) - { - if (atmelDfuPids.Contains(productId)) - { - if (revisionBcd == 0x0936) // QMK-DFU - { - deviceName = "QMK DFU"; - deviceType = Chipset.QmkDfu; - } - else // Atmel DFU - { - deviceName = "Atmel DFU"; - deviceType = Chipset.AtmelDfu; - } - } - else if (productId == 0x2045) // LUFA MS - { - deviceName = "LUFA Mass Storage"; - deviceType = Chipset.LufaMs; - mountPoint = GetMountPoint(instance); - _flasher.MountPoint = mountPoint; - } - else - { - return false; - } - } - else if (vendorId == 0x16C0 && productId == 0x0478) // PJRC Teensy - { - deviceName = "Halfkay"; - deviceType = Chipset.Halfkay; - } - else if (vendorId == 0x0483 && productId == 0xDF11) // STM32 DFU - { - deviceName = "STM32 DFU"; - deviceType = Chipset.Stm32Dfu; - } - else if (vendorId == 0x314B && productId == 0x0106) // APM32 DFU - { - deviceName = "APM32 DFU"; - deviceType = Chipset.Apm32Dfu; - } - else if (vendorId == 0x1C11 && productId == 0xB007) // Kiibohd - { - deviceName = "Kiibohd"; - deviceType = Chipset.Kiibohd; - } - else if (vendorId == 0x16C0 && productId == 0x05DF) // Objective Development BootloadHID - { - deviceName = "BootloadHID"; - deviceType = Chipset.BootloadHid; - } - else if (vendorId == 0x16C0 && productId == 0x05DC) // USBasp and USBaspLoader - { - deviceName = "USBasp"; - deviceType = Chipset.UsbAsp; - } - else if (vendorId == 0x1781 && productId == 0x0C9F) // AVR Pocket ISP - { - deviceName = "USB Tiny"; - deviceType = Chipset.UsbTiny; - } - else if (vendorId == 0x1EAF && productId == 0x0003) // STM32Duino - { - deviceName = "STM32Duino"; - deviceType = Chipset.Stm32Duino; - } - else - { - return false; - } - - var connectedString = connected ? "connected" : "disconnected"; - var comPortString = comPort != null ? $" [{comPort}]" : ""; - var mountPointString = mountPoint != null ? $" [{mountPoint}]" : ""; - var driverString = driverName ?? "NO DRIVER"; - - _printer.Print($"{deviceName} device {connectedString} ({driverString}): {instance.GetPropertyValue("Manufacturer")} {instance.GetPropertyValue("Name")} ({vendorId:X4}:{productId:X4}:{revisionBcd:X4}){comPortString}{mountPointString}", MessageType.Bootloader); - - _devicesAvailable[(int)deviceType] += (connected ? 1 : -1); - - return true; - } - - return false; - } - - public string GetHardwareId(ManagementBaseObject instance) - { - var hardwareIds = (string[])instance.GetPropertyValue("HardwareID"); - if (hardwareIds != null && hardwareIds.Length > 0) - { - return hardwareIds[0]; - } - - return null; - } - - public string GetDriverName(ManagementBaseObject instance) - { - var service = (string)instance.GetPropertyValue("Service"); - if (service != null && service.Length > 0) - { - return service; - } - - return null; - } - - public bool IsSerialDevice(ManagementBaseObject instance) - { - var compatibleIds = (string[])instance.GetPropertyValue("CompatibleID"); - return (compatibleIds != null && compatibleIds.Contains("USB\\Class_02&SubClass_02")); // CDC-ACM - } - - public string GetComPort(ManagementBaseObject instance) - { - using (var searcher = new ManagementObjectSearcher("SELECT PNPDeviceID, DeviceID FROM Win32_SerialPort")) - { - foreach (var device in searcher.Get()) - { - if (device.GetPropertyValue("PNPDeviceID").ToString().Equals(instance.GetPropertyValue("PNPDeviceID").ToString())) - { - return device.GetPropertyValue("DeviceID").ToString(); - } - } - } - - return null; - } - - public string GetMountPoint(ManagementBaseObject instance) - { - foreach (ManagementObject usbHub in new ManagementObjectSearcher("SELECT * FROM Win32_USBHub").Get()) - { - if (usbHub.GetPropertyValue("PNPDeviceID").ToString().Equals(instance.GetPropertyValue("PNPDeviceID").ToString())) - { - foreach (ManagementObject usbController in usbHub.GetRelated("Win32_USBController")) - { - foreach (ManagementObject assoc in new ManagementObjectSearcher("ASSOCIATORS OF {Win32_USBController.DeviceID='" + usbController["PNPDeviceID"].ToString() + "'}").Get()) - { - if (assoc.GetPropertyValue("CreationClassName").Equals("Win32_PnPEntity") && assoc.GetPropertyValue("DeviceID").ToString().Contains("USBSTOR")) - { - foreach (ManagementObject diskDrive in new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive").Get()) - { - if (diskDrive.GetPropertyValue("PNPDeviceID").ToString().Equals(assoc.GetPropertyValue("PNPDeviceID").ToString())) - { - foreach (ManagementObject partition in diskDrive.GetRelated("Win32_DiskPartition")) - { - foreach (ManagementObject logicalDisk in partition.GetRelated("Win32_LogicalDisk")) - { - return logicalDisk.GetPropertyValue("Name").ToString(); - } - } - } - } - } - } - } - } - } - - return null; - } - - public bool CanFlash(Chipset chipset) => _devicesAvailable[(int)chipset] > 0; - - public bool AreDevicesAvailable() - { - var available = false; - for (var i = 0; i < (int)Chipset.NumberOfChipsets; i++) - { - available |= _devicesAvailable[i] > 0; - } - return available; - } - } -} diff --git a/windows/QMK Toolbox/Usb/Bootloader/Apm32DfuDevice.cs b/windows/QMK Toolbox/Usb/Bootloader/Apm32DfuDevice.cs new file mode 100644 index 0000000000..8c41903ed5 --- /dev/null +++ b/windows/QMK Toolbox/Usb/Bootloader/Apm32DfuDevice.cs @@ -0,0 +1,30 @@ +using System.IO; +using System.Threading.Tasks; + +namespace QMK_Toolbox.Usb.Bootloader +{ + class Apm32DfuDevice : BootloaderDevice + { + public Apm32DfuDevice(UsbDevice d) : base(d) + { + Type = BootloaderType.Apm32Dfu; + Name = "APM32 DFU"; + PreferredDriver = "WinUSB"; + IsResettable = true; + } + + public async override Task Flash(string mcu, string file) + { + if (Path.GetExtension(file)?.ToLower() == ".bin") + { + await RunProcessAsync("dfu-util.exe", $"-a 0 -d 314B:0106 -s 0x08000000:leave -D \"{file}\""); + } + else + { + PrintMessage("Only firmware files in .bin format can be flashed with dfu-util!", MessageType.Error); + } + } + + public async override Task Reset(string mcu) => await RunProcessAsync("dfu-util.exe", "-a 0 -d 314B:0106 -s 0x08000000:leave"); + } +} diff --git a/windows/QMK Toolbox/Usb/Bootloader/AtmelDfuDevice.cs b/windows/QMK Toolbox/Usb/Bootloader/AtmelDfuDevice.cs new file mode 100644 index 0000000000..da5ce1781b --- /dev/null +++ b/windows/QMK Toolbox/Usb/Bootloader/AtmelDfuDevice.cs @@ -0,0 +1,50 @@ +using System.Threading.Tasks; + +namespace QMK_Toolbox.Usb.Bootloader +{ + class AtmelDfuDevice : BootloaderDevice + { + public AtmelDfuDevice(UsbDevice d) : base(d) + { + if (d.RevisionBcd == 0x0936) + { + Type = BootloaderType.QmkDfu; + Name = "QMK DFU"; + } + else + { + Type = BootloaderType.AtmelDfu; + Name = "Atmel DFU"; + } + PreferredDriver = "libusb0"; + IsEepromFlashable = true; + IsResettable = true; + } + + public async override Task Flash(string mcu, string file) + { + await RunProcessAsync("dfu-programmer.exe", $"{mcu} erase --force"); + await Task.Delay(5); + await RunProcessAsync("dfu-programmer.exe", $"{mcu} flash --force \"{file}\""); + await Task.Delay(5); + await RunProcessAsync("dfu-programmer.exe", $"{mcu} reset"); + } + + public async override Task FlashEeprom(string mcu, string file) + { + if (Type == BootloaderType.AtmelDfu) + { + await RunProcessAsync("dfu-programmer.exe", $"{mcu} erase --force"); + } + + await RunProcessAsync("dfu-programmer.exe", $"{mcu} flash --force --suppress-validation --eeprom \"{file}\""); + + if (Type == BootloaderType.AtmelDfu) + { + PrintMessage("Please reflash device with firmware now", MessageType.Bootloader); + } + } + + public async override Task Reset(string mcu) => await RunProcessAsync("dfu-programmer.exe", $"{mcu} reset"); + } +} diff --git a/windows/QMK Toolbox/Usb/Bootloader/AtmelSamBaDevice.cs b/windows/QMK Toolbox/Usb/Bootloader/AtmelSamBaDevice.cs new file mode 100644 index 0000000000..fae1306ff2 --- /dev/null +++ b/windows/QMK Toolbox/Usb/Bootloader/AtmelSamBaDevice.cs @@ -0,0 +1,43 @@ +using System.Threading.Tasks; + +namespace QMK_Toolbox.Usb.Bootloader +{ + class AtmelSamBaDevice : BootloaderDevice + { + private string ComPort { get; } + + public AtmelSamBaDevice(UsbDevice d) : base(d) + { + Type = BootloaderType.AtmelSamBa; + Name = "Atmel SAM-BA"; + PreferredDriver = "usbser"; + IsResettable = true; + + ComPort = UsbDevice.FindComPort(); + } + + public async override Task Flash(string mcu, string file) + { + if (ComPort == null) + { + PrintMessage("COM port not found!", MessageType.Error); + return; + } + + await RunProcessAsync("mdloader.exe", $"-p {ComPort} -D \"{file}\" --restart"); + } + + public async override Task Reset(string mcu) + { + if (ComPort == null) + { + PrintMessage("COM port not found!", MessageType.Error); + return; + } + + await RunProcessAsync("mdloader.exe", $"-p {ComPort} --restart"); + } + + public override string ToString() => $"{base.ToString()} [{ComPort}]"; + } +} diff --git a/windows/QMK Toolbox/Usb/Bootloader/AvrIspDevice.cs b/windows/QMK Toolbox/Usb/Bootloader/AvrIspDevice.cs new file mode 100644 index 0000000000..c5821b4465 --- /dev/null +++ b/windows/QMK Toolbox/Usb/Bootloader/AvrIspDevice.cs @@ -0,0 +1,29 @@ +using System.Threading.Tasks; + +namespace QMK_Toolbox.Usb.Bootloader +{ + class AvrIspDevice : BootloaderDevice + { + private string ComPort { get; } + + public AvrIspDevice(UsbDevice d) : base(d) + { + Type = BootloaderType.AvrIsp; + Name = "AVR ISP"; + PreferredDriver = "usbser"; + + ComPort = UsbDevice.FindComPort(); + } + + public async override Task Flash(string mcu, string file) + { + if (ComPort == null) + { + PrintMessage("COM port not found!", MessageType.Error); + return; + } + + await RunProcessAsync("avrdude.exe", $"-p {mcu} -c avrisp -U flash:w:\"{file}\":i -P {ComPort}"); + } + } +} diff --git a/windows/QMK Toolbox/Usb/Bootloader/BootloadHidDevice.cs b/windows/QMK Toolbox/Usb/Bootloader/BootloadHidDevice.cs new file mode 100644 index 0000000000..19aa4e7e63 --- /dev/null +++ b/windows/QMK Toolbox/Usb/Bootloader/BootloadHidDevice.cs @@ -0,0 +1,19 @@ +using System.Threading.Tasks; + +namespace QMK_Toolbox.Usb.Bootloader +{ + class BootloadHidDevice : BootloaderDevice + { + public BootloadHidDevice(UsbDevice d) : base(d) + { + Type = BootloaderType.AtmelDfu; + Name = "BootloadHID"; + PreferredDriver = "HidUsb"; + IsResettable = true; + } + + public async override Task Flash(string mcu, string file) => await RunProcessAsync("bootloadHID.exe", $"-r \"{file}\""); + + public async override Task Reset(string mcu) => await RunProcessAsync("bootloadHID.exe", $"-r"); + } +} diff --git a/windows/QMK Toolbox/Usb/Bootloader/BootloaderDevice.cs b/windows/QMK Toolbox/Usb/Bootloader/BootloaderDevice.cs new file mode 100644 index 0000000000..a3fae05ca0 --- /dev/null +++ b/windows/QMK Toolbox/Usb/Bootloader/BootloaderDevice.cs @@ -0,0 +1,134 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Management; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace QMK_Toolbox.Usb.Bootloader +{ + public abstract class BootloaderDevice : IUsbDevice + { + public delegate void FlashOutputReceivedDelegate(BootloaderDevice device, string data, MessageType type); + + public FlashOutputReceivedDelegate outputReceived; + + private UsbDevice UsbDevice { get; } + + public ManagementBaseObject WmiDevice { get => UsbDevice.WmiDevice; } + + public ushort VendorId { get => UsbDevice.VendorId; } + + public ushort ProductId { get => UsbDevice.ProductId; } + + public ushort RevisionBcd { get => UsbDevice.RevisionBcd; } + + public string ManufacturerString { get => UsbDevice.ManufacturerString; } + + public string ProductString { get => UsbDevice.ProductString; } + + public string Driver { get => UsbDevice.Driver; } + + public string PreferredDriver { get; protected set; } + + public bool IsEepromFlashable { get; protected set; } + + public bool IsResettable { get; protected set; } + + public BootloaderType Type { get; protected set; } + + public string Name { get; protected set; } + + public BootloaderDevice(UsbDevice d) + { + UsbDevice = d; + } + + public override string ToString() => UsbDevice.ToString(); + + public abstract Task Flash(string mcu, string file); + + public virtual Task FlashEeprom(string mcu, string file) + { + throw new NotImplementedException(); + } + + public virtual Task Reset(string mcu) + { + throw new NotImplementedException(); + } + + protected async Task RunProcessAsync(string command, string args) + { + PrintMessage($"{command} {args}", MessageType.Command); + + using (var process = new Process + { + StartInfo = + { + FileName = Path.Combine(Application.LocalUserAppDataPath, command), + Arguments = args, + WorkingDirectory = Application.LocalUserAppDataPath, + UseShellExecute = false, + CreateNoWindow = true, + RedirectStandardOutput = true, + RedirectStandardError = true + }, + EnableRaisingEvents = true + }) + { + return await RunProcessAsync(process).ConfigureAwait(false); + } + } + + private Task RunProcessAsync(Process process) + { + var tcs = new TaskCompletionSource(); + + process.Exited += (sender, e) => + { + process.WaitForExit(); + tcs.SetResult(process.ExitCode); + }; + + bool started = process.Start(); + if (!started) + { + PrintMessage($"Could not start process: {process}", MessageType.Error); + } + + Thread processOutputThread = new Thread(ProcessOutput); + processOutputThread.Start(process.StandardOutput); + Thread processErrorOutputThread = new Thread(ProcessErrorOutput); + processErrorOutputThread.Start(process.StandardError); + + return tcs.Task; + } + + private void ProcessOutput(object o) + { + StreamReader reader = (StreamReader)o; + + while (!reader.EndOfStream) + { + PrintMessage($"{reader.ReadLine()}", MessageType.Info); + } + } + + private void ProcessErrorOutput(object o) + { + StreamReader reader = (StreamReader)o; + + while (!reader.EndOfStream) + { + PrintMessage($"{reader.ReadLine()}", MessageType.Info); + } + } + + protected void PrintMessage(string message, MessageType type) + { + outputReceived?.Invoke(this, message, type); + } + } +} diff --git a/windows/QMK Toolbox/Usb/Bootloader/BootloaderType.cs b/windows/QMK Toolbox/Usb/Bootloader/BootloaderType.cs new file mode 100644 index 0000000000..bda27b413a --- /dev/null +++ b/windows/QMK Toolbox/Usb/Bootloader/BootloaderType.cs @@ -0,0 +1,21 @@ +namespace QMK_Toolbox.Usb.Bootloader +{ + public enum BootloaderType + { + Apm32Dfu, + AtmelDfu, + AtmelSamBa, + AvrIsp, + BootloadHid, + Caterina, + HalfKay, + KiibohdDfu, + LufaMs, + QmkDfu, + Stm32Dfu, + Stm32Duino, + UsbAsp, + UsbTinyIsp, + None + } +} diff --git a/windows/QMK Toolbox/Usb/Bootloader/CaterinaDevice.cs b/windows/QMK Toolbox/Usb/Bootloader/CaterinaDevice.cs new file mode 100644 index 0000000000..182fc8ef5d --- /dev/null +++ b/windows/QMK Toolbox/Usb/Bootloader/CaterinaDevice.cs @@ -0,0 +1,43 @@ +using System.Threading.Tasks; + +namespace QMK_Toolbox.Usb.Bootloader +{ + class CaterinaDevice : BootloaderDevice + { + public string ComPort { get; } + + public CaterinaDevice(UsbDevice d) : base(d) + { + Type = BootloaderType.Caterina; + Name = "Caterina"; + PreferredDriver = "usbser"; + IsEepromFlashable = true; + + ComPort = UsbDevice.FindComPort(); + } + + public async override Task Flash(string mcu, string file) + { + if (ComPort == null) + { + PrintMessage("COM port not found!", MessageType.Error); + return; + } + + await RunProcessAsync("avrdude.exe", $"-p {mcu} -c avr109 -U flash:w:\"{file}\":i -P {ComPort}"); + } + + public async override Task FlashEeprom(string mcu, string file) + { + if (ComPort == null) + { + PrintMessage("COM port not found!", MessageType.Error); + return; + } + + await RunProcessAsync("avrdude.exe", $"-p {mcu} -c avr109 -U eeprom:w:\"{file}\":i -P {ComPort}"); + } + + public override string ToString() => $"{base.ToString()} [{ComPort}]"; + } +} diff --git a/windows/QMK Toolbox/Usb/Bootloader/HalfKayDevice.cs b/windows/QMK Toolbox/Usb/Bootloader/HalfKayDevice.cs new file mode 100644 index 0000000000..6eece7d948 --- /dev/null +++ b/windows/QMK Toolbox/Usb/Bootloader/HalfKayDevice.cs @@ -0,0 +1,19 @@ +using System.Threading.Tasks; + +namespace QMK_Toolbox.Usb.Bootloader +{ + class HalfKayDevice : BootloaderDevice + { + public HalfKayDevice(UsbDevice d) : base(d) + { + Type = BootloaderType.HalfKay; + Name = "HalfKay"; + PreferredDriver = "HidUsb"; + IsResettable = true; + } + + public async override Task Flash(string mcu, string file) => await RunProcessAsync("teensy_loader_cli.exe", $"-mmcu={mcu} \"{file}\" -v"); + + public async override Task Reset(string mcu) => await RunProcessAsync("teensy_loader_cli.exe", $"-mmcu={mcu} -bv"); + } +} diff --git a/windows/QMK Toolbox/Usb/Bootloader/KiibohdDfuDevice.cs b/windows/QMK Toolbox/Usb/Bootloader/KiibohdDfuDevice.cs new file mode 100644 index 0000000000..b8785b2506 --- /dev/null +++ b/windows/QMK Toolbox/Usb/Bootloader/KiibohdDfuDevice.cs @@ -0,0 +1,30 @@ +using System.IO; +using System.Threading.Tasks; + +namespace QMK_Toolbox.Usb.Bootloader +{ + class KiibohdDfuDevice : BootloaderDevice + { + public KiibohdDfuDevice(UsbDevice d) : base(d) + { + Type = BootloaderType.KiibohdDfu; + Name = "Kiibohd DFU"; + PreferredDriver = "WinUSB"; + IsResettable = true; + } + + public async override Task Flash(string mcu, string file) + { + if (Path.GetExtension(file)?.ToLower() == ".bin") + { + await RunProcessAsync("dfu-util.exe", $"-a 0 -d 1C11:B007 -D \"{file}\""); + } + else + { + PrintMessage("Only firmware files in .bin format can be flashed with dfu-util!", MessageType.Error); + } + } + + public async override Task Reset(string mcu) => await RunProcessAsync("dfu-util.exe", "-a 0 -d 1C11:B007 -e"); + } +} diff --git a/windows/QMK Toolbox/Usb/Bootloader/LufaMsDevice.cs b/windows/QMK Toolbox/Usb/Bootloader/LufaMsDevice.cs new file mode 100644 index 0000000000..ac5256a154 --- /dev/null +++ b/windows/QMK Toolbox/Usb/Bootloader/LufaMsDevice.cs @@ -0,0 +1,91 @@ +using System.IO; +using System.Management; +using System.Threading.Tasks; + +namespace QMK_Toolbox.Usb.Bootloader +{ + class LufaMsDevice : BootloaderDevice + { + public string MountPoint { get; } + + public LufaMsDevice(UsbDevice d) : base(d) + { + Type = BootloaderType.LufaMs; + Name = "LUFA MS"; + PreferredDriver = "USBSTOR"; + + MountPoint = FindMountPoint(); + } + + public async override Task Flash(string mcu, string file) + { + await Task.Run(() => + { + if (MountPoint == null) + { + PrintMessage("Mount point not found!", MessageType.Error); + return; + } + + if (Path.GetExtension(file)?.ToLower() == ".bin") + { + var destFile = $"{MountPoint}\\FLASH.BIN"; + + try + { + PrintMessage($"Deleting {destFile}...", MessageType.Command); + File.Delete(destFile); + PrintMessage($"Copying {file} to {destFile}...", MessageType.Command); + File.Copy(file, destFile); + + PrintMessage("Done, please eject drive now.", MessageType.Bootloader); + } + catch (IOException e) + { + PrintMessage($"IO ERROR: {e.Message}", MessageType.Error); + } + } + else + { + PrintMessage("Only firmware files in .bin format can be flashed with this bootloader!", MessageType.Error); + } + }); + } + + public override string ToString() => $"{base.ToString()} [{MountPoint}]"; + + private static string FindMountPoint() + { + foreach (ManagementObject usbHub in new ManagementObjectSearcher("SELECT * FROM Win32_USBHub").Get()) + { + if (usbHub.GetPropertyValue("PNPDeviceID").ToString().Equals(WmiDevice.GetPropertyValue("PNPDeviceID").ToString())) + { + foreach (ManagementObject usbController in usbHub.GetRelated("Win32_USBController")) + { + foreach (ManagementObject assoc in new ManagementObjectSearcher("ASSOCIATORS OF {Win32_USBController.DeviceID='" + usbController["PNPDeviceID"].ToString() + "'}").Get()) + { + if (assoc.GetPropertyValue("CreationClassName").Equals("Win32_PnPEntity") && assoc.GetPropertyValue("DeviceID").ToString().Contains("USBSTOR")) + { + foreach (ManagementObject diskDrive in new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive").Get()) + { + if (diskDrive.GetPropertyValue("PNPDeviceID").ToString().Equals(assoc.GetPropertyValue("PNPDeviceID").ToString())) + { + foreach (ManagementObject partition in diskDrive.GetRelated("Win32_DiskPartition")) + { + foreach (ManagementObject logicalDisk in partition.GetRelated("Win32_LogicalDisk")) + { + return logicalDisk.GetPropertyValue("Name").ToString(); + } + } + } + } + } + } + } + } + } + + return null; + } + } +} diff --git a/windows/QMK Toolbox/Usb/Bootloader/Stm32DfuDevice.cs b/windows/QMK Toolbox/Usb/Bootloader/Stm32DfuDevice.cs new file mode 100644 index 0000000000..9798601a5a --- /dev/null +++ b/windows/QMK Toolbox/Usb/Bootloader/Stm32DfuDevice.cs @@ -0,0 +1,30 @@ +using System.IO; +using System.Threading.Tasks; + +namespace QMK_Toolbox.Usb.Bootloader +{ + class Stm32DfuDevice : BootloaderDevice + { + public Stm32DfuDevice(UsbDevice d) : base(d) + { + Type = BootloaderType.Stm32Dfu; + Name = "STM32 DFU"; + PreferredDriver = "WinUSB"; + IsResettable = true; + } + + public async override Task Flash(string mcu, string file) + { + if (Path.GetExtension(file)?.ToLower() == ".bin") + { + await RunProcessAsync("dfu-util.exe", $"-a 0 -d 0483:DF11 -s 0x08000000:leave -D \"{file}\""); + } + else + { + PrintMessage("Only firmware files in .bin format can be flashed with dfu-util!", MessageType.Error); + } + } + + public async override Task Reset(string mcu) => await RunProcessAsync("dfu-util.exe", "-a 0 -d 0483:DF11 -s 0x08000000:leave"); + } +} diff --git a/windows/QMK Toolbox/Usb/Bootloader/Stm32DuinoDevice.cs b/windows/QMK Toolbox/Usb/Bootloader/Stm32DuinoDevice.cs new file mode 100644 index 0000000000..2f4187ebc7 --- /dev/null +++ b/windows/QMK Toolbox/Usb/Bootloader/Stm32DuinoDevice.cs @@ -0,0 +1,27 @@ +using System.IO; +using System.Threading.Tasks; + +namespace QMK_Toolbox.Usb.Bootloader +{ + class Stm32DuinoDevice : BootloaderDevice + { + public Stm32DuinoDevice(UsbDevice d) : base(d) + { + Type = BootloaderType.Stm32Duino; + Name = "STM32Duino"; + PreferredDriver = "WinUSB"; + } + + public async override Task Flash(string mcu, string file) + { + if (Path.GetExtension(file)?.ToLower() == ".bin") + { + await RunProcessAsync("dfu-util.exe", $"-a 2 -d 1EAF:0003 -R -D \"{file}\""); + } + else + { + PrintMessage("Only firmware files in .bin format can be flashed with dfu-util!", MessageType.Error); + } + } + } +} diff --git a/windows/QMK Toolbox/Usb/Bootloader/UsbAspDevice.cs b/windows/QMK Toolbox/Usb/Bootloader/UsbAspDevice.cs new file mode 100644 index 0000000000..e529d5e0b9 --- /dev/null +++ b/windows/QMK Toolbox/Usb/Bootloader/UsbAspDevice.cs @@ -0,0 +1,19 @@ +using System.Threading.Tasks; + +namespace QMK_Toolbox.Usb.Bootloader +{ + class UsbAspDevice : BootloaderDevice + { + public UsbAspDevice(UsbDevice d) : base(d) + { + Type = BootloaderType.UsbAsp; + Name = "USBasp"; + PreferredDriver = "libusbK"; + IsEepromFlashable = true; + } + + public async override Task Flash(string mcu, string file) => await RunProcessAsync("avrdude.exe", $"-p {mcu} -c usbasp -U flash:w:\"{file}\":i"); + + public async override Task FlashEeprom(string mcu, string file) => await RunProcessAsync("avrdude.exe", $"-p {mcu} -c usbasp -U eeprom:w:\"{file}\":i"); + } +} diff --git a/windows/QMK Toolbox/Usb/Bootloader/UsbTinyIspDevice.cs b/windows/QMK Toolbox/Usb/Bootloader/UsbTinyIspDevice.cs new file mode 100644 index 0000000000..701df7b7de --- /dev/null +++ b/windows/QMK Toolbox/Usb/Bootloader/UsbTinyIspDevice.cs @@ -0,0 +1,19 @@ +using System.Threading.Tasks; + +namespace QMK_Toolbox.Usb.Bootloader +{ + class UsbTinyIspDevice : BootloaderDevice + { + public UsbTinyIspDevice(UsbDevice d) : base(d) + { + Type = BootloaderType.UsbTinyIsp; + Name = "USBtinyISP"; + PreferredDriver = "libusb0"; + IsEepromFlashable = true; + } + + public async override Task Flash(string mcu, string file) => await RunProcessAsync("avrdude.exe", $"-p {mcu} -c usbtiny -U flash:w:\"{file}\":i"); + + public async override Task FlashEeprom(string mcu, string file) => await RunProcessAsync("avrdude.exe", $"-p {mcu} -c usbtiny -U eeprom:w:\"{file}\":i"); + } +} diff --git a/windows/QMK Toolbox/Usb/IUsbDevice.cs b/windows/QMK Toolbox/Usb/IUsbDevice.cs new file mode 100644 index 0000000000..8bc4a04790 --- /dev/null +++ b/windows/QMK Toolbox/Usb/IUsbDevice.cs @@ -0,0 +1,21 @@ +using System.Management; + +namespace QMK_Toolbox.Usb +{ + public interface IUsbDevice + { + ManagementBaseObject WmiDevice { get; } + + ushort VendorId { get; } + + ushort ProductId { get; } + + ushort RevisionBcd { get; } + + string ManufacturerString { get; } + + string ProductString { get; } + + string Driver { get; } + } +} diff --git a/windows/QMK Toolbox/Usb/UsbDevice.cs b/windows/QMK Toolbox/Usb/UsbDevice.cs new file mode 100644 index 0000000000..3ade706c85 --- /dev/null +++ b/windows/QMK Toolbox/Usb/UsbDevice.cs @@ -0,0 +1,83 @@ +using System; +using System.Management; +using System.Text.RegularExpressions; + +namespace QMK_Toolbox.Usb +{ + public class UsbDevice : IUsbDevice + { + private static readonly Regex HardwareIdTripletRegex = new Regex(@"USB\\VID_([0-9A-F]{4})&PID_([0-9A-F]{4})&REV_([0-9A-F]{4}).*"); + + public ManagementBaseObject WmiDevice { get; } + + public ushort VendorId { get; } + + public ushort ProductId { get; } + + public ushort RevisionBcd { get; } + + public string ManufacturerString { get; } + + public string ProductString { get; } + + public string Driver { get; } + + public UsbDevice(ManagementBaseObject d) + { + WmiDevice = d; + + ManufacturerString = (string)WmiDevice.GetPropertyValue("Manufacturer"); + ProductString = (string)WmiDevice.GetPropertyValue("Name"); + + var hardwareIdTriplet = HardwareIdTripletRegex.Match(GetHardwareId(WmiDevice)); + VendorId = Convert.ToUInt16(hardwareIdTriplet.Groups[1].ToString(), 16); + ProductId = Convert.ToUInt16(hardwareIdTriplet.Groups[2].ToString(), 16); + RevisionBcd = Convert.ToUInt16(hardwareIdTriplet.Groups[3].ToString(), 16); + + Driver = GetDriverName(WmiDevice); + } + + public override string ToString() + { + return $"{ManufacturerString} {ProductString} ({VendorId:X4}:{ProductId:X4}:{RevisionBcd:X4})"; + } + + private static string GetHardwareId(ManagementBaseObject d) + { + var hardwareIds = (string[])d.GetPropertyValue("HardwareID"); + if (hardwareIds != null && hardwareIds.Length > 0) + { + return hardwareIds[0]; + } + + return null; + } + + private static string GetDriverName(ManagementBaseObject d) + { + var service = (string)d.GetPropertyValue("Service"); + if (service != null && service.Length > 0) + { + return service; + } + + return "NO DRIVER"; + } + + protected string FindComPort() + { + using (var searcher = new ManagementObjectSearcher("SELECT PNPDeviceID, DeviceID FROM Win32_SerialPort")) + { + foreach (var device in searcher.Get()) + { + if (device.GetPropertyValue("PNPDeviceID").ToString().Equals(WmiDevice.GetPropertyValue("PNPDeviceID").ToString())) + { + return device.GetPropertyValue("DeviceID").ToString(); + } + } + } + + return null; + } + } +} diff --git a/windows/QMK Toolbox/Usb/UsbListener.cs b/windows/QMK Toolbox/Usb/UsbListener.cs new file mode 100644 index 0000000000..9b417e9f6c --- /dev/null +++ b/windows/QMK Toolbox/Usb/UsbListener.cs @@ -0,0 +1,301 @@ +using QMK_Toolbox.Usb.Bootloader; +using System.Collections.Generic; +using System.Linq; +using System.Management; +using System.Text.RegularExpressions; + +namespace QMK_Toolbox.Usb +{ + public class UsbListener + { + private static readonly Regex UsbIdRegex = new Regex(@"USB\\VID_([0-9A-F]{4})&PID_([0-9A-F]{4}).*"); + + public List Devices { get; private set; } + + public delegate void UsbDeviceEventDelegate(UsbDevice device); + + public delegate void BootloaderDeviceEventDelegate(BootloaderDevice device); + public delegate void FlashOutputReceivedDelegate(BootloaderDevice device, string data, MessageType type); + + public UsbDeviceEventDelegate usbDeviceConnected; + public UsbDeviceEventDelegate usbDeviceDisconnected; + + public BootloaderDeviceEventDelegate bootloaderDeviceConnected; + public BootloaderDeviceEventDelegate bootloaderDeviceDisconnected; + public FlashOutputReceivedDelegate outputReceived; + + private void EnumerateUsbDevices(bool connected) + { + var enumeratedDevices = new ManagementObjectSearcher(@"SELECT * FROM Win32_PnPEntity WHERE DeviceID LIKE 'USB%'").Get() + .Cast().ToList() + .Where(d => UsbIdRegex.Match((string)d.GetPropertyValue("DeviceID")).Success); + + if (connected) + { + foreach (var device in enumeratedDevices) + { + var listed = Devices.Aggregate(false, (curr, d) => curr | d.WmiDevice.Equals(device)); + + if (device != null && !listed) + { + IUsbDevice usbDevice = CreateDevice(device); + Devices.Add(usbDevice); + + if (usbDevice is BootloaderDevice) + { + bootloaderDeviceConnected?.Invoke(usbDevice as BootloaderDevice); + (usbDevice as BootloaderDevice).outputReceived = FlashOutputReceived; + } + else + { + usbDeviceConnected?.Invoke(usbDevice as UsbDevice); + } + } + } + } + else + { + foreach (var device in Devices.ToList()) + { + var listed = enumeratedDevices.Aggregate(false, (curr, d) => curr | device.WmiDevice.Equals(d)); + + if (!listed) + { + Devices.Remove(device); + + if (device is BootloaderDevice) + { + bootloaderDeviceDisconnected?.Invoke(device as BootloaderDevice); + (device as BootloaderDevice).outputReceived = null; + } + else + { + usbDeviceDisconnected?.Invoke(device as UsbDevice); + } + } + } + } + } + + private void FlashOutputReceived(BootloaderDevice device, string data, MessageType type) + { + outputReceived?.Invoke(device, data, type); + } + + private ManagementEventWatcher deviceConnectedWatcher; + private ManagementEventWatcher deviceDisconnectedWatcher; + + private ManagementEventWatcher CreateManagementEventWatcher(string eventType) + { + return new ManagementEventWatcher($"SELECT * FROM {eventType} WITHIN 2 WHERE TargetInstance ISA 'Win32_PnPEntity' AND TargetInstance.DeviceID LIKE 'USB%'"); + } + + private void UsbDeviceWmiEvent(object sender, EventArrivedEventArgs e) + { + if (!(e.NewEvent["TargetInstance"] is ManagementBaseObject _)) + { + return; + } + + (sender as ManagementEventWatcher)?.Stop(); + EnumerateUsbDevices(e.NewEvent.ClassPath.ClassName.Equals("__InstanceCreationEvent")); + (sender as ManagementEventWatcher)?.Start(); + } + + public void Start() + { + if (Devices == null) + { + Devices = new List(); + } + EnumerateUsbDevices(true); + + if (deviceConnectedWatcher == null) + { + deviceConnectedWatcher = CreateManagementEventWatcher("__InstanceCreationEvent"); + } + deviceConnectedWatcher.EventArrived += UsbDeviceWmiEvent; + deviceConnectedWatcher.Start(); + + if (deviceDisconnectedWatcher == null) + { + deviceDisconnectedWatcher = CreateManagementEventWatcher("__InstanceDeletionEvent"); + } + deviceDisconnectedWatcher.EventArrived += UsbDeviceWmiEvent; + deviceDisconnectedWatcher.Start(); + } + + public void Stop() + { + if (deviceConnectedWatcher != null) + { + deviceConnectedWatcher.Stop(); + deviceConnectedWatcher.EventArrived -= UsbDeviceWmiEvent; + } + + if (deviceDisconnectedWatcher != null) + { + deviceDisconnectedWatcher.Stop(); + deviceDisconnectedWatcher.EventArrived -= UsbDeviceWmiEvent; + } + } + + public void Dispose() + { + Stop(); + deviceConnectedWatcher?.Dispose(); + deviceDisconnectedWatcher?.Dispose(); + } + + private static IUsbDevice CreateDevice(ManagementBaseObject d) + { + UsbDevice usbDevice = new UsbDevice(d); + + switch (GetDeviceType(usbDevice.VendorId, usbDevice.ProductId, usbDevice.RevisionBcd)) + { + case BootloaderType.Apm32Dfu: + return new Apm32DfuDevice(usbDevice); + case BootloaderType.AtmelDfu: + case BootloaderType.QmkDfu: + return new AtmelDfuDevice(usbDevice); + case BootloaderType.AtmelSamBa: + return new AtmelSamBaDevice(usbDevice); + case BootloaderType.AvrIsp: + return new AvrIspDevice(usbDevice); + case BootloaderType.BootloadHid: + return new BootloadHidDevice(usbDevice); + case BootloaderType.Caterina: + return new CaterinaDevice(usbDevice); + case BootloaderType.HalfKay: + return new HalfKayDevice(usbDevice); + case BootloaderType.KiibohdDfu: + return new KiibohdDfuDevice(usbDevice); + case BootloaderType.LufaMs: + return new LufaMsDevice(usbDevice); + case BootloaderType.Stm32Dfu: + return new Stm32DfuDevice(usbDevice); + case BootloaderType.Stm32Duino: + return new Stm32DuinoDevice(usbDevice); + case BootloaderType.UsbAsp: + return new UsbAspDevice(usbDevice); + case BootloaderType.UsbTinyIsp: + return new UsbTinyIspDevice(usbDevice); + } + + return usbDevice; + } + + private static BootloaderType GetDeviceType(ushort vendorId, ushort productId, ushort revisionBcd) + { + switch (vendorId) + { + case 0x03EB: + switch (productId) + { + case 0x2045: + return BootloaderType.LufaMs; + case 0x2FEF: // ATmega16U2 + case 0x2FF0: // ATmega32U2 + case 0x2FF3: // ATmega16U4 + case 0x2FF4: // ATmega32U4 + case 0x2FF9: // AT90USB64 + case 0x2FFA: // AT90USB162 + case 0x2FFB: // AT90USB128 + if (revisionBcd == 0x0936) // Unicode Ψ + { + return BootloaderType.QmkDfu; + } + + return BootloaderType.AtmelDfu; + case 0x6124: + return BootloaderType.AtmelSamBa; + } + break; + case 0x0483: + if (productId == 0xDF11) + { + return BootloaderType.Stm32Dfu; + } + break; + case 0x1209: // pid.codes + if (productId == 0x2302) // Keyboardio Atreus 2 Bootloader + { + return BootloaderType.Caterina; + } + break; + case 0x16C0: + switch (productId) + { + case 0x0478: + return BootloaderType.HalfKay; + case 0x0483: + return BootloaderType.AvrIsp; + case 0x05DC: + return BootloaderType.UsbAsp; + case 0x05DF: + return BootloaderType.BootloadHid; + } + break; + case 0x1781: + if (productId == 0x0C9F) + { + return BootloaderType.UsbTinyIsp; + } + break; + case 0x1B4F: // Spark Fun Electronics + switch (productId) + { + case 0x9203: // Pro Micro 3V3/8MHz + case 0x9205: // Pro Micro 5V/16MHz + case 0x9207: // LilyPad 3V3/8MHz (and some Pro Micro clones) + return BootloaderType.Caterina; + } + break; + case 0x1C11: + if (productId == 0xB007) + { + return BootloaderType.KiibohdDfu; + } + break; + case 0x1EAF: + if (productId == 0x0003) + { + return BootloaderType.Stm32Duino; + } + break; + case 0x1FFB: // Pololu Electronics + if (productId == 0x0101) // A-Star 32U4 + { + return BootloaderType.Caterina; + } + break; + case 0x2341: // Arduino SA + case 0x2A03: // dog hunter AG + switch (productId) + { + case 0x0036: // Leonardo + case 0x0037: // Micro + return BootloaderType.Caterina; + } + break; + case 0x239A: // Adafruit Industries LLC + switch (productId) + { + case 0x000C: // Feather 32U4 + case 0x000D: // ItsyBitsy 32U4 3V3/8MHz + case 0x000E: // ItsyBitsy 32U4 5V/16MHz + return BootloaderType.Caterina; + } + break; + case 0x314B: + if (productId == 0x0106) + { + return BootloaderType.Apm32Dfu; + } + break; + } + + return BootloaderType.None; + } + } +} From 61f8e63cd83bd27960709d13fa01bf62d5b577ad Mon Sep 17 00:00:00 2001 From: fauxpark Date: Thu, 10 Mar 2022 20:42:54 +1100 Subject: [PATCH 2/9] Fix some silly errors --- .../Usb/Bootloader/AtmelSamBaDevice.cs | 2 +- .../QMK Toolbox/Usb/Bootloader/AvrIspDevice.cs | 2 +- .../Usb/Bootloader/BootloaderDevice.cs | 16 ++++++++++++++++ .../QMK Toolbox/Usb/Bootloader/CaterinaDevice.cs | 2 +- .../QMK Toolbox/Usb/Bootloader/LufaMsDevice.cs | 2 +- windows/QMK Toolbox/Usb/UsbDevice.cs | 16 ---------------- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/windows/QMK Toolbox/Usb/Bootloader/AtmelSamBaDevice.cs b/windows/QMK Toolbox/Usb/Bootloader/AtmelSamBaDevice.cs index fae1306ff2..8648f16233 100644 --- a/windows/QMK Toolbox/Usb/Bootloader/AtmelSamBaDevice.cs +++ b/windows/QMK Toolbox/Usb/Bootloader/AtmelSamBaDevice.cs @@ -13,7 +13,7 @@ public AtmelSamBaDevice(UsbDevice d) : base(d) PreferredDriver = "usbser"; IsResettable = true; - ComPort = UsbDevice.FindComPort(); + ComPort = FindComPort(); } public async override Task Flash(string mcu, string file) diff --git a/windows/QMK Toolbox/Usb/Bootloader/AvrIspDevice.cs b/windows/QMK Toolbox/Usb/Bootloader/AvrIspDevice.cs index c5821b4465..dc51b766f8 100644 --- a/windows/QMK Toolbox/Usb/Bootloader/AvrIspDevice.cs +++ b/windows/QMK Toolbox/Usb/Bootloader/AvrIspDevice.cs @@ -12,7 +12,7 @@ public AvrIspDevice(UsbDevice d) : base(d) Name = "AVR ISP"; PreferredDriver = "usbser"; - ComPort = UsbDevice.FindComPort(); + ComPort = FindComPort(); } public async override Task Flash(string mcu, string file) diff --git a/windows/QMK Toolbox/Usb/Bootloader/BootloaderDevice.cs b/windows/QMK Toolbox/Usb/Bootloader/BootloaderDevice.cs index a3fae05ca0..d4bf226d94 100644 --- a/windows/QMK Toolbox/Usb/Bootloader/BootloaderDevice.cs +++ b/windows/QMK Toolbox/Usb/Bootloader/BootloaderDevice.cs @@ -130,5 +130,21 @@ protected void PrintMessage(string message, MessageType type) { outputReceived?.Invoke(this, message, type); } + + protected string FindComPort() + { + using (var searcher = new ManagementObjectSearcher("SELECT PNPDeviceID, DeviceID FROM Win32_SerialPort")) + { + foreach (var device in searcher.Get()) + { + if (device.GetPropertyValue("PNPDeviceID").ToString().Equals(WmiDevice.GetPropertyValue("PNPDeviceID").ToString())) + { + return device.GetPropertyValue("DeviceID").ToString(); + } + } + } + + return null; + } } } diff --git a/windows/QMK Toolbox/Usb/Bootloader/CaterinaDevice.cs b/windows/QMK Toolbox/Usb/Bootloader/CaterinaDevice.cs index 182fc8ef5d..a89de04d69 100644 --- a/windows/QMK Toolbox/Usb/Bootloader/CaterinaDevice.cs +++ b/windows/QMK Toolbox/Usb/Bootloader/CaterinaDevice.cs @@ -13,7 +13,7 @@ public CaterinaDevice(UsbDevice d) : base(d) PreferredDriver = "usbser"; IsEepromFlashable = true; - ComPort = UsbDevice.FindComPort(); + ComPort = FindComPort(); } public async override Task Flash(string mcu, string file) diff --git a/windows/QMK Toolbox/Usb/Bootloader/LufaMsDevice.cs b/windows/QMK Toolbox/Usb/Bootloader/LufaMsDevice.cs index ac5256a154..b191b105ea 100644 --- a/windows/QMK Toolbox/Usb/Bootloader/LufaMsDevice.cs +++ b/windows/QMK Toolbox/Usb/Bootloader/LufaMsDevice.cs @@ -54,7 +54,7 @@ await Task.Run(() => public override string ToString() => $"{base.ToString()} [{MountPoint}]"; - private static string FindMountPoint() + private string FindMountPoint() { foreach (ManagementObject usbHub in new ManagementObjectSearcher("SELECT * FROM Win32_USBHub").Get()) { diff --git a/windows/QMK Toolbox/Usb/UsbDevice.cs b/windows/QMK Toolbox/Usb/UsbDevice.cs index 3ade706c85..6cb3b3f063 100644 --- a/windows/QMK Toolbox/Usb/UsbDevice.cs +++ b/windows/QMK Toolbox/Usb/UsbDevice.cs @@ -63,21 +63,5 @@ private static string GetDriverName(ManagementBaseObject d) return "NO DRIVER"; } - - protected string FindComPort() - { - using (var searcher = new ManagementObjectSearcher("SELECT PNPDeviceID, DeviceID FROM Win32_SerialPort")) - { - foreach (var device in searcher.Get()) - { - if (device.GetPropertyValue("PNPDeviceID").ToString().Equals(WmiDevice.GetPropertyValue("PNPDeviceID").ToString())) - { - return device.GetPropertyValue("DeviceID").ToString(); - } - } - } - - return null; - } } } From e32bc7d897c1071eeb19672ff4dda83a00e99afb Mon Sep 17 00:00:00 2001 From: fauxpark Date: Fri, 11 Mar 2022 22:28:58 +1100 Subject: [PATCH 3/9] Extract MessageType --- windows/QMK Toolbox/MessageType.cs | 11 +++++++++++ windows/QMK Toolbox/Printing.cs | 9 --------- windows/QMK Toolbox/QMK Toolbox.csproj | 1 + 3 files changed, 12 insertions(+), 9 deletions(-) create mode 100644 windows/QMK Toolbox/MessageType.cs diff --git a/windows/QMK Toolbox/MessageType.cs b/windows/QMK Toolbox/MessageType.cs new file mode 100644 index 0000000000..66af136339 --- /dev/null +++ b/windows/QMK Toolbox/MessageType.cs @@ -0,0 +1,11 @@ +namespace QMK_Toolbox +{ + public enum MessageType + { + Bootloader, + Command, + Error, + Hid, + Info + } +} diff --git a/windows/QMK Toolbox/Printing.cs b/windows/QMK Toolbox/Printing.cs index 44020e7cf6..b1b152c3a9 100644 --- a/windows/QMK Toolbox/Printing.cs +++ b/windows/QMK Toolbox/Printing.cs @@ -5,15 +5,6 @@ namespace QMK_Toolbox { - public enum MessageType - { - Bootloader, - Hid, - Command, - Info, - Error - } - public class Printing { private MessageType _lastMessage; diff --git a/windows/QMK Toolbox/QMK Toolbox.csproj b/windows/QMK Toolbox/QMK Toolbox.csproj index 2010b94e1e..70e90a498b 100644 --- a/windows/QMK Toolbox/QMK Toolbox.csproj +++ b/windows/QMK Toolbox/QMK Toolbox.csproj @@ -90,6 +90,7 @@ KeyTesterWindow.cs + Component From a12f56b24b294e740914bd3b37b0fb7811ccf7cc Mon Sep 17 00:00:00 2001 From: fauxpark Date: Sat, 12 Mar 2022 19:59:24 +1100 Subject: [PATCH 4/9] Add setting to control normal USB device logging --- windows/QMK Toolbox/App.config | 3 ++ windows/QMK Toolbox/MainWindow.Designer.cs | 11 ++++++ windows/QMK Toolbox/MainWindow.cs | 36 +++++++++++++------ .../Properties/Settings.Designer.cs | 12 +++++++ .../QMK Toolbox/Properties/Settings.settings | 3 ++ windows/QMK Toolbox/WindowState.cs | 14 ++++++++ 6 files changed, 69 insertions(+), 10 deletions(-) diff --git a/windows/QMK Toolbox/App.config b/windows/QMK Toolbox/App.config index b0e8945fd0..1c4afd8cf5 100644 --- a/windows/QMK Toolbox/App.config +++ b/windows/QMK Toolbox/App.config @@ -36,6 +36,9 @@ False + + False + diff --git a/windows/QMK Toolbox/MainWindow.Designer.cs b/windows/QMK Toolbox/MainWindow.Designer.cs index 86a879ae8a..362f7ede66 100644 --- a/windows/QMK Toolbox/MainWindow.Designer.cs +++ b/windows/QMK Toolbox/MainWindow.Designer.cs @@ -61,6 +61,7 @@ private void InitializeComponent() { this.exitDFUToolStripMenuItem = new QMK_Toolbox.BindableToolStripMenuItem(); this.toolsToolStripMenuSep1 = new System.Windows.Forms.ToolStripSeparator(); this.autoFlashToolStripMenuItem = new QMK_Toolbox.BindableToolStripMenuItem(); + this.showAllDevicesToolStripMenuItem = new QMK_Toolbox.BindableToolStripMenuItem(); this.toolsToolStripMenuSep2 = new System.Windows.Forms.ToolStripSeparator(); this.keyTesterToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.installDriversToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -349,6 +350,7 @@ private void InitializeComponent() { this.exitDFUToolStripMenuItem, this.toolsToolStripMenuSep1, this.autoFlashToolStripMenuItem, + this.showAllDevicesToolStripMenuItem, this.toolsToolStripMenuSep2, this.keyTesterToolStripMenuItem, this.installDriversToolStripMenuItem, @@ -440,6 +442,14 @@ private void InitializeComponent() { this.autoFlashToolStripMenuItem.Size = new System.Drawing.Size(196, 22); this.autoFlashToolStripMenuItem.Text = "Auto-Flash"; // + // showAllDevicesToolStripMenuItem + // + this.showAllDevicesToolStripMenuItem.CheckOnClick = true; + this.showAllDevicesToolStripMenuItem.DataBindings.Add(new System.Windows.Forms.Binding("Checked", this.windowStateBindingSource, "ShowAllDevices", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged)); + this.showAllDevicesToolStripMenuItem.Name = "showAllDevicesToolStripMenuItem"; + this.showAllDevicesToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.showAllDevicesToolStripMenuItem.Text = "Show All Devices"; + // // toolsToolStripMenuSep2 // this.toolsToolStripMenuSep2.Name = "toolsToolStripMenuSep2"; @@ -584,5 +594,6 @@ private void InitializeComponent() { private System.Windows.Forms.ToolStripSeparator eepromToolStripMenuSep; private System.Windows.Forms.ToolStripMenuItem keyTesterToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolsToolStripMenuSep3; + private QMK_Toolbox.BindableToolStripMenuItem showAllDevicesToolStripMenuItem; } } diff --git a/windows/QMK Toolbox/MainWindow.cs b/windows/QMK Toolbox/MainWindow.cs index dee260d244..258d74e5ba 100644 --- a/windows/QMK Toolbox/MainWindow.cs +++ b/windows/QMK Toolbox/MainWindow.cs @@ -56,6 +56,8 @@ private void MainWindow_Load(object sender, EventArgs e) { windowStateBindingSource.DataSource = windowState; windowState.PropertyChanged += AutoFlashEnabledChanged; + windowState.PropertyChanged += ShowAllDevicesEnabledChanged; + windowState.ShowAllDevices = Settings.Default.showAllDevices; if (Settings.Default.hexFileCollection != null) { @@ -78,8 +80,8 @@ private void MainWindow_Load(object sender, EventArgs e) _printer.PrintResponse(" - USBasp (AVR ISP)\n", MessageType.Info); _printer.PrintResponse(" - USBTiny (AVR Pocket)\n", MessageType.Info); - //usbListener.usbDeviceConnected += UsbDeviceConnected; - //usbListener.usbDeviceDisconnected += UsbDeviceDisconnected; + usbListener.usbDeviceConnected += UsbDeviceConnected; + usbListener.usbDeviceDisconnected += UsbDeviceDisconnected; usbListener.bootloaderDeviceConnected += BootloaderDeviceConnected; usbListener.bootloaderDeviceDisconnected += BootloaderDeviceDisconnected; usbListener.outputReceived += BootloaderCommandOutputReceived; @@ -269,15 +271,21 @@ private void BootloaderCommandOutputReceived(BootloaderDevice device, string dat _printer.PrintResponse($"{data}\n", type); } - //private void UsbDeviceConnected(UsbDevice device) - //{ - // _printer.Print($"USB device connected ({device.Driver}): {device}", MessageType.Info); - //} + private void UsbDeviceConnected(UsbDevice device) + { + if (windowState.ShowAllDevices) + { + _printer.Print($"USB device connected ({device.Driver}): {device}", MessageType.Info); + } + } - //private void UsbDeviceDisconnected(UsbDevice device) - //{ - // _printer.Print($"USB device disconnected ({device.Driver}): {device}", MessageType.Info); - //} + private void UsbDeviceDisconnected(UsbDevice device) + { + if (windowState.ShowAllDevices) + { + _printer.Print($"USB device disconnected ({device.Driver}): {device}", MessageType.Info); + } + } #endregion #region UI Interaction @@ -298,6 +306,14 @@ private void AutoFlashEnabledChanged(object sender, PropertyChangedEventArgs e) } } + private void ShowAllDevicesEnabledChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == "ShowAllDevices") + { + Settings.Default.showAllDevices = windowState.ShowAllDevices; + } + } + private async void FlashButton_Click(object sender, EventArgs e) { string selectedMcu = (string)mcuBox.SelectedValue; diff --git a/windows/QMK Toolbox/Properties/Settings.Designer.cs b/windows/QMK Toolbox/Properties/Settings.Designer.cs index 85ff67f09a..288e90fa7f 100644 --- a/windows/QMK Toolbox/Properties/Settings.Designer.cs +++ b/windows/QMK Toolbox/Properties/Settings.Designer.cs @@ -129,5 +129,17 @@ public bool driversInstalled { this["driversInstalled"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool showAllDevices { + get { + return ((bool)(this["showAllDevices"])); + } + set { + this["showAllDevices"] = value; + } + } } } diff --git a/windows/QMK Toolbox/Properties/Settings.settings b/windows/QMK Toolbox/Properties/Settings.settings index 8be7ca2db0..69882fc1bc 100644 --- a/windows/QMK Toolbox/Properties/Settings.settings +++ b/windows/QMK Toolbox/Properties/Settings.settings @@ -29,5 +29,8 @@ False + + False + \ No newline at end of file diff --git a/windows/QMK Toolbox/WindowState.cs b/windows/QMK Toolbox/WindowState.cs index 4b3cd2ad30..4604718695 100644 --- a/windows/QMK Toolbox/WindowState.cs +++ b/windows/QMK Toolbox/WindowState.cs @@ -19,6 +19,20 @@ public bool AutoFlashEnabled } } + private bool _showAllDevices = false; + public bool ShowAllDevices + { + get => _showAllDevices; + set + { + if (_showAllDevices != value) + { + _showAllDevices = value; + OnPropertyChanged(); + } + } + } + private bool _canFlash = false; public bool CanFlash { From bfdf23cf6e87f2cc47b0e01b4f4bba0317757646 Mon Sep 17 00:00:00 2001 From: fauxpark Date: Sat, 12 Mar 2022 20:00:52 +1100 Subject: [PATCH 5/9] Remove completion messages for now --- windows/QMK Toolbox/MainWindow.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/windows/QMK Toolbox/MainWindow.cs b/windows/QMK Toolbox/MainWindow.cs index 258d74e5ba..0cc6885b88 100644 --- a/windows/QMK Toolbox/MainWindow.cs +++ b/windows/QMK Toolbox/MainWindow.cs @@ -334,7 +334,6 @@ private async void FlashButton_Click(object sender, EventArgs e) { _printer.Print("Attempting to flash, please don't remove device", MessageType.Bootloader); await b.Flash(selectedMcu, filePath); - _printer.Print("Flash complete", MessageType.Bootloader); } if (!windowState.AutoFlashEnabled) @@ -381,7 +380,6 @@ private async void ClearEepromButton_Click(object sender, EventArgs e) { _printer.Print("Attempting to clear EEPROM, please don't remove device", MessageType.Bootloader); await b.FlashEeprom(selectedMcu, "reset.eep"); - _printer.Print("EEPROM clear complete", MessageType.Bootloader); } } @@ -407,7 +405,6 @@ private async void SetHandednessButton_Click(object sender, EventArgs e) { _printer.Print("Attempting to set handedness, please don't remove device", MessageType.Bootloader); await b.FlashEeprom(selectedMcu, file); - _printer.Print("EEPROM write complete", MessageType.Bootloader); } } From 8a42fd5073ce18072979e824dd34eb217c085cb4 Mon Sep 17 00:00:00 2001 From: fauxpark Date: Sun, 13 Mar 2022 14:45:53 +1100 Subject: [PATCH 6/9] Fix output sync --- windows/QMK Toolbox/MainWindow.cs | 3 +++ .../Usb/Bootloader/BootloaderDevice.cs | 25 ++++++++----------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/windows/QMK Toolbox/MainWindow.cs b/windows/QMK Toolbox/MainWindow.cs index 0cc6885b88..258d74e5ba 100644 --- a/windows/QMK Toolbox/MainWindow.cs +++ b/windows/QMK Toolbox/MainWindow.cs @@ -334,6 +334,7 @@ private async void FlashButton_Click(object sender, EventArgs e) { _printer.Print("Attempting to flash, please don't remove device", MessageType.Bootloader); await b.Flash(selectedMcu, filePath); + _printer.Print("Flash complete", MessageType.Bootloader); } if (!windowState.AutoFlashEnabled) @@ -380,6 +381,7 @@ private async void ClearEepromButton_Click(object sender, EventArgs e) { _printer.Print("Attempting to clear EEPROM, please don't remove device", MessageType.Bootloader); await b.FlashEeprom(selectedMcu, "reset.eep"); + _printer.Print("EEPROM clear complete", MessageType.Bootloader); } } @@ -405,6 +407,7 @@ private async void SetHandednessButton_Click(object sender, EventArgs e) { _printer.Print("Attempting to set handedness, please don't remove device", MessageType.Bootloader); await b.FlashEeprom(selectedMcu, file); + _printer.Print("EEPROM write complete", MessageType.Bootloader); } } diff --git a/windows/QMK Toolbox/Usb/Bootloader/BootloaderDevice.cs b/windows/QMK Toolbox/Usb/Bootloader/BootloaderDevice.cs index d4bf226d94..57786e0d18 100644 --- a/windows/QMK Toolbox/Usb/Bootloader/BootloaderDevice.cs +++ b/windows/QMK Toolbox/Usb/Bootloader/BootloaderDevice.cs @@ -92,37 +92,34 @@ private Task RunProcessAsync(Process process) tcs.SetResult(process.ExitCode); }; + process.OutputDataReceived += ProcessOutput; + process.ErrorDataReceived += ProcessErrorOutput; + bool started = process.Start(); if (!started) { PrintMessage($"Could not start process: {process}", MessageType.Error); } - Thread processOutputThread = new Thread(ProcessOutput); - processOutputThread.Start(process.StandardOutput); - Thread processErrorOutputThread = new Thread(ProcessErrorOutput); - processErrorOutputThread.Start(process.StandardError); + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); return tcs.Task; } - private void ProcessOutput(object o) + private void ProcessOutput(object sender, DataReceivedEventArgs e) { - StreamReader reader = (StreamReader)o; - - while (!reader.EndOfStream) + if (e.Data != null) { - PrintMessage($"{reader.ReadLine()}", MessageType.Info); + PrintMessage($"{e.Data}", MessageType.Info); } } - private void ProcessErrorOutput(object o) + private void ProcessErrorOutput(object sender, DataReceivedEventArgs e) { - StreamReader reader = (StreamReader)o; - - while (!reader.EndOfStream) + if (e.Data != null) { - PrintMessage($"{reader.ReadLine()}", MessageType.Info); + PrintMessage($"{e.Data}", MessageType.Info); } } From 83354d9ed1c38bd049f6ecbe8e880cfdf033e577 Mon Sep 17 00:00:00 2001 From: fauxpark Date: Sun, 13 Mar 2022 14:48:35 +1100 Subject: [PATCH 7/9] Ensure revision present when enumerating devices --- windows/QMK Toolbox/Usb/UsbListener.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/windows/QMK Toolbox/Usb/UsbListener.cs b/windows/QMK Toolbox/Usb/UsbListener.cs index 9b417e9f6c..6217fe5778 100644 --- a/windows/QMK Toolbox/Usb/UsbListener.cs +++ b/windows/QMK Toolbox/Usb/UsbListener.cs @@ -8,7 +8,7 @@ namespace QMK_Toolbox.Usb { public class UsbListener { - private static readonly Regex UsbIdRegex = new Regex(@"USB\\VID_([0-9A-F]{4})&PID_([0-9A-F]{4}).*"); + private static readonly Regex UsbIdRegex = new Regex(@"USB\\VID_([0-9A-F]{4})&PID_([0-9A-F]{4})&REV_([0-9A-F]{4})"); public List Devices { get; private set; } @@ -28,7 +28,7 @@ private void EnumerateUsbDevices(bool connected) { var enumeratedDevices = new ManagementObjectSearcher(@"SELECT * FROM Win32_PnPEntity WHERE DeviceID LIKE 'USB%'").Get() .Cast().ToList() - .Where(d => UsbIdRegex.Match((string)d.GetPropertyValue("DeviceID")).Success); + .Where(d => ((string[])d.GetPropertyValue("HardwareID")).Any(s => UsbIdRegex.Match(s).Success)); if (connected) { From 387a112d44ecfcde128ad59bded66901fc831ee9 Mon Sep 17 00:00:00 2001 From: fauxpark Date: Sun, 13 Mar 2022 19:35:09 +1100 Subject: [PATCH 8/9] Make sure to extract flashing tools if needed --- .../Helpers/EmbeddedResourceHelper.cs | 19 +++++++++++++++++++ windows/QMK Toolbox/MainWindow.cs | 2 ++ 2 files changed, 21 insertions(+) diff --git a/windows/QMK Toolbox/Helpers/EmbeddedResourceHelper.cs b/windows/QMK Toolbox/Helpers/EmbeddedResourceHelper.cs index 0cbf432bee..482a4f12bd 100644 --- a/windows/QMK Toolbox/Helpers/EmbeddedResourceHelper.cs +++ b/windows/QMK Toolbox/Helpers/EmbeddedResourceHelper.cs @@ -7,6 +7,25 @@ namespace QMK_Toolbox.Helpers { public static class EmbeddedResourceHelper { + public static readonly string[] Resources = + { + "avrdude.conf", + "reset.eep", + "reset_left.eep", + "reset_right.eep", + "avrdude.exe", + "bootloadHID.exe", + "dfu-programmer.exe", + "dfu-util.exe", + "mdloader.exe", + "teensy_loader_cli.exe", + "libftdi1.dll", + "libusb0.dll", + "libusb-0-1-4.dll", + "libusb-1.0.dll", + "libwinpthread-1.dll" + }; + public static void ExtractResource(string file) { var destPath = Path.Combine(Application.LocalUserAppDataPath, file); diff --git a/windows/QMK Toolbox/MainWindow.cs b/windows/QMK Toolbox/MainWindow.cs index 258d74e5ba..6db587e9c4 100644 --- a/windows/QMK Toolbox/MainWindow.cs +++ b/windows/QMK Toolbox/MainWindow.cs @@ -66,6 +66,8 @@ private void MainWindow_Load(object sender, EventArgs e) mcuBox.SelectedValue = Settings.Default.targetSetting; + EmbeddedResourceHelper.ExtractResources(EmbeddedResourceHelper.Resources); + _printer.Print($"QMK Toolbox {Application.ProductVersion} (https://qmk.fm/toolbox)", MessageType.Info); _printer.PrintResponse("Supported bootloaders:\n", MessageType.Info); _printer.PrintResponse(" - ARM DFU (APM32, Kiibohd, STM32, STM32duino) via dfu-util (http://dfu-util.sourceforge.net/)\n", MessageType.Info); From 4908549188fcdb3a60b41d58d26835d60f6e592e Mon Sep 17 00:00:00 2001 From: fauxpark Date: Sun, 20 Mar 2022 17:02:12 +1100 Subject: [PATCH 9/9] Document VIDs --- windows/QMK Toolbox/Usb/UsbListener.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/windows/QMK Toolbox/Usb/UsbListener.cs b/windows/QMK Toolbox/Usb/UsbListener.cs index 6217fe5778..1e7a3c103f 100644 --- a/windows/QMK Toolbox/Usb/UsbListener.cs +++ b/windows/QMK Toolbox/Usb/UsbListener.cs @@ -189,7 +189,7 @@ private static BootloaderType GetDeviceType(ushort vendorId, ushort productId, u { switch (vendorId) { - case 0x03EB: + case 0x03EB: // Atmel Corporation switch (productId) { case 0x2045: @@ -211,7 +211,7 @@ private static BootloaderType GetDeviceType(ushort vendorId, ushort productId, u return BootloaderType.AtmelSamBa; } break; - case 0x0483: + case 0x0483: // STMicroelectronics if (productId == 0xDF11) { return BootloaderType.Stm32Dfu; @@ -223,7 +223,7 @@ private static BootloaderType GetDeviceType(ushort vendorId, ushort productId, u return BootloaderType.Caterina; } break; - case 0x16C0: + case 0x16C0: // Van Ooijen Technische Informatica switch (productId) { case 0x0478: @@ -236,7 +236,7 @@ private static BootloaderType GetDeviceType(ushort vendorId, ushort productId, u return BootloaderType.BootloadHid; } break; - case 0x1781: + case 0x1781: // MECANIQUE if (productId == 0x0C9F) { return BootloaderType.UsbTinyIsp; @@ -251,19 +251,19 @@ private static BootloaderType GetDeviceType(ushort vendorId, ushort productId, u return BootloaderType.Caterina; } break; - case 0x1C11: + case 0x1C11: // Input Club Inc. if (productId == 0xB007) { return BootloaderType.KiibohdDfu; } break; - case 0x1EAF: + case 0x1EAF: // Leaflabs if (productId == 0x0003) { return BootloaderType.Stm32Duino; } break; - case 0x1FFB: // Pololu Electronics + case 0x1FFB: // Pololu Corporation if (productId == 0x0101) // A-Star 32U4 { return BootloaderType.Caterina; @@ -278,7 +278,7 @@ private static BootloaderType GetDeviceType(ushort vendorId, ushort productId, u return BootloaderType.Caterina; } break; - case 0x239A: // Adafruit Industries LLC + case 0x239A: // Adafruit switch (productId) { case 0x000C: // Feather 32U4 @@ -287,7 +287,7 @@ private static BootloaderType GetDeviceType(ushort vendorId, ushort productId, u return BootloaderType.Caterina; } break; - case 0x314B: + case 0x314B: // Geehy Semiconductor Co. Ltd. if (productId == 0x0106) { return BootloaderType.Apm32Dfu;