Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results


Before Posting...

Please check out the Community Guidelines in the Announcements and Administration Category.

More Info on Driver Writing and Debugging

The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.

Check out The OSR Learning Library at:

Isochronous endpoints MSFT UDE

bojan_janjicbojan_janjic Member Posts: 6
edited January 2022 in NTDEV

I am writing USB device emulator using Microsoft Usb Device Emulation framework.

So far I have implemented support for interrupt and bulk transfers, but isochronous transfers just do not work.

Driver sets up dynamic endpoints (UdecxUsbDeviceInitSetEndpointsType is called with UdecxEndpointTypeDynamic). So when virtual USB device is plugged (UdecxUsbDevicePlugIn), UDE framework calls callback for endpoint creation. There I create and associate queue with endpoint:

Here is a part of the code:
WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchSequential);
queueConfig.EvtIoInternalDeviceControl = OnTestIoInternalControl;
queueConfig.EvtIoCanceledOnQueue = OnTestCancelled;
queueConfig.EvtIoDefault = OnTestDefault;
queueConfig.EvtIoDeviceControl = OnTestIoControl;
queueConfig.EvtIoRead = OnTestRead;
queueConfig.EvtIoResume = OnTestResume;
queueConfig.EvtIoStop = OnTestStop;
queueConfig.EvtIoWrite = OnTestWrite;

WdfIoQueueCreate(hubDevice, &queueConfig, &queueAttributes, &queue);


UdecxUsbEndpointCreate(&endpointInit, &endpointAttributes, &udecxEndpoint);
UdecxUsbEndpointSetWdfIoQueue(udecxEndpoint, queue);

Note: I have just extracted part of the code, to make this post as short as possible

For bulk and interrupt endpoints it works fine, but for isochronous endpoint no "Test" callbacks are called. From log I can see that UDE has created endpoint and queue. USBVIEW shows opened pipe for isochronous endpoint, but when I try to play some music (tested virtual USB is audio device) it just does not trigger any callbacks that I could use to transfer data.

Does anybody know is isochronous transfers supported at all by Microsoft UDE?
If so, is there any additional setup required to make this work?


  • Benjamin_HöglingerBenjamin_Höglinger Member - All Emails Posts: 20

    Yes, UDE supports isochronous transfers but you need to be careful of certain pitfalls with the descriptors. Can you post your Configuration Descriptor here?

  • Andreas_GraefeAndreas_Graefe Member Posts: 5

    (Sorry for double or triple posting, somehow my post was deleted when I tried to edit)

    I have a similar issue with an emulated audio device. Communication with default control endpoint is OK, but the ISO endpoint's callback is only called once, then never again. Looks like something is blocking the queue, but I have no idea what.

    Here is the configuration descriptor I use. This should be a simple stereo USB speaker with 16bit / 48 kHz plus volume and mute controls.

    // Configuration Descriptor Type
    0x9,                              // Descriptor Size
    USB_CONFIGURATION_DESCRIPTOR_TYPE, // Configuration Descriptor Type
    0x76, 0x00,                        // Length of this descriptor and all sub descriptors
    0x02,                              // Number of interfaces
    0x01,                              // Configuration number
    0x00,                              // Configuration string index
    0xA0,                              // Config characteristics - bus powered
    0x32,                              // Max power consumption of device (in 2mA unit) : 0 ma
    // Interface association descriptor
    0x08,                                      // Descriptor size
    USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE, // Descriptor Type (Interface Association)
    0x00,                                      // bFirstInterface (number of first interface of the collection)
    0x02,                                      // bInterfaceCount (number of interfaces in the collection)
    USB_DEVICE_CLASS_AUDIO,                    // bFunctionClass (Audio)
    0x01,                                      // bFunctionSubclass (Audio)
    0x00,                                      // bFunctionProtocol (None)
    0x00,                                      // iFunction
    // Audio Interface descriptor (Control)
    0x09,                                     // Descriptor size
    USB_INTERFACE_DESCRIPTOR_TYPE,            // Descriptor type (Interface descriptor)
    0x00,                                     // bInterfaceNumber
    0x00,                                     // bAlternateSetting
    0x00,                                     // bNumEndpoints
    USB_DEVICE_CLASS_AUDIO,                   // bInterfaceClass (Audio)
    0x01,                                     // bInterfaceSubClass (Control)
    0x00,                                     // bInterfaceProtocol 
    0x00,                                     // iInterface
    // AudioControl Interface Descriptor (Header)
    0x09,                                     // Descriptor size
    0x24,                                     // bDescriptorType (CS Interface)
    0x01,                                     // bDescriptorSubType (HEADER)
    0x00, 0x01,                               // bdcADC
    0x28, 0x00,                               // wTotalLength
    0x01,                                     // bInCollection
    0x01,                                     // baInterfaceNr
    // AudioControl Interface Descriptor (Input Terminal)
    0x0C,                                     // Descriptor size
    0x24,                                     // bDescriptorType (CS Interface)
    0x02,                                     // bDescriptorSubType (Input Terminal)
    0x01,                                     // bTerminalID
    0x01, 0x01,                               // wTerminalType (USB Streaming)
    0x00,                                     // bAssocTerminal
    0x02,                                     // bNrChannels
    0x03, 0x00,                               // wChannelConfig
    0x00,                                     // iChannelNames
    0x00,                                     // iTerminal
    // AudioControl Interface Descriptor (Feature Unit)
    0x0A,                                     // Descriptor size
    0x24,                                     // bDescriptorType (CS Interface)
    0x06,                                     // bDescriptorSubType (Feature Unit)
    0x02,                                     // bUnitID
    0x01,                                     // bSourceID
    0x01,                                     // bControlSize
    0x03,                                     // bmaControls (Mute, Volume)
    0x00,                                     // bmaControls (1)
    0x00,                                     // bmaControls (2)
    0x00,                                     // iFeature
    // AudioControl Interface Descriptor (Output Terminal)
    0x09,                                     // Descriptor size
    0x24,                                     // bDescriptorType (Class specific interface)
    0x03,                                     // bDescriptorSubType (Output Terminal)
    0x03,                                     // bTerminalID
    0x01, 0x03,                               // wTerminalType (Speaker)
    0x00,                                     // bAssocTerminal
    0x02,                                     // bSourceID
    0x00,                                     // iTerminal
    // Audio Interface  descriptor (Streaming)
    0x9,                                      // Descriptor size
    USB_INTERFACE_DESCRIPTOR_TYPE,            // Interface Association Descriptor Type
    0x01,                                     // bInterfaceNumber
    0x00,                                     // bAlternateSetting
    0x00,                                     // bNumEndpoints
    0x01,                                     // bInterfaceClass (Audio)
    0x02,                                     // bInterfaceSubClass (Streaming)
    0x00,                                     // bInterfaceProtocol 
    0x00,                                     // iInterface
    // Audio Interface  descriptor (Streaming)
    0x9,                                      // Descriptor size
    USB_INTERFACE_DESCRIPTOR_TYPE,            // Interface Association Descriptor Type
    0x01,                                     // bInterfaceNumber
    0x01,                                     // bAlternateSetting
    0x01,                                     // bNumEndpoints
    0x01,                                     // bInterfaceClass (Audio)
    0x02,                                     // bInterfaceSubClass (Streaming)
    0x00,                                     // bInterfaceProtocol 
    0x00,                                     // iInterface
    // Audio Streaming interface descriptor
    0x07,                                     // Descriptor size
    0x24,                                     // Descriptor type 
    0x1,                                      // bDescriptorSubType
    0x1,                                      // bTerminalLink
    0x0,                                      // bDelay
    0x01, 0x00,                               // wFormatTag (PCM)
    // Audio Streaming interface descriptor
    0x0B,                                      // Descriptor size
    0x24,                                      // Descriptor type 
    0x02,                                      // Descriptor subtype (FORMAT_TYPE)
    0x01,                                      // bFormatType
    0x02,                                      // bNrChannels
    0x02,                                      // bSubFrameSize
    0x10,                                      // bBitResolution (16)
    0x01,                                      // bSamFreqType
    0x80, 0xBB, 0x00,                          // tSamFreq 48000
    // Endpoint Descriptor :
    0x9,                                       // Descriptor size
    USB_ENDPOINT_DESCRIPTOR_TYPE,              // Descriptor type (endpoint)
    0x01,                   // Endpoint address
    0x9,                                       // bmAttributes (Iso, Adaptive, Data)
    0xc0, 0x00,                                // wMaxPacketSize (192 bytes)
    0x4,                                       // bInterval (8 microframes = 1 millisecond)
    0x0,                                       // bRefresh
    0x0,                                       // bSynchAddress
    // AudioStreaming Endpoint descriptor
    0x7,                                       // bLength
    0x25,                                      // bDescriptorType
    0x1,                                       // bDescriptorSubType (EP General)
    0x00,                                      // bmAttributes
    0x0,                                       // bLockDelayUnits
    0x00, 0x00                                 // wLockDelay
  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,446

    How are you testing this? In battle, using a live audio app?

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • bojan_janjicbojan_janjic Member Posts: 6

    Thanks @Andreas_Graefe , I will try with hardcoded descriptor - just to see what happens.

    Have you used static or dynamic endpoints?

    For my project: I am doing USB forwarding. So I get configuration descriptor of remote device - I have double check - it is correct configuration. Basically when I "forward" device with bulk and interrupt endpoints, everything works fine. Just device with isochronous endpoints does not trigger any callbacks (to perform USB transfers). So I thought I am missing something for isochronous transfers.

  • Benjamin_HöglingerBenjamin_Höglinger Member - All Emails Posts: 20

    Are you using UsbFullSpeed or UsbHighSpeed? If using UsbFullSpeed, try switching to UsbHighSpeed instead and retry.

  • bojan_janjicbojan_janjic Member Posts: 6

    @Benjamin_Höglinger I am using UdecxUsbHighSpeed, but I will try another values just to see will it make any difference.

  • Andreas_GraefeAndreas_Graefe Member Posts: 5

    @Tim_Roberts: I'm testing it "in battle" (nice term btw).
    I also looked into manually creating URBs and sending it to the device via the WinUSB API (following this guide but I wasn't able to open the device from my test application. As far as I understand, this is because the device is already "in use" by Windows' class audio driver, but I didn't find a way to work around this.

  • Andreas_GraefeAndreas_Graefe Member Posts: 5

    @bojan_janjic, @Benjamin_Höglinger

    Regarding the speed: I tried both UsbFullSpeed and UsbHighSpeed, made no difference.

    Regarding static and dynamic endpoints: I started with this UDE sample, which uses static endpoints and modified it to use the descriptor posted above, then I switched to dynamic endpoints.
    I did that because I learned that the EvtUsbDeviceEndpointsConfigure callback (which handles the altsettings requests for an audio interface) is only called when dynamic endpoints are used.

    Now I see the EvtUsbDeviceEndpointsConfigure callback called with setting my audio interfaces' altsetting to 0 (which means audio playback is stopped), but it never seems to be set to 1 when I try to play something.

  • bojan_janjicbojan_janjic Member Posts: 6

    @Andreas_Graefe for WinUSB:
    Yes Windows blocks lot of devices: has own services that use device. So to access device you will need to do it from kernel - I did write a filter driver to make it work.

    For EvtUsbDeviceEndpointsConfigure:
    I have noticed that it does not trigger correctly alternate setting change - even found a Github project where somebody else had similar issue and was making a workaround. So I will make a workaround for my project to deal with alternate setting change.

    However I do receive EvtUsbDeviceEndpointsConfigure when alternate setting is changed (to choose setting that activates endpoint). I see that endpoint is created and usbview displays that endpoint's pipe is opened. But UDE does not fire any of events for data transmission.

  • Andreas_GraefeAndreas_Graefe Member Posts: 5

    Yes, I can confirm that behaviour. The altsetting is either incorrect (set to 0 when it should be set to 1) or it's just not called.

    I believe that something needs to be done in EvtUsbDeviceEndpointsConfigure, but I don't know what.

    Can you please post the link to the mentioned github project? Would like to take a look myself at this workaround.

  • Andreas_GraefeAndreas_Graefe Member Posts: 5

    Ah yes, I also looked into that before. I also tried it out, but it also wasn't able to forward an audio device properly (at least I didn't manage to get it running).

    Indeed, EvtUsbDeviceEndpointsConfigureis called with UdecxEndpointsConfigureTypeInterfaceSettingChange, but Params->InterfaceNumber and Params->NewInterfaceSetting are wrong.

    I'm asking myself what needs to be done in the EvtUsbDeviceEndpointsConfigurecallback to notify the framework that the interface setting request was sucessful. I'm just doing

    WdfRequestComplete(Request, STATUS_SUCCESS);

    (because I only want to simulate an audio device), but this is seems to be not enough. Perhaps the endpoint has to be started / restarted somehow, but I was assuming that this is already done by the framework in the EvtUsbDeviceEndpointAdd callback.

  • bojan_janjicbojan_janjic Member Posts: 6

    I have logged today what values are received in EvtUsbDeviceEndpointsConfigure, and it is for sure wrong.

    Device has interface 1 for speaker with 2 alternate settings:
    0 - no endpoints
    1 - two isochronous endpoints

    When I try to test speaker, USB analyzer tool shows that alternate setting 1 of interface 1 is selected, however in EvtUsbDeviceEndpointsConfigure callback I receive:
    InterfaceNumber = 1
    NewInterfaceSetting = 0

    Like streaming is off (alternate setting has not endpoints), but that is not the case. UDE driver actually created 2 endpoints and device has opened pipes.

    I have tried to "fix" value for NewInterfaceSetting, but again I do not receive any data.

    Seems like problem is not with isochronous endpoints, but with interfaces that have alternate settings.

  • Benjamin_HöglingerBenjamin_Höglinger Member - All Emails Posts: 20
    edited January 24

    Took a couple months of excruciating research, trial and error but we finally cracked it!

    UDE doesn't implement QueryBusTime in USB_BUS_INTERFACE_USBDI_V1 which USBAUDIO.SYS depends on to compare frame times. I've reported this to Microsoft and in the meantime have written a filter driver to mitigate this problem and now audio works with UDE! I'll update my post once I got a writeup published.


Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. Sign in or register to get started.

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Kernel Debugging 30 January 2023 Live, Online
Developing Minifilters 20 March 2023 Live, Online
Internals & Software Drivers 17 April 2023 Live, Online
Writing WDF Drivers 22 May 2023 Live, Online