windows-ce

USB dongle (non-storage device) not recognized after rebooted while plugged in


We have a programmable proprietary USB dongle (that is not a storage device) that we insert into a machine running Windows CE7. With the dongle there is an API we can use. One simple API function is the "checkIfDongleInserted" function. The USB dongle is recognized when inserted on the running machine, i.e. it is listed in the Wince Registry under HKLM\Drivers\Active and we can find it with the checkIfDongleInserted function. However if we restart the machine while the dongle stays inserted, the device is not recognized anymore, i.e. it doesn't show up in the registry and the API function fails. If we reinsert the dongle by hand then it is recognized again. Funny enough other devices (USB sticks, USB keyboards, USB mouses) work and are recognized perfectly well after a reboot of the machine while said devices stay inserted.

Upon inspecting the USB dongle's driver I found that it implements the interface USBInstallDriver. Researching this interface led me to https://learn.microsoft.com/en-us/previous-versions/windows/embedded/ms923254(v=msdn.10), where in the remarks it says that

The USB driver module calls this function when an unrecognized device is attached to the USB port

So my guess is that restarting this "USB driver module" (from a client application) while the machine is running could be an idea to recognize the USB dongle. Though I don't see this happening from a client application.

What could be the reason for this specific device not being detected upon boot while it is inserted? Is there a way to recognize it without having to reinsert it manually?


Solution

  • Inspired by this post I found the solution. I was right in the assumption that I had to restart the USB controller, I just didn't know how. After further research I found that HCD (Host Controller Driver) is the driver that detects the inserted USB devices and that I need to reload again. Upon doing that it would detect my already inserted USB dongle again.

    Use FindFirstDevice to find the device (in this case the Host controller), then unload the driver with DeactivateDevice() and soon after load the driver again with ActivateDeviceEx().

    Here's the code without any error handling (I'm on a different PC and too lazy to copy everything over, so I just roughly wrote the above steps in C)

    DeviceSearchType searchType = DeviceSearchByDeviceName;
    DEVMGR_DEVICE_INFORMATION deviceInfo;
    
    //Find HCD
    handle = FindFirstDevice(searchType,L"HCD*",&deviceInfo);
    
    
    //Save the deviceKey to later be able to ActivateDeviceEx()
    WCHAR* deviceKey = deviceInfo.szDeviceKey;
    DeactivateDevice(deviceInfo.hDevice);
    Sleep(100); //to make sure
    ActivateDeviceEx(deviceKey,NULL,0,NULL);