How can my application detect when my device is attached or removed?
To find out when a device has been attached or removed, catch the WM_DEVICECHANGE messege with the parameter DBT_DEVNODES_CHANGED. Then use SetupDi_ functions to find out what device was attached or removed. A Usenet post on the subject is USB Device Insertion/Removal Event Notification. Also see my example code.
How can my application reset, disable, or restart a USB device?
The DevCon example in the WDK is a command-line utility that shows how to enable, disable, restart, update, remove and query devices using the SetupAPI and CfgMgr32 API functions.
How can I determine which port my device is attached to?
Under Windows, every device has a unique driver key, also called the software key. You can obtain the key from a device using SetupDi functions, and obtain the same key from a hub port using undocumented DeviceIoControl codes. When you have a match, you know which port the device is attached to.
To retrieve the driver key name for a device, call SetupDiGetClassDevs and SetupDiEnumDeviceInfo, then use SetupDiGetDeviceRegistryPropertyA with Property set to SPDRP_DRIVER.
To retrieve the driver key name for a hub port, first find the hubs with SetupDi_ functions and GUID_DEVINTERFACE_USB_HUB.
Obtain a handle to a hub with CreateFile.
Get the number of ports on the hub with IOCTL_USB_GET_NODE_INFORMATION (undocumented IO control code in usbioctl.h).
Find out if a device is attached to a port with IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX.
For each attached device, get the driver key name with IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME (undocumented IO control code in usbioctl.h).
I have two or more identical devices attached to a host. How can I tell which is which?
Store a serial number in the device descriptor or use another vendor-specific identifier. For HID-class devices, applications can read the serial number with the HidD_GetSerialNumberString function.
I've made changes to my device's firmware but Windows doesn't seem to recognize the changes.
With the device attached, remove the device in Windows Device Manager. Then detach and reattach the device.
Is there a limit to the maximum size of a transfer?
See Maximum size of USB transfers on various operating systems (Microsoft Knowledge Base Article 832430).
These values are the maximum amount of data a WDM driver can request to send or receive in a single USB Request Block (URB). An application may request to send or receive more or less than this amount. The driver can handle larger amounts by using multiple URBs. A specific device may have stricter limits on transfer size.
During device testing, we attach many devices that are identical except for the serial numbers. How can I prevent Windows from asking to install a new driver every time a device is attached?
The method described below causes Windows 2000 and XP to ignore a device's serial number. It's recommended for test environments only.
This registry key controls whether Windows uses or ignores device serial numbers:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\UsbFlags]
It's possible to ignore all serial numbers, though this approach is NOT recommended. To ignore all serial numbers, in the above key, change this value to zero:
GlobalDisableSerNumGen = 1
To ignore the serial number for an individual device, create an entry under the above ...\UsbFlags key. The name must start with "IgnoreHWSerNum" followed by the vendor and product ID of the device. A value of 1 = "disable the serial number."
Example (Vendor ID = 0925h, Product ID = 016Ah):
IgnoreHWSerNum0925016A= 1
(Thanks to Dieter Fauth for this answer.)
How is the USB data CRC value calculated?
Here are two examples.
Example 1 from Ron Hemphill.
Example 2 from Barry Twycross:
This is not suitable for use as production code; it is very inefficient:
UInt16 CRC16(void *buffer, UInt32 count)
{
UInt8 *bp;
UInt32 poly, a, b, newBit, lostBit; int i;
poly = 0x8005;
a = 0xffff;
bp = buffer;
while(count--)
{
b = *(bp++);
for(i = 0; i<8; i++)
{
a <<= 1;
newBit = (b & 1);
b >>= 1;
lostBit = a >> 16;
if(newBit != lostBit)
{
a ^= poly;
}
a &= 0xffff;
}
}
return(a^0xffff); }