EDN Admin
Well-known member
Hi,
Im making a configuration tool (Win32 API, C++) which connects to a USB HID device and read / writes a 512B EEprom.
My software is registered for receiving the WM_DEVICECHANGE event and connects to the device when it receives a device arrival event. This works great, once the device driver (default Windows USB HID driver) is installed.
My problem is that the first time a new device (or same device with a new USB iSerialNumber) is connected to a Windows PC (Windows XP, Windows 7) the "Found new hardware wizard" is invoked. Before it says "Your new hardware is ready for use" my software picks up a "WM_DEVICECHANGE + DBT_DEVICEARRIVAL" and uses CreateFile() to connect to the device.
However, the driver installation is not done at this point and the device is then detached and reconnected and Windows now displays "Hardware ready to use" followed by a "You need to restart windows in order for this device to work". The problem is that communication fails during this "dead"-period where the driver is not really functional.
There is nothing in the received WM_DEVICECHANGE that indicates that the device is not actually ready yet. If i call CreateFile() afterDBT_DEVICEARRIVAL followed immediately by a CloseHandle() then Windows believes it still requires a reboot. I think it has something to do with fact that first Windows installs a "HID compliant device" then it installs a "USB input device". So the device arrival event is sent after the first one is installed?
By USBview my USB descriptor looks like this:
Device Descriptor:
bcdUSB: 0x0110
bDeviceClass: 0x00
bDeviceSubClass: 0x00
bDeviceProtocol: 0x00
bMaxPacketSize0: 0x40 (64)
idVendor: 0xXXXX
idProduct: 0xXXXX
bcdDevice: 0x0000
iManufacturer: 0x01
0x0409: "XXXX"
iProduct: 0x02
0x0409: "XXXX"
iSerialNumber: 0x03
bNumConfigurations: 0x01
ConnectionStatus: DeviceConnected
Current Config Value: 0x01
Device Bus Speed: Full
Device Address: 0x02
Open Pipes: 2
Endpoint Descriptor:
bEndpointAddress: 0x81
Transfer Type: Interrupt
wMaxPacketSize: 0x0040 (64)
bInterval: 0x20
Endpoint Descriptor:
bEndpointAddress: 0x01
Transfer Type: Interrupt
wMaxPacketSize: 0x0040 (64)
bInterval: 0x20
Configuration Descriptor:
wTotalLength: 0x0029
bNumInterfaces: 0x01
bConfigurationValue: 0x01
iConfiguration: 0x00
bmAttributes: 0xA0 (Bus Powered Remote Wakeup)
MaxPower: 0x32 (100 Ma)
Interface Descriptor:
bInterfaceNumber: 0x00
bAlternateSetting: 0x00
bNumEndpoints: 0x02
bInterfaceClass: 0x03 (HID)
bInterfaceSubClass: 0x00
bInterfaceProtocol: 0x00
iInterface: 0x00
HID Descriptor:
bcdHID: 0x0111
bCountryCode: 0x00
bNumDescriptors: 0x01
bDescriptorType: 0x22
wDescriptorLength: 0x0025
Endpoint Descriptor:
bEndpointAddress: 0x81
Transfer Type: Interrupt
wMaxPacketSize: 0x0040 (64)
bInterval: 0x20
Endpoint Descriptor:
bEndpointAddress: 0x01
Transfer Type: Interrupt
wMaxPacketSize: 0x0040 (64)
bInterval: 0x20
This is the code for registering for the WM_DEVICECHANGE event
void
RequestNotification(HWND hWnd)
{
DEV_BROADCAST_DEVICEINTERFACE broadcastInterface;
HDEVNOTIFY NotifyDevHandle;
memset (&broadcastInterface, 0,
sizeof(broadcastInterface));//zero the structure
broadcastInterface.dbcc_size =
sizeof(DEV_BROADCAST_DEVICEINTERFACE);
broadcastInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
HidD_GetHidGuid((LPGUID)&broadcastInterface.dbcc_classguid);
NotifyDevHandle = RegisterDeviceNotification(hWnd,&broadcastInterface,DEVICE_NOTIFY_WINDOW_HANDLE);
}
This is my CreateFile()
m_DataHandle = CreateFile(hidDeviceInterfaceDetailData->DevicePath,GENERIC_WRITE,0, (LPSECURITY_ATTRIBUTES)NULL,OPEN_EXISTING,0,NULL);
m_DataHandle2 = CreateFile(hidDeviceInterfaceDetailData->DevicePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
View the full article
Im making a configuration tool (Win32 API, C++) which connects to a USB HID device and read / writes a 512B EEprom.
My software is registered for receiving the WM_DEVICECHANGE event and connects to the device when it receives a device arrival event. This works great, once the device driver (default Windows USB HID driver) is installed.
My problem is that the first time a new device (or same device with a new USB iSerialNumber) is connected to a Windows PC (Windows XP, Windows 7) the "Found new hardware wizard" is invoked. Before it says "Your new hardware is ready for use" my software picks up a "WM_DEVICECHANGE + DBT_DEVICEARRIVAL" and uses CreateFile() to connect to the device.
However, the driver installation is not done at this point and the device is then detached and reconnected and Windows now displays "Hardware ready to use" followed by a "You need to restart windows in order for this device to work". The problem is that communication fails during this "dead"-period where the driver is not really functional.
There is nothing in the received WM_DEVICECHANGE that indicates that the device is not actually ready yet. If i call CreateFile() afterDBT_DEVICEARRIVAL followed immediately by a CloseHandle() then Windows believes it still requires a reboot. I think it has something to do with fact that first Windows installs a "HID compliant device" then it installs a "USB input device". So the device arrival event is sent after the first one is installed?
By USBview my USB descriptor looks like this:
Device Descriptor:
bcdUSB: 0x0110
bDeviceClass: 0x00
bDeviceSubClass: 0x00
bDeviceProtocol: 0x00
bMaxPacketSize0: 0x40 (64)
idVendor: 0xXXXX
idProduct: 0xXXXX
bcdDevice: 0x0000
iManufacturer: 0x01
0x0409: "XXXX"
iProduct: 0x02
0x0409: "XXXX"
iSerialNumber: 0x03
bNumConfigurations: 0x01
ConnectionStatus: DeviceConnected
Current Config Value: 0x01
Device Bus Speed: Full
Device Address: 0x02
Open Pipes: 2
Endpoint Descriptor:
bEndpointAddress: 0x81
Transfer Type: Interrupt
wMaxPacketSize: 0x0040 (64)
bInterval: 0x20
Endpoint Descriptor:
bEndpointAddress: 0x01
Transfer Type: Interrupt
wMaxPacketSize: 0x0040 (64)
bInterval: 0x20
Configuration Descriptor:
wTotalLength: 0x0029
bNumInterfaces: 0x01
bConfigurationValue: 0x01
iConfiguration: 0x00
bmAttributes: 0xA0 (Bus Powered Remote Wakeup)
MaxPower: 0x32 (100 Ma)
Interface Descriptor:
bInterfaceNumber: 0x00
bAlternateSetting: 0x00
bNumEndpoints: 0x02
bInterfaceClass: 0x03 (HID)
bInterfaceSubClass: 0x00
bInterfaceProtocol: 0x00
iInterface: 0x00
HID Descriptor:
bcdHID: 0x0111
bCountryCode: 0x00
bNumDescriptors: 0x01
bDescriptorType: 0x22
wDescriptorLength: 0x0025
Endpoint Descriptor:
bEndpointAddress: 0x81
Transfer Type: Interrupt
wMaxPacketSize: 0x0040 (64)
bInterval: 0x20
Endpoint Descriptor:
bEndpointAddress: 0x01
Transfer Type: Interrupt
wMaxPacketSize: 0x0040 (64)
bInterval: 0x20
This is the code for registering for the WM_DEVICECHANGE event
void
RequestNotification(HWND hWnd)
{
DEV_BROADCAST_DEVICEINTERFACE broadcastInterface;
HDEVNOTIFY NotifyDevHandle;
memset (&broadcastInterface, 0,
sizeof(broadcastInterface));//zero the structure
broadcastInterface.dbcc_size =
sizeof(DEV_BROADCAST_DEVICEINTERFACE);
broadcastInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
HidD_GetHidGuid((LPGUID)&broadcastInterface.dbcc_classguid);
NotifyDevHandle = RegisterDeviceNotification(hWnd,&broadcastInterface,DEVICE_NOTIFY_WINDOW_HANDLE);
}
This is my CreateFile()
m_DataHandle = CreateFile(hidDeviceInterfaceDetailData->DevicePath,GENERIC_WRITE,0, (LPSECURITY_ATTRIBUTES)NULL,OPEN_EXISTING,0,NULL);
m_DataHandle2 = CreateFile(hidDeviceInterfaceDetailData->DevicePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
View the full article