Skip to content

Add the Low-Latency Audio Driver Selector, a release build script and a preview installer - #43

Open
Pete Brown (Psychlist1972) wants to merge 3 commits into
mainfrom
preview-installer-and-driver-selector
Open

Pete Brown (Psychlist1972) wants to merge 3 commits into
mainfrom
preview-installer-and-driver-selector

Conversation

@Psychlist1972

Copy link
Copy Markdown
Collaborator

Add the Low-Latency Audio Driver Selector, a release build script and a preview installer

AI Generated Content. GitHub Copilot (Claude Opus 5.5) wrote the code in this pull request and this description, working for Pete Brown (Microsoft). Read the "What was tested" section before relying on any part of it.

Summary

This adds what a preview release needs around the driver and the ASIO driver:

  • Low-Latency Audio Driver Selector, a small WinUI 3 app (C++/WinRT) where a customer chooses which driver each USB Audio 2.0 device uses: the low-latency driver, the Windows USB Audio 2.0 driver, or the manufacturer's driver. It's the only way the low-latency driver gets onto a device, because the INF won't list any devices.
  • build\build-all.ps1, a release build: builds every project, stages and checks what ships, signs with a code signing certificate chosen by its thumbprint, makes the .cab files for attestation signing, and builds the installers. The existing build\build.ps1 is unchanged.
  • A WiX installer for x64 and one for Arm64. The bundle installs the Visual C++ runtime and the Windows App Runtime, then an .msi with the ASIO driver and its registration, the ASIO control panel, the Driver Selector, and the driver package. The existing src\installer is unchanged.

The driver supports USB Audio 2.0 only. The Driver Selector lists only USB Audio 2.0 devices, and never offers the low-latency driver for a USB Audio 1.0 device.

Every file in this pull request is new. No existing file changes.

How it works for a customer

  1. They run LowLatencyAudioSetup-<version>-<platform>.exe. It installs the runtimes and the .msi. The .msi adds the driver package to the Windows driver store but puts it on no device, so nothing changes yet.
  2. The installer's finish page offers to open the Driver Selector. It lists each USB Audio 2.0 device, the driver it uses now, and buttons for the other choices.
  3. They choose Use low-latency driver for a device. Their music apps can then use it through ASIO, as "USB ASIO".
  4. They can switch any device back at any time. Uninstalling moves every device on the low-latency driver back to the Windows driver and deletes the driver package.

On an upgrade, devices already on an older copy of the driver move to the new one by themselves, and older copies nothing uses are deleted.

What's in it

Folder What it is
src\driver-selector The Driver Selector app. See its README.
src\shared\driver-store Driver store code shared by the app and the installer: finds the driver's packages by INF name, and installs a driver from one INF on one device.
src\installers The installer: WiX package and bundle, a small C++ custom action DLL, the signing hooks, and Branding.wxi. See its README.
build\build-all.ps1, build\sign-files.ps1, build\version.json The release build, the signing script, and the version.
build\.gitignore Keeps the downloaded runtime installers and the release folder out of git.

What Yamaha needs to change before a release

The driver INF (src\uac2-driver\USBAudio2-ACX.inf)

  • Replace the model lines with one line that matches no real device. The Driver Selector installs the driver from a class driver list built from this one INF, the way Device Manager's Have disk does, so the INF doesn't need to list devices. Any ID that no device reports works, for example:

    [Standard.NT$ARCH$.10.0...22621]
    %USBAudio2-ACX.DeviceDesc%=USBAudio2-ACX_Device, USBAudio2-ACX\ChosenInDriverSelector

    Please confirm that InfVerif and attestation signing accept it.

  • Set the minimum Windows build in the models section to the real one. The driver uses ACX 1.1 and KMDF 1.33, which shipped in Windows 11, version 22H2 (build 22621). The INF currently says 16299. Only Windows 11 25h2 and later shall be supported.

  • Keep Provider the same in every release. The installer finds the copies older releases put in the driver store by INF file name and provider. If you want a different provider name, change it before the first release.

  • Raise DriverVer in every release. The installer and the Driver Selector compare it to decide which copy is newer.

  • Keep the INF file name USBAudio2-ACX.inf and the service name USBAudio2-ACX, or change them in src\driver-selector\SelectorConfig.h, src\installers\low-latency-audio-installer\package\Package.wxs (DriverInfName) and the top of build\build-all.ps1.

Today the INF puts the driver on the whole device for three Steinberg models (UR22, UR44C, IXO22). The Driver Selector always puts it on the audio interface (MI_xx) under Windows' composite driver. Please check that those three work that way. A device an older INF already put on the whole device shows up in the Driver Selector, which moves it to the audio interface.

src\installers\low-latency-audio-installer\Branding.wxi

Every value marked PLACEHOLDER: publisher, product name, install folder, Start menu folder and shortcut names, license and support links, and the minimum Windows build. The two upgrade codes are marked KEEP. If Yamaha ships its own release line, replace both with new GUIDs before the first release, and then never change them again.

The ASIO driver name and class ID there must match DRIVER_NAME_8b and IID_ASIO_DRIVER in src\uac2-asio\USBAsio.cpp: USB ASIO on x64 and USB ASIO (ARM64X) on Arm64.

Other placeholders

  • The app icon, src\driver-selector\Assets\AppIcon.ico, and the installer logo, src\installers\low-latency-audio-installer\bundle\logo.png.
  • The company and product name in the version resources: src\driver-selector\Resources.rc and src\installers\low-latency-audio-installer\custom-actions\Resources.rc.
  • The version, in build\version.json. Raise patch for every release that must upgrade an earlier one.

If Yamaha's open pull request changes these

  • The control panel's Windows App SDK version. The Driver Selector installs into the same folder and shares two files with the control panel, so its packages.config and the package imports in LowLatencyDriverSelector.vcxproj must match the control panel's exactly. build-all.ps1 stops if the shared files differ.
  • The control panel's resources. Both apps must keep their resources and compiled XAML in their own <exe name>.pri, and neither may produce a resources.pri. build-all.ps1 checks this too.
  • The output folders under src\vsfiles\out. build-all.ps1 stages from them.

Building and signing a release

PowerShell 7.2 or later, Visual Studio 2022 or later with the C++ desktop workload, the Windows SDK, the Windows Driver Kit for the driver, and the Steinberg ASIO SDK in src\uac2-asio\asio for the ASIO driver. WiX comes from NuGet. The build downloads the two runtime installers from Microsoft and checks Microsoft signed them.

Signing uses a certificate from your certificate store, chosen by its thumbprint. An EV certificate on a hardware token works: signtool asks for the token's password. Attestation signing needs the EV certificate registered in Partner Center.

cd build

# 1. Build the driver and the .cab files to submit for attestation signing
.\build-all.ps1 -Target Driver,DriverCab -Sign -CertificateThumbprint <thumbprint>

# 2. Submit each .cab in build\release\<version>\attestation in Partner Center. Unzip the
#    signed results into one folder; each unzips into a folder named for its platform.

# 3. Build everything else and the installers around the Microsoft-signed driver
.\build-all.ps1 -Target Asio,Apps,Stage,Setup,Release -Sign -CertificateThumbprint <thumbprint> -AttestedDriverPath <folder>

The installers and symbols land in build\release\<version>. A signed build stops if the staged driver isn't signed by Microsoft. src\installers\README.md has the details, including how to try the signing steps with a throwaway test certificate.

Attestation-signed drivers load on Windows 10 and Windows 11 desktop editions only.

What was tested

On one Windows 11 PC, x64, without administrator rights:

  • The Driver Selector, the custom action DLL and the WiX projects build for x64 and Arm64, with no warnings.
  • build-all.ps1 -Target Apps,Stage,Setup,Release for both platforms, with stand-in files for the driver and the ASIO DLL, because the WDK and the ASIO SDK weren't available. The .msi tables (files, registry, custom actions, sequence, launch conditions, upgrades) and the bundle manifest (chain, conditions, launch target) were read back and match this description.
  • Signing end to end with a throwaway self-signed certificate: the staged binaries, the custom action DLL (including the copy inside the .msi), the .msi and the bundle were signed and timestamped, and Microsoft's own files kept their signatures.
  • The DriverCab target, with stand-in files: each .cab holds <platform>\USBAudio2-ACX.inf, .sys and .pdb.
  • The Driver Selector started read-only and listed the one USB Audio 2.0 device on the PC, on the Windows driver, with the right buttons turned off.
  • Reading configuration descriptors through the hub, which the Driver Selector uses to tell USB Audio 2.0 from 1.0 for devices a manufacturer's driver has taken over: it worked without administrator rights on all 17 composite devices on the PC. It found the USB Audio 2.0 device, and correctly left out a webcam whose microphone is USB Audio 1.0 and two USB MIDI interfaces.

What was not tested

  • No install, upgrade or uninstall was run, and no driver was changed on any device. Those need administrator rights and a signed driver. The core of the Driver Selector, installing the driver from a class driver list with DiInstallDevice, has not run yet.
  • The driver and the ASIO DLL weren't built.
  • Nothing ran on Arm64, and nothing ran with Smart App Control turned on.
  • Attestation submission and signing with an EV token.
  • Silent installs of the Windows App Runtime (--quiet) and their exit codes.

Suggested test pass

  1. Clean Windows 11 22H2 or later, x64 and Arm64: install, then check pnputil /enum-drivers lists USBAudio2-ACX.inf and no device changed driver.
  2. A class-compliant USB Audio 2.0 device on the Windows driver: switch to the low-latency driver, play and record through ASIO in a DAW, open the control panel from the DAW, switch back.
  3. A device with its manufacturer's driver for the whole device: switch to the low-latency driver, then back to the manufacturer's driver.
  4. On Arm64: an Arm64 DAW and an x64 DAW both find "USB ASIO (ARM64X)".
  5. Install release N, put a device on the low-latency driver, install release N+1: the device moves to the new driver, and the old package is gone.
  6. Uninstall: the device is back on the Windows driver, and pnputil /enum-drivers no longer lists the package.
  7. Start the Driver Selector and decline the administrator prompt: it shows the read-only banner.
  8. Repeat an install with Smart App Control on.

Known limitations

  • The installer has no rollback for the driver store. If an install fails after the package was added, run the installer again and then uninstall.
  • Uninstalling moves devices to the Windows driver, not back to a manufacturer's driver.
  • A device without a serial number plugged into a different USB port shows up as a new device on the Windows driver. Choose the low-latency driver for it again.
  • Windows Update can replace the low-latency driver if it offers a driver that names the device.
  • A device that offers USB Audio 2.0 only in its second configuration isn't listed, because Windows' composite driver uses the first one.
  • There is no 32-bit ASIO driver, so 32-bit music apps don't see it.

…iew installer

- src/driver-selector: a WinUI 3 app where a customer chooses the driver each USB Audio 2.0 device uses: the low-latency driver, the Windows USB Audio 2.0 driver, or the manufacturer's driver. USB Audio 1.0 devices aren't listed, because the driver doesn't support them.
- src/shared/driver-store: driver store code shared by the app and the installer.
- src/installers: WiX package and bundle for x64 and Arm64 with the Visual C++ runtime, the Windows App Runtime, the ASIO driver and its registration, the ASIO control panel, the Driver Selector and the driver package. C++ custom actions add the driver package to the driver store and remove it. Branding.wxi holds every value a release partner sets.
- build/build-all.ps1, sign-files.ps1, version.json: a release build that signs with a certificate chosen by thumbprint and makes the .cab files for attestation signing. build/build.ps1 and src/installer are unchanged.

No existing file changes. Not yet tested on hardware: no install, uninstall or driver change has run.
@ymh-yasuto-kaida

Copy link
Copy Markdown
Collaborator

Pete Brown (@Psychlist1972)

I confirmed that clicking “Use low-latency driver” in LowLatencyDriverSelector.exe fails to switch the driver and displays the following message:

“The driver wasn't changed. Windows couldn't install the driver (error 0x00000490). Element not found.”

In DriverStore.cpp, InstallDriverFromInf uses EqualsNoCase to compare the INF filenames recorded in detail.InfFileName and expectedInfName. However, detail.InfFileName contains oemX.inf, while expectedInfName contains usbaudio2-acx.inf. Since the filenames do not match, InstallDriverFromInf returns ERROR_NOT_FOUND, causing the driver switch to fail.

if (!GetDriverNodeDetail(set.Get(), device, driver, detail) ||
!EqualsNoCase(FileNameOnly(detail.InfFileName), expectedInfName))
{
continue;
}

@ymh-takashi-ito

Copy link
Copy Markdown
Collaborator

Pete Brown (@Psychlist1972) Yasuto Kaida (@ymh-yasuto-kaida)
As Yasuto pointed out, it seems that the Driver Selector won't work without the proposed fix. I've asked Yasuto to prepare the fix and decide on the placeholder text, so he'll submit the changes as suggested changes.

One additional request: I'd like to change the ASIO driver name from "USB ASIO" to "USBAudio2-ACX ASIO". The current name makes it difficult for users who have multiple ASIO drivers installed to identify the correct driver.

I'll approve the PR once these changes are incorporated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants