From 3c73b497909ce5bacd16d23e54928a7f66544e09 Mon Sep 17 00:00:00 2001 From: Gerhard de Clercq <11624490+Gerharddc@users.noreply.github.com> Date: Mon, 12 May 2025 15:51:19 +0200 Subject: [embassy-usb-dfu] support function level WinUSB GUIDs This commit makes it possible to provide function level msos GUIDs to usb_dfu. This helps to ensure that composite DFU devices automatically get assigned the WinUSB driver on Windows. --- embassy-usb-dfu/src/application.rs | 16 +++++++++++++++- embassy-usb-dfu/src/dfu.rs | 16 +++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) (limited to 'embassy-usb-dfu') diff --git a/embassy-usb-dfu/src/application.rs b/embassy-usb-dfu/src/application.rs index 6ad07a78c..52a7ca951 100644 --- a/embassy-usb-dfu/src/application.rs +++ b/embassy-usb-dfu/src/application.rs @@ -2,7 +2,7 @@ use embassy_boot::BlockingFirmwareState; use embassy_time::{Duration, Instant}; use embassy_usb::control::{InResponse, OutResponse, Recipient, RequestType}; use embassy_usb::driver::Driver; -use embassy_usb::{Builder, Handler}; +use embassy_usb::{msos, Builder, Handler}; use embedded_storage::nor_flash::NorFlash; use crate::consts::{ @@ -130,8 +130,22 @@ pub fn usb_dfu<'d, D: Driver<'d>, MARK: DfuMarker, RST: Reset>( builder: &mut Builder<'d, D>, handler: &'d mut Control, timeout: Duration, + winusb_guids: Option<&'d [&str]>, ) { let mut func = builder.function(0x00, 0x00, 0x00); + if let Some(winusb_guids) = winusb_guids { + // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows. + // Otherwise users need to do this manually using a tool like Zadig. + // + // Adding them here on the function level appears to only work for compositive devices though. + // For non-composite devices they should be placed on the device level instead. + func.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); + func.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( + "DeviceInterfaceGUIDs", + msos::PropertyData::RegMultiSz(winusb_guids), + )); + } + let mut iface = func.interface(); let mut alt = iface.alt_setting(USB_CLASS_APPN_SPEC, APPN_SPEC_SUBCLASS_DFU, DFU_PROTOCOL_RT, None); let timeout = timeout.as_millis() as u16; diff --git a/embassy-usb-dfu/src/dfu.rs b/embassy-usb-dfu/src/dfu.rs index a98d6ab40..83feacaf8 100644 --- a/embassy-usb-dfu/src/dfu.rs +++ b/embassy-usb-dfu/src/dfu.rs @@ -1,7 +1,7 @@ use embassy_boot::{AlignedBuffer, BlockingFirmwareUpdater, FirmwareUpdaterError}; use embassy_usb::control::{InResponse, OutResponse, Recipient, RequestType}; use embassy_usb::driver::Driver; -use embassy_usb::{Builder, Handler}; +use embassy_usb::{msos, Builder, Handler}; use embedded_storage::nor_flash::{NorFlash, NorFlashErrorKind}; use crate::consts::{ @@ -186,8 +186,22 @@ impl<'d, DFU: NorFlash, STATE: NorFlash, RST: Reset, const BLOCK_SIZE: usize> Ha pub fn usb_dfu<'d, D: Driver<'d>, DFU: NorFlash, STATE: NorFlash, RST: Reset, const BLOCK_SIZE: usize>( builder: &mut Builder<'d, D>, handler: &'d mut Control<'d, DFU, STATE, RST, BLOCK_SIZE>, + winusb_guids: Option<&'d [&str]>, ) { let mut func = builder.function(USB_CLASS_APPN_SPEC, APPN_SPEC_SUBCLASS_DFU, DFU_PROTOCOL_DFU); + if let Some(winusb_guids) = winusb_guids { + // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows. + // Otherwise users need to do this manually using a tool like Zadig. + // + // Adding them here on the function level appears to only work for compositive devices though. + // For non-composite devices they should be placed on the device level instead. + func.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); + func.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( + "DeviceInterfaceGUIDs", + msos::PropertyData::RegMultiSz(winusb_guids), + )); + } + let mut iface = func.interface(); let mut alt = iface.alt_setting(USB_CLASS_APPN_SPEC, APPN_SPEC_SUBCLASS_DFU, DFU_PROTOCOL_DFU, None); alt.descriptor( -- cgit