A while ago I was trying to get descriptors asynchronously from devices since in some situations, like if you catch a Mass Storage device while it's busy servicing a CDB, the device could drop control pipe requests on the floor, causing DeviceIoControl to block until Windows loses patience with the device and resets it (about five seconds).

The naïve approach is to use an OVERLAPPED structure with DeviceIoControl, since that's how you do async IO on Windows, but this doesn't work. It's up to the device driver to determine whether the call will be completed synchronously or not, and the Windows USB drivers complete all calls synchronously unless the pipe gets stalled by the device (normally between a URB submission and completion the device just NAKs until the result is ready). This is extremely uncommon, and impossible for the control pipe (which is where descriptor requests go) because the control pipe is used to clear stalls. Stall the control pipe and you wedge the device, leaving a device reset as the only option. In five seconds.

The solution I wound up using is not one I'm particularly proud of, but it does have the advantage of working: I didn't mind a synchronous call (in fact, it made things easier), but I didn't want to deal with getting wedged when a device went out to lunch, so I spawned a thread1 and used WaitForSingleObject to set my timeout. Plan on waiting 80ms or so per quarter-kilobyte expected. Measured very unscientifically, a config descriptor without interfaces (nine bytes) takes less than 10ms, average 4.7ms, standard deviation 0.00831.

Note that you want to open the HANDLE you're using in the DeviceIoControl call in the thread too—if there's another request in flight, opening the file handle will block until it's completed, which is exactly what we're trying so hard to avoid. You shouldn't really be calling for another descriptor from the same device right after it's failed though, because it's likely about to be reset by Windows.

Bonus pitfall: For configuration and string descriptors, you don't know how big the descriptor is, so you can grab a portion of it, get the bLength (wTotalLength for configuration descriptors) and use that to get the rest of the descriptor, or you can just request UINT16_MAX and cross your fingers.

It turns out that neither of these approaches work for all devices for any value of n. To save some space, but keep the number of round trips to the device low, I always used a 256 byte buffer in my requests, and failed over to a larger buffer if the descriptor was too big. Unfortunately, in the classic "just bang on it until it starts working" approach of USB vendors, some devices will just not respond if you make a request with a buffer size that is not the exact size of the descriptor or sizeof UsbConfigurationDescriptor (nine bytes). The reason for this appears to be one of convenience—Windows itself only requests either nine bytes or the entirety of descriptors, so some device firmwares were written with only these two cases in mind.


1 more accurately: reused a vthread, but the internal implementation of our threading library is not germane to this article

It’s true that a Verizon iPhone would require new hardware. But that’s not a holdup. I’m nearly certain that a Verizon-compatible iPhone is pretty much like the Intel-compatible version of Mac OS X — something that Apple has kept going all along, ready to put into production when, if ever, its time comes.John Gruber

Other than "sources informed on the topic" (of which there are none in this post) I don't see any evidence why this would be the case. The reason Mac OS X was continuously built on x86 after NeXT acquired Apple is the same reason the USB team at VMware accepts bugs encountered in configurations we don't publicly support: it's a great way to ensure that your product is solid. If there's a problem in one configuration, chances are really good that it affects the others in some way. Never throw anything out that is supposed to work.

Apple has never made a product using CDMA before, and it's not worth the new investment to create new hardware unless it's in the plan. The iPhone division's time is too important—there's just too much to do. If there is a CDMA iPhone in existence, it's a recent development, not something that's "pretty much like the Intel-compatible version of Mac OS X".

I'm also not sold on this fixation with Verizon. They may have the largest subscriber base, but Verizon is notorious for the control they exert over their handsets. New firmware, new UI, disabling hardware features like GPS and Bluetooth—it would take a complete paradigm shift for Verizon to ever accept the iPhone without trying to dick with it. If there is a deal for a CDMA iPhone it seems more likely to me that it would be with Sprint. This "iPhone is coming to Verizon!" stuff has always sounded more like wishful thinking by locked-in Verizon customers than educated guesses by an impartial analyst.


for many years before this, today would have been my last day at work. about this time I would be wrapping up my projects and handing in my keys.

this graduated stuff is weird. I feel too young to be an adult!