Add Avalonia GUI front-end and packaging for CLI + GUI#21
Open
mahoshojoHCG wants to merge 26 commits into
Open
Add Avalonia GUI front-end and packaging for CLI + GUI#21mahoshojoHCG wants to merge 26 commits into
mahoshojoHCG wants to merge 26 commits into
Conversation
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Introduces QCEDL.GUI (Avalonia 12 + ReactiveUI) with Overview, Connection, Partitions, and Logs views driven by a shared EdlService. Refactors the CLI core so both front-ends can drive EdlManager: extracts EdlOptions as a POCO, promotes EdlManager / DeviceMode / StorageGeometry to public, and reworks Logging with an observable sink alongside the console sink. Ships a Claude-inspired custom theme (tokens + scratch ControlThemes + class variants), updates CLAUDE.md with the two-front-end architecture, and adds gui-todos.md as a living tracker. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Localized strings (en/zh-Hans/zh-Hant/ja) via a Localizer singleton and
{l:Localize} markup extension, with a Settings screen for runtime language
switching. FontTheme swaps the primary serif/sans/mono families to match
the active CJK script, and GuiSettings persists the chosen culture.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Implements Phase 1 `read-part` and all Phase 2 read/write/erase flows. Adds a shared `ConfirmDialog` with optional typed-string gating, a Sectors view replacing the placeholder, and an operations card on the Partitions view. Rows in the GPT table auto-populate the op fields on selection. All new strings are localized across en / zh-Hans / zh-Hant / ja. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move rawprogram, dump-rawprogram, and provision orchestration out of the CLI command files into Core/*Runner static classes, then back the RawProgram and Advanced GUI views with them (replacing placeholders). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the view-layer Click handlers and StorageProvider/window lookups with view-model-owned ReactiveCommands and ReactiveUI Interactions, so VMs no longer depend on Avalonia.Window owners for confirmations or pickers. Adds ReactiveUI.SourceGenerators to collapse RaiseAndSetIfChanged boilerplate and command wiring, plus a reflection-based LogCommandErrors helper on ViewModelBase so unhandled command exceptions always reach the Logs view. Also adds FindDeviceMacOSSerial so the serial backend auto-discovers /dev/tty.usbserial-* on macOS instead of requiring --serial-device. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 4 polish: extend GuiSettings to carry log level + last-used Connection options (loader, VID/PID, memory, backend) via a shared Current model; surface a Log-level picker in Settings; wire Window.KeyBindings so nav shortcuts work on Windows/Linux, not just the macOS NativeMenu; thicken the Focus Blue ring on buttons and nav items for keyboard discoverability. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EdlManager, EdlOptions, runners, storage backends, and the shared Logging/Helpers now live in QCEDL.NET so the GUI references only the protocol library. QCEDL.CLI is now just command wiring, and the GUI's dependency on QCEDL.CLI is gone. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Cover EdlManager.EnumerateDevices, DeviceCandidate, EdlOptions.UsbDeviceId, and the DeviceChooserDialog / RegisterPickDevice bridge so future agents know the GUI has a session-safe discovery path and a canonical picker surface for multi-device scenarios. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add `DeviceCandidate` and static `EdlManager.EnumerateDevices(EdlOptions)` with non-destructive per-OS backends (Linux sysfs, Windows SetupDi, macOS /dev/tty.usbserial-*, libusb). - Extend `EdlOptions` with `UsbDeviceId` (`usb:vid_XXXX,pid_YYYY,bus_N, addr_M`) and teach `QualcommSerial.FindLibUsbDevice` to filter by bus+addr so multiple EDL devices can be disambiguated. - Wire `EdlService.EnumerateDevicesAsync`, a `DeviceChooserDialog` / `DeviceChooserDialogViewModel`, and a `DialogBridges.RegisterPickDevice` interaction. Connection view gains a Devices card (Scan + list + Clear) and auto-prompts from Connect/Probe when >1 candidate matches. - Fix `EdlService.CloneOptions` silently dropping `Backend`, `SerialDevicePath`, and `UsbDeviceId` on session rebuilds. - Document the auto-prompt behavior and CloneOptions invariant in CLAUDE.md; update gui-todos.md tracker. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Split semantic brushes in Tokens.axaml into Avalonia ThemeDictionaries so DynamicResource lookups re-resolve when RequestedThemeVariant changes — accents and always-on-dark text stay outside the dictionaries. ThemeService owns the app-wide variant and Settings persists the choice so first paint matches the user's preference without flicker. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ice access macOS routes every QualcommSerial session through a new edl-ng-helper process spawned under osascript's administrator-privileges prompt, so the GUI and CLI no longer need to be launched with sudo. Linux ships a udev rule granting MODE=0660, GROUP=wheel on Qualcomm EDL USB/tty nodes; users in the wheel group open the device directly. SMAppService support is stubbed behind the same launcher interface for future signed-bundle work. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rework the CI pipeline to ship both front-ends across every supported RID and replace dotnet-deb/dotnet-rpm with from-scratch packaging so we own the file layout, udev-rule placement, and post-install hooks. GUI is self-contained non-AOT; the macOS helper is AOT/trimmed/single-file and overwrites the GUI's content copy inside the .app bundle. Signing + notarization degrade gracefully to ad-hoc when Apple secrets are absent. Version is now sourced once from Directory.Build.props (<EdlNgVersion>) — MSBuild inherits <Version> for every csproj and the workflow greps the same file for package naming. Adds a Debian-variant udev rule (TAG+="uaccess", GROUP="plugdev") since wheel doesn't exist on Debian/Ubuntu. Ships a branded icon set (SVG source + rasterized PNG / ICO / ICNS) wired into the Windows exe, Avalonia window, macOS bundle, and Linux hicolor theme. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Collaborator
Author
Gate the Developer ID import, codesign, and notarize steps on push-to-main so PRs don't need Apple secrets and still exercise .app/.dmg packaging. Move the helper's PublishAot/Trimmed/SingleFile properties into QCEDL.Helper.csproj so they don't propagate as global MSBuild properties into the analyzer ProjectReference (netstandard2.0), which trips NETSDK1207 under the .NET 10 SDK on the runner. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a new Avalonia-based desktop GUI (qcedl-gui) and supporting packaging/elevation infrastructure, while refactoring shared orchestration into QCEDL.NET so both CLI and GUI share the same runner/protocol surface.
Changes:
- Introduces
QCEDL.GUI(Avalonia 12) +QCEDL.Helper(privileged helper) and wires them into the solution/build. - Extracts/introduces shared core options + runners + transport elevation plumbing in
QCEDL.NET. - Adds cross-distro packaging assets (deb/rpm/Arch/Nix, macOS app/dmg), udev rules, icons, and release workflow flattening.
Reviewed changes
Copilot reviewed 143 out of 156 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| resources/udev/99-edl-ng.rules | Adds wheel-based udev rule for USB + tty nodes. |
| resources/udev/99-edl-ng.debian.rules | Adds Debian/Ubuntu udev rule variant (uaccess + plugdev). |
| resources/icons/generate.sh | Script to regenerate icon set from the SVG source. |
| resources/icons/edl-ng.svg | Canonical SVG icon source. |
| resources/icons/edl-ng-16.png | Pre-rendered icon asset. |
| resources/icons/edl-ng-32.png | Pre-rendered icon asset. |
| resources/icons/edl-ng-48.png | Pre-rendered icon asset. |
| resources/icons/edl-ng-64.png | Pre-rendered icon asset. |
| resources/icons/edl-ng-128.png | Pre-rendered icon asset. |
| pkgs/edl-ng/default.nix | Installs udev rules in Nix derivation output. |
| packaging/rpm/qcedl-gui.spec | RPM spec for GUI packaging (desktop entry, icons, udev). |
| packaging/rpm/edl-ng.spec | RPM spec for CLI packaging (binary + udev). |
| packaging/rpm/build-rpm.sh | Script to build rpms from prebuilt publish trees. |
| packaging/macos/build-dmg.sh | Script to wrap an app bundle into a dmg. |
| packaging/macos/build-app.sh | Script to assemble a macOS .app from publish output. |
| packaging/deb/build-gui-deb.sh | Script to build GUI .deb (tree install + desktop + icons + udev). |
| packaging/deb/build-cli-deb.sh | Script to build CLI .deb (binary + udev). |
| packaging/arch/gui/qcedl-gui.desktop | Desktop entry for GUI on Linux. |
| packaging/arch/gui/PKGBUILD | Arch PKGBUILD for GUI using CI-staged publish tree. |
| packaging/arch/cli/PKGBUILD | Arch PKGBUILD for CLI using CI-staged publish tree. |
| edl-ng.slnx | Adds GUI + helper projects to solution. |
| docs/linux-udev.md | Documents Linux udev installation/verification for device access. |
| README.md | Updates readme to reflect CLI+GUI, features, and platform notes. |
| QCEDL.NET/Transport/HelperClient.cs | Adds GUI-side client for privileged helper protocol. |
| QCEDL.NET/Transport/HelperChannel.cs | Adds helper frame codec + request/response payload helpers. |
| QCEDL.NET/Transport/Elevation/MacSmAppServiceLauncher.cs | Adds placeholder SMAppService-based launcher (currently unsupported). |
| QCEDL.NET/Transport/Elevation/MacOsAscriptLauncher.cs | Adds osascript-based elevation + Unix socket transport for macOS. |
| QCEDL.NET/Transport/Elevation/IHelperLauncher.cs | Defines helper launcher abstraction and session DTO. |
| QCEDL.NET/Transport/Elevation/HelperLauncher.cs | Chooses best available elevation launcher and resolves helper path. |
| QCEDL.NET/Transport/Elevation/ElevationPolicy.cs | Adds policy/probe logic for when elevation/udev is needed. |
| QCEDL.NET/QCEDL.NET.csproj | Adds InternalsVisibleTo and Vanara dependency for shared code. |
| QCEDL.NET/Helpers/ProgressReporter.cs | Moves helper into shared namespace. |
| QCEDL.NET/Helpers/Logging.cs | Introduces shared logging/event sink for CLI + GUI. |
| QCEDL.NET/Helpers/ImageSizeParser.cs | Moves helper into shared namespace. |
| QCEDL.NET/Helpers/AlignmentHelper.cs | Moves helper into shared namespace. |
| QCEDL.NET/Core/StorageGeometry.cs | Introduces shared storage geometry DTO. |
| QCEDL.NET/Core/RadxaWoSDeviceManager.cs | Moves Radxa WoS backend into shared namespace/deps. |
| QCEDL.NET/Core/ProvisionRunner.cs | Extracts provisioning flow into shared runner. |
| QCEDL.NET/Core/HostDeviceManager.cs | Moves host-device backend into shared namespace; adjusts P/Invoke attributes. |
| QCEDL.NET/Core/EdlOptions.cs | Adds GUI-friendly POCO options surface shared with CLI. |
| QCEDL.NET/Core/DeviceMode.cs | Promotes device mode enum to shared/public. |
| QCEDL.NET/Core/DeviceCandidate.cs | Adds device enumeration candidate model for chooser/pinning. |
| QCEDL.NET/Core/BlockDeviceManagerBase.cs | Moves base class into shared namespace. |
| QCEDL.Helper/QCEDL.Helper.csproj | New privileged helper project (AOT/single-file publish settings). |
| QCEDL.Helper/Program.cs | Helper entrypoint using Unix socket + frame server. |
| QCEDL.Helper/FrameServer.cs | Implements server-side frame dispatch to QualcommSerial + log forwarding. |
| QCEDL.GUI/macOS/entitlements.plist | Adds macOS entitlements for GUI app bundle signing. |
| QCEDL.GUI/macOS/Info.plist | Adds macOS Info.plist template for app bundle. |
| QCEDL.GUI/app.manifest | Adds Windows DPI awareness manifest. |
| QCEDL.GUI/Views/SettingsView.axaml.cs | GUI settings view code-behind. |
| QCEDL.GUI/Views/SettingsView.axaml | GUI settings view layout (language/theme/log-level). |
| QCEDL.GUI/Views/SectorsView.axaml.cs | GUI sectors view code-behind + dialog hookups. |
| QCEDL.GUI/Views/SectorsView.axaml | GUI sectors view layout + progress UI. |
| QCEDL.GUI/Views/RawProgramView.axaml.cs | GUI rawprogram view code-behind + dialog hookups. |
| QCEDL.GUI/Views/RawProgramView.axaml | GUI rawprogram exec/dump view layout. |
| QCEDL.GUI/Views/PlaceholderView.axaml.cs | Placeholder view code-behind. |
| QCEDL.GUI/Views/PlaceholderView.axaml | Placeholder view layout. |
| QCEDL.GUI/Views/PartitionsView.axaml.cs | GUI partitions view code-behind + dialog hookups. |
| QCEDL.GUI/Views/PartitionsView.axaml | GUI partitions view layout + ops panel. |
| QCEDL.GUI/Views/OverviewView.axaml.cs | Overview view code-behind. |
| QCEDL.GUI/Views/OverviewView.axaml | Overview view layout. |
| QCEDL.GUI/Views/MainWindow.axaml.cs | Main window code-behind. |
| QCEDL.GUI/Views/MainWindow.axaml | Shell layout + navigation rail + native menus + keybindings. |
| QCEDL.GUI/Views/LogsView.axaml.cs | Logs view code-behind. |
| QCEDL.GUI/Views/LogsView.axaml | Logs view layout + scrolling log list. |
| QCEDL.GUI/Views/LicenseViewerDialog.axaml.cs | License viewer dialog code-behind. |
| QCEDL.GUI/Views/LicenseViewerDialog.axaml | License viewer dialog layout. |
| QCEDL.GUI/Views/DeviceChooserDialog.axaml.cs | Device chooser dialog logic. |
| QCEDL.GUI/Views/DeviceChooserDialog.axaml | Device chooser dialog layout. |
| QCEDL.GUI/Views/ConnectionView.axaml.cs | Connection view code-behind + dialog hookups. |
| QCEDL.GUI/Views/ConnectionView.axaml | Connection view layout (scan/select/connect + options). |
| QCEDL.GUI/Views/ConfirmDialog.axaml.cs | Confirm dialog logic (typed confirmation + optional link). |
| QCEDL.GUI/Views/ConfirmDialog.axaml | Confirm dialog layout. |
| QCEDL.GUI/Views/AdvancedView.axaml.cs | Advanced view code-behind + dialog hookups. |
| QCEDL.GUI/Views/AdvancedView.axaml | Advanced view layout (provision/upload/reset). |
| QCEDL.GUI/Views/AboutDialog.axaml.cs | About dialog logic + license viewer launch. |
| QCEDL.GUI/Views/AboutDialog.axaml | About dialog layout + dependency list. |
| QCEDL.GUI/ViewModels/ViewModelBase.cs | Adds common VM base with command error logging. |
| QCEDL.GUI/ViewModels/ShellViewModel.cs | Adds shell navigation view model and navigation items. |
| QCEDL.GUI/ViewModels/SettingsViewModel.cs | Settings view model (culture/theme/log persistence). |
| QCEDL.GUI/ViewModels/OverviewViewModel.cs | Overview view model reacting to connection/session state. |
| QCEDL.GUI/ViewModels/LogsViewModel.cs | Logs view model wrapper around observable sink. |
| QCEDL.GUI/ViewModels/LicenseViewerViewModel.cs | License viewer VM. |
| QCEDL.GUI/ViewModels/DeviceChooserDialogViewModel.cs | Device chooser dialog VM. |
| QCEDL.GUI/ViewModels/ConfirmDialogViewModel.cs | Confirm dialog VM with typed confirmation gating. |
| QCEDL.GUI/ViewModels/AdvancedViewModel.cs | Advanced operations VM (provision/upload/reset). |
| QCEDL.GUI/ViewModels/AboutDialogViewModel.cs | About dialog VM (dependency/license metadata). |
| QCEDL.GUI/Services/ThemeService.cs | Central theme switching service (System/Light/Dark). |
| QCEDL.GUI/Services/ObservableLogSink.cs | UI-thread log sink with bounded entry buffer. |
| QCEDL.GUI/Services/Localizer.cs | resx-based localization service with live culture switching. |
| QCEDL.GUI/Services/LicenseTexts.cs | Loads embedded license texts from Avalonia resources. |
| QCEDL.GUI/Services/GuiSettings.cs | JSON-persisted GUI settings (culture/theme/log + connection defaults). |
| QCEDL.GUI/Services/FontTheme.cs | Culture-aware font resource swapping for CJK/Latin. |
| QCEDL.GUI/Services/EdlService.cs | GUI service wrapper over EdlManager with operation serialization. |
| QCEDL.GUI/Services/DialogInteractions.cs | Interaction DTOs + bridges to Avalonia pickers/dialogs. |
| QCEDL.GUI/Services/AppCommands.cs | Global app commands (docs/about) for menus/keybindings. |
| QCEDL.GUI/QCEDL.GUI.csproj | New GUI project definition + packages + embeds licenses + helper content. |
| QCEDL.GUI/Program.cs | Avalonia app bootstrap. |
| QCEDL.GUI/Markup/LocalizeExtension.cs | XAML markup extension for localized strings. |
| QCEDL.GUI/Markup/AppThemeDisplayConverter.cs | Localized display converter for theme enum values. |
| QCEDL.GUI/Assets/Licenses/vanara.txt | Bundled third-party license text. |
| QCEDL.GUI/Assets/Licenses/reactiveui.txt | Bundled third-party license text. |
| QCEDL.GUI/Assets/Licenses/qcedl-net.txt | Bundled third-party license text. |
| QCEDL.GUI/Assets/Licenses/libusbdotnet.txt | Bundled third-party license text. |
| QCEDL.GUI/Assets/Licenses/inter.txt | Bundled third-party license text. |
| QCEDL.GUI/Assets/Licenses/dotnet-runtime.txt | Bundled third-party license text. |
| QCEDL.GUI/Assets/Licenses/avalonia.txt | Bundled third-party license text. |
| QCEDL.GUI/App.axaml.cs | App init: applies persisted culture/theme, wires log sink, creates shell. |
| QCEDL.GUI/App.axaml | App-level styles + native menu entry. |
| QCEDL.CLI/QCEDL.CLI.csproj | Removes per-project version; adds app icon; relies on shared versioning. |
| QCEDL.CLI/Program.cs | Switches CLI helpers usage to shared helper namespace. |
| QCEDL.CLI/Helpers/Logging.cs | Removes CLI-local logging (now shared in QCEDL.NET). |
| QCEDL.CLI/Helpers/CommandExecutor.cs | Imports shared logging. |
| QCEDL.CLI/Core/StorageGeometry.cs | Removes CLI-local DTO (now shared). |
| QCEDL.CLI/Core/GlobalOptionsBinder.cs | Binds global CLI options into shared EdlOptions. |
| QCEDL.CLI/Commands/WriteSectorCommand.cs | Updates command handler signature to shared EdlOptions. |
| QCEDL.CLI/Commands/WritePartitionCommand.cs | Updates command handler signature to shared EdlOptions. |
| QCEDL.CLI/Commands/UploadLoaderCommand.cs | Updates command handler signature to shared EdlOptions. |
| QCEDL.CLI/Commands/ResetCommand.cs | Updates command handler signature to shared EdlOptions. |
| QCEDL.CLI/Commands/ReadSectorCommand.cs | Updates command handler signature to shared EdlOptions. |
| QCEDL.CLI/Commands/ReadPartitionCommand.cs | Updates command handler signature to shared EdlOptions. |
| QCEDL.CLI/Commands/ProvisionCommand.cs | Uses shared ProvisionRunner instead of inline provisioning logic. |
| QCEDL.CLI/Commands/PrintGptCommand.cs | Updates command handler signature to shared EdlOptions. |
| QCEDL.CLI/Commands/EraseSectorCommand.cs | Updates command handler signature to shared EdlOptions. |
| QCEDL.CLI/Commands/ErasePartitionCommand.cs | Updates command handler signature to shared EdlOptions. |
| QCEDL.Analyzer/EnumExtensionsGenerator.cs | Avoids nested enums; disambiguates hint name with namespace prefix. |
| Directory.Build.props | Centralizes version in EdlNgVersion and sets MSBuild Version. |
| .github/workflows/release.yml | Flattens artifacts under release/ and expands uploaded file set. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…nExclusiveAsync
The privileged helper runs as root, so an Open request with an arbitrary
path would let a compromised GUI coerce it into opening any file. Restrict
the Open path to /dev/{cu,tty}.usb* nodes, reject traversal and symlinks.
Add RunExclusiveAsync overloads that pass the CancellationToken into the
action so GUI runners can actually observe cancellation.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previously the direct-mode branch of ConnectionViewModel.ConnectAsync only updated status text and returned, so EdlService never constructed an EdlManager and IsConnected stayed false — leaving Partitions, Sectors, RawProgram, and Advanced disabled. Force manager construction via a no-op RunExclusiveAsync so StateChanged fires and IsDirectMode flips IsConnected to true. USB/Firehose path is untouched. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When a GUI user picked a specific EDL device via the chooser, that pin was encoded as usb:vid_*,pid_*,bus_N,addr_M. After UploadLoaderViaSahara the device re-enumerates and typically gets a new bus/addr, so the bus/addr filter in FindDeviceViaLibUsb failed and the fallback silently latched onto the first-match VID/PID device — potentially a different EDL device on the same host. Capture the USB iSerial descriptor on the initial open (pinned or not) and prefer it on subsequent FindDeviceViaLibUsb calls. When the captured iSerial can't be matched and more than one EDL device is visible, refuse to fall back to first-match and surface a clear error instead. The single-device happy path is preserved (fallback still works when only one candidate is present). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The standalone Upload Loader command was gated on WhenConnectedChanged, which only becomes true once the device has advanced to Firehose/direct mode — but the command body only succeeds while the device is still in Sahara (pre-loader). Result: the button was disabled in the only mode where it works and enabled where it was guaranteed to fail. Expose IsInSaharaMode + WhenSaharaModeChanged on EdlService (mirroring IsConnected / WhenConnectedChanged) and gate UploadLoaderCommand on a dedicated observable combining CanInteract with the Sahara signal. Provision and Reset keep their existing WhenConnectedChanged gating. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The CanExecute gate previously required a discovered candidate, but EdlManager already honours an explicit SerialDevicePath on EdlOptions. Widen the predicate to also accept a non-empty manual path (and keep the direct-mode bypass) so the manual serial-device textbox isn't a dead end. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
macOS exposes some adapters as /dev/tty.USBxxx; the Ordinal prefix check rejected them before the helper could open the device. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Treat "<?xm" (0x6D783F3C) on the Sahara endpoint after at least one image has been transferred as "programmer is up" and exit the loop. The prior code relied on a 1 s read timeout firing before the uploaded Firehose programmer's XML hello reached the host — a race main happened to win and current branch loses on macOS IOKit, producing the Unexpected Sahara command failure after DoneResponse. Also: - Route Auto backend to LibUsb on macOS too (not only Windows). The IOKit-backed /dev/tty.usbserial-* path needs root; libusb opens the USB interface directly without elevation. - Make ElevationPolicy.RequiresHelper backend-aware so LibUsb sessions on macOS bypass the privileged helper. - Drop the pre-open UsbDevice.TryOpen/Close iSerial read during enumeration — perturbed the 9008 device state on macOS and desynced the subsequent Sahara handshake. Capture iSerial from the already-open libusb handle via a new QualcommSerial.UsbSerialNumber property. - Store the resolved TransportBackend on EdlManager instead of overloading _deviceGuid as a backend flag. - Wire LibraryLogger.LogAction in the GUI so protocol-layer errors (Transfer crash, Pre-transfer validation failed, Unexpected Sahara command, etc.) surface in the Logs view instead of being silently dropped. - Document the Auto->LibUsb rule for macOS and the "never pre-open to read iSerial" invariant in CLAUDE.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Connection view now shows only a Probe button. Every form field (loader path, VID/PID, memory type, slot, direct-mode toggles, serial device path, backend, selected candidate) is merged into a single observable that projects the options onto EdlService and resets any live session so the next op re-opens with fresh options. Downstream VMs (Advanced, Partitions, Raw Program, Sectors) no longer gate their commands on WhenConnectedChanged / WhenSaharaModeChanged — EdlService now rebuilds the session on demand from the auto-projected options, so there is no "must click Connect first" UX. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Collaborator
Author
|
Verified E2E working with all GUI features. |
macOS access no longer requires a privileged sidecar — LibUsb opens the EDL interface through IOKit directly. Drops QCEDL.Helper, Transport/Elevation, HelperClient/HelperChannel, and all packaging / CI wiring that shipped the helper alongside qcedl-gui. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.









Summary
qcedl-gui) drivingEdlManagerdirectly, with localization (en/zh-Hans/zh-Hant/ja), dark mode, persisted settings, native menus, About + bundled license viewer, and a Claude-inspired theme written from scratch.EdlManager,EdlOptions,*Runnerflows, logging) fromQCEDL.CLIintoQCEDL.NETso both front-ends share one protocol/runner surface; add non-destructiveEnumerateDeviceswith bus/addr pinning and a device chooser.edl-ng-helper+ elevation launchers (macOS AppleScript/SMAppService) and Linux udev rules for unprivileged device access; hand-rolled deb/rpm/pacman/dmg packaging for CLI + GUI across platforms.Test plan
dotnet format --verify-no-changes --verbosity diagnosticdotnet build(solution)dotnet run --project QCEDL.GUI/QCEDL.GUI.csproj— connect, switch language/theme, run partitions/sectors/rawprogram/provision flowsprintgpt,read-part,rawprogram,provision,reset🤖 Generated with Claude Code