MidiInput::getAvailableDevices() doesn't immediately find newly connected devices

I have a simple timer callback function which detects newly connected or disconnected midi devices. It’s called every 500 ms and uses MidiInput::getAvailableDevices(). This code has worked well for years, literally. All of a sudden, with a ‘new’ Windows 10 installation that I haven’t used for testing until now, there’s a significant delay between a new device appearing in the Device Manager window and the same device showing up in the output list returned by getAvailableDevices(). The delay is around 9 seconds and the timer callback runs 18 or so times before the new connection is noticed.

I have another Windows PCs where this isn’t an issue and the app is already out in the wild with probably thousands of users, but I’d still like to understand the behaviour. Has anyone come across this kind of thing before or have any suggestions as to where to look for differences in setup or other likely causes?

Thanks

I took a quick look at the code, and the code path for that calls the OS API’s directly, so it’s not obvious how juce would cause the delay. You could put some sort of logging in Win32InputWrapper::getDeviceCaps () to track what the OS is returning, and verify it is, or isn’t, juce related (it is in juce_audio_devices\native\juce_win32_Midi.cpp)

Thanks for the reply. I’d already found the Win32InputWrapper code and yes, it looks fairly straightfoward before calling into the OS and I don’t really see how Juce itself would be causing new entries to be missed. I was just wondering, given that this would be familiar territory for some people in this forum, if anyone had come across something that would cause Windows to misbehave in this way. I’ll put some logging code where you suggested, though, and report back if I learn anything.

This is a very interesting topic, because its thorny.

Is it possible your MIDI device is qualifying as a “USB MIDI Class Device” and thus using the class driver, but “falling over” somehow during the enumeration, until finally the manufacturer-provided driver is enumerated for the device, and ‘eventually’ provides the appropriate device endpoints?

Could it be a composite device? [0]

USB MIDI devices often fit in one of two different catetgories - two-stage loader, or single-stage.

A two-stage loader is usually used in the case where the device itself doesn’t have any static RAM or EEPROM, and thus needs to have its ‘real’ firmware loaded, in the first stage, as a binary blob from a manufacturer-provided driver - only then (once the binary blob is loaded and the device reboots to run it) - is the Microsoft-provided internal class driver instantiated for the running device.

(A single-stage driver doesn’t do this because the device has EEPROM/sram and can thus just boot straight to a firmware which gets recognized as a class-compliant device, and the OS thus uses the class driver to provide that device to applications)

More details about the devices in your situation would prove useful - also, have you tested this on every single USB port in the buggy system? Its quite possible, also, that POWER requirements are not being fulfilled on one of the systems ports - i.e. the port starts up in low-power mode, the device is connected to it, the driver determines that the device needs hi-power, but - for some reason known only to the Microsoft gods - the USB port itself takes a while to switch from lo- to hi- power mode. Another factor occurs when you’ve got a USB HUB connected to one of these misbehaving lo-/hi- power USB ports, and there is a dizzying storm of enumeration going on before the PC USB port and the HUB USB port finally settle on the correct power requirements for the MIDI Device you’ve plugged in.

Chase down and install the “USBVIEW.EXE” application from Microsofts Windows SDK for your system [1] - this can be used to show you when seemingly-random enumerations on the USB bus are occurring, and can provide you some clues about things. It may be that USBVIEW.EXE will show you that the port you’ve plugged into has a power-draw problem, then a few seconds later a second-stage of the firmware loader resets that port into hi- power mode, and then - even more complexity - maybe the device itself resets because it doesn’t get the power it needs.

This, by the way, can then also be magnified in terms of complexity yet again, if the device is also a composite device

USB is ass. Just sayin’.

[0] - Descriptors on USB Composite Devices - Windows drivers | Microsoft Learn

[1] - Universal Serial Bus Viewer in Windows - Windows drivers | Microsoft Learn

1 Like

Thanks for all those suggestions. The devices here are the entire range of Modal Electronics synths, both bus powered and self powered. The delays happen consistently on all eight ports in the system and on a powered hub that has proved very reliable over the years. USBView shows them as not being composite devices. (Admittedly I’d forgotten about USBView and haven’t used it in years. And it’s also prompted me to have a look with WireShark, too.)

Roger that, hope you will keep us updated.

I think I’m going to have to draw a blank on this one, but I’m reporting back for completeness.

Things I’ve found since last posting here include:

  • Watching the whole process more closely in Device Manager, I noticed two refreshes happen. The first is when the device connects and appears in the DM list, the second happens nine or ten seconds later, and it’s only at this point that repeated polls to midiInGetNumDevs() in the Win32 API finally see the device.
  • I see this double refresh with long delay happen with devices from other manufacturers, and not just USB audio devices. For instance, I see it happening when connecting a couple of external DVD drives.
  • I have verified that the latest chipset drivers are installed in the PC. (I inherited this machine and did not set it up myself, so something could have been left out.)
  • I have booted from an external SSD with a clean copy of Windows.
  • I have toggled the few USB related features that I found in BIOS setup.
  • Using Wireshark to examine packet streams I see no differences between this machine and another (much older) machine where there is no obvious delay. The same negotiation happens when the device first connects, ending with a SET INTERFACE exchange. (The same sequence of message types, though I haven’t checked the contents of each.) This is followed by an endless stream of mostly empty URB_BULK messages which eventually carry our sysex connection messages, indicating that our app has finally seen the synth. On the ‘normal’ machine there are a few hundred packets before we see our connection exchange, representing a delay of about 1.5 seconds. On the problem machine, there are several thousand. What ever is causing the delay, I can’t see any symptoms of it there.

Apart from inconvience, the only worrying effect of all this for any of this is during our firmware update process where our devices reboot and reconnect. Our app waits, but will report timeout errors when there are delays. The update process usually picks up when the synth is finally detected, so no harm done, but these error reports would be worrying for users so I’d rather they weren’t there. On the other hand, I’m not aware of any such reports coming in from the wild, so this must be a fairly rare occurrence, hence the decision to leave things here for now.

For reference here are the machine details:
12th Gen Intel(R) Core™ i7-12700 2.10 GHz, RAM 16.0 GB
ASUS Prime H610M-D D4, Bios ver 0403
Windows 10 Pro, Version 22H2, OS build 19045.4529

Thanks again to those who commented.