OnDeviceChange dbcc_name length
-
Hello, I have registered USB serial devices for notification and get a device arrival & removal notice now in OnDeviceChange. However, always when I try to print out the dbcc_name, its length is one wide character (as defined in the structure documentation) and nothing more prints out. I have browsed countless examples where the code proceeds to extract for instance a VID/PID from the string. What am I doing wrong? The examples also give me one character. I am using windows 10 & VS2017. I have even reserved a larger buffer for notification registration to fit in the full dbcc_name string. Nothing helps, just get that one character. I have also tried the WideCharToMultibyte and then instead of a Chinese character I get a single question mark. Please advise.
-
Hello, I have registered USB serial devices for notification and get a device arrival & removal notice now in OnDeviceChange. However, always when I try to print out the dbcc_name, its length is one wide character (as defined in the structure documentation) and nothing more prints out. I have browsed countless examples where the code proceeds to extract for instance a VID/PID from the string. What am I doing wrong? The examples also give me one character. I am using windows 10 & VS2017. I have even reserved a larger buffer for notification registration to fit in the full dbcc_name string. Nothing helps, just get that one character. I have also tried the WideCharToMultibyte and then instead of a Chinese character I get a single question mark. Please advise.
-
Hello, I have registered USB serial devices for notification and get a device arrival & removal notice now in OnDeviceChange. However, always when I try to print out the dbcc_name, its length is one wide character (as defined in the structure documentation) and nothing more prints out. I have browsed countless examples where the code proceeds to extract for instance a VID/PID from the string. What am I doing wrong? The examples also give me one character. I am using windows 10 & VS2017. I have even reserved a larger buffer for notification registration to fit in the full dbcc_name string. Nothing helps, just get that one character. I have also tried the WideCharToMultibyte and then instead of a Chinese character I get a single question mark. Please advise.
Member 13899178 wrote:
However, always when I try to print out the dbcc_name, its length is one wide character (as defined in the structure documentation) and nothing more prints out. ... Please advise.
Please provide the code you are using to do the printing.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
-
Quote:
I am using windows 10 & VS2017.
Yes, but we cannot guess what code you are using. Please edit your question and provide full details.t
I am using MFC & C++. This code is missing the WideCharToMultibyte conversion which didn't help one bit. I am using this document as refrence: http://www.ftdichip.com/Support/Documents/AppNotes/AN\_152\_Detecting\_USB\_ Device\_Insertion\_and\_Removal.pdf
BOOL CTesterDlg::OnDeviceChange(UINT nEventType, DWORD_PTR dwPtrData)
{
BOOL bReturn = CWnd::OnDeviceChange(nEventType, dwPtrData);PDEV\_BROADCAST\_DEVICEINTERFACE b = (PDEV\_BROADCAST\_DEVICEINTERFACE)dwPtrData; if(b != NULL) { CString Msg; Msg.Format(L"%s",b->dbcc\_name); MessageBox(Msg); } switch (nEventType) { case DBT\_DEVICEARRIVAL: if(hComm==INVALID\_HANDLE\_VALUE) DeviceInit(); break; case DBT\_DEVICEREMOVECOMPLETE: ClosePort(); break; } return bReturn;
}
-
I am using MFC & C++. This code is missing the WideCharToMultibyte conversion which didn't help one bit. I am using this document as refrence: http://www.ftdichip.com/Support/Documents/AppNotes/AN\_152\_Detecting\_USB\_ Device\_Insertion\_and\_Removal.pdf
BOOL CTesterDlg::OnDeviceChange(UINT nEventType, DWORD_PTR dwPtrData)
{
BOOL bReturn = CWnd::OnDeviceChange(nEventType, dwPtrData);PDEV\_BROADCAST\_DEVICEINTERFACE b = (PDEV\_BROADCAST\_DEVICEINTERFACE)dwPtrData; if(b != NULL) { CString Msg; Msg.Format(L"%s",b->dbcc\_name); MessageBox(Msg); } switch (nEventType) { case DBT\_DEVICEARRIVAL: if(hComm==INVALID\_HANDLE\_VALUE) DeviceInit(); break; case DBT\_DEVICEREMOVECOMPLETE: ClosePort(); break; } return bReturn;
}
-
Use your debugger to see exactly what is returned in
Dbcc_name
. The code looks correct but the actual data may be the problem.Yeah, there is nothing more with my debugger than is in the MessageBox added for debugging purposes.
-
Hello, I have registered USB serial devices for notification and get a device arrival & removal notice now in OnDeviceChange. However, always when I try to print out the dbcc_name, its length is one wide character (as defined in the structure documentation) and nothing more prints out. I have browsed countless examples where the code proceeds to extract for instance a VID/PID from the string. What am I doing wrong? The examples also give me one character. I am using windows 10 & VS2017. I have even reserved a larger buffer for notification registration to fit in the full dbcc_name string. Nothing helps, just get that one character. I have also tried the WideCharToMultibyte and then instead of a Chinese character I get a single question mark. Please advise.
The handler is called multiple times for a single event with different parameters, and also upon specific device changes even when not registered. So you have to check always if the device type matches and cast then to the corresponding broadcast structure (because all structures have the common _DEV_BROADCAST_HDR | Microsoft Docs[^] header, casting can be done initially when checking for the matching type). So your code should look like (based on your code snippet posted in the above sub thread):
// FTDI_D2XX_Device Class GUID
// To be used with RegisterDeviceNotification()
/*static*/ const GUID CTesterDlg::GUID_DEVINTERFACE_FTDI_D2XX =
{ 0x219D0508, 0x57A8, 0x4FF5, { 0x97, 0xA1, 0xBD, 0x86, 0x58, 0x7C, 0x6C, 0x7E }};BOOL CTesterDlg::OnDeviceChange(UINT nEventType, DWORD_PTR dwPtrData)
{
BOOL bReturn = CWnd::OnDeviceChange(nEventType, dwPtrData);PDEV\_BROADCAST\_DEVICEINTERFACE b = reinterpret\_cast(dwPtrData); // Check if dwPtrData is not NULL and for type BROADCAST\_DEVICEINTERFACE. // When having registered an event with a GUID, that should be also compared here. // Comparing the GUID must be done when having registered multiple events. if (b && b->dbcc\_devicetype == DBT\_DEVTYP\_DEVICEINTERFACE && b->dbcc\_classguid == GUID\_DEVINTERFACE\_FTDI\_D2XX) { //MessageBox(b->dbcc\_name); // Handle events here // switch (nEventType) } return bReturn;
}
Regarding the encoding of the name, see _DEV_BROADCAST_DEVICEINTERFACE_A | Microsoft Docs[^]:
Quote:
When this structure is returned to a window through the WM_DEVICECHANGE message, the dbcc_name string is converted to ANSI as appropriate.
That means you will get an ANSI string with ANSI builds and a Unicode string with Unicode builds when having called
RegisterDeviceNotification()
. Portions of the above (like the GUID) are from some testing code I have written in 20 -
The handler is called multiple times for a single event with different parameters, and also upon specific device changes even when not registered. So you have to check always if the device type matches and cast then to the corresponding broadcast structure (because all structures have the common _DEV_BROADCAST_HDR | Microsoft Docs[^] header, casting can be done initially when checking for the matching type). So your code should look like (based on your code snippet posted in the above sub thread):
// FTDI_D2XX_Device Class GUID
// To be used with RegisterDeviceNotification()
/*static*/ const GUID CTesterDlg::GUID_DEVINTERFACE_FTDI_D2XX =
{ 0x219D0508, 0x57A8, 0x4FF5, { 0x97, 0xA1, 0xBD, 0x86, 0x58, 0x7C, 0x6C, 0x7E }};BOOL CTesterDlg::OnDeviceChange(UINT nEventType, DWORD_PTR dwPtrData)
{
BOOL bReturn = CWnd::OnDeviceChange(nEventType, dwPtrData);PDEV\_BROADCAST\_DEVICEINTERFACE b = reinterpret\_cast(dwPtrData); // Check if dwPtrData is not NULL and for type BROADCAST\_DEVICEINTERFACE. // When having registered an event with a GUID, that should be also compared here. // Comparing the GUID must be done when having registered multiple events. if (b && b->dbcc\_devicetype == DBT\_DEVTYP\_DEVICEINTERFACE && b->dbcc\_classguid == GUID\_DEVINTERFACE\_FTDI\_D2XX) { //MessageBox(b->dbcc\_name); // Handle events here // switch (nEventType) } return bReturn;
}
Regarding the encoding of the name, see _DEV_BROADCAST_DEVICEINTERFACE_A | Microsoft Docs[^]:
Quote:
When this structure is returned to a window through the WM_DEVICECHANGE message, the dbcc_name string is converted to ANSI as appropriate.
That means you will get an ANSI string with ANSI builds and a Unicode string with Unicode builds when having called
RegisterDeviceNotification()
. Portions of the above (like the GUID) are from some testing code I have written in 20All valid points, thank you. The note about device interface was good and got me on the right track. I was blind to that part as the code seemed to work and returned something. The problem seems to have been that I have registered to receive messages to my Hwnd from GUID_DEVCLASS_PORTS which is not an interface class, now I changed to GUID_DEVINTERFACE_USB_DEVICE and I get a proper string with VID & PID. Problem solved, thanks!
-
All valid points, thank you. The note about device interface was good and got me on the right track. I was blind to that part as the code seemed to work and returned something. The problem seems to have been that I have registered to receive messages to my Hwnd from GUID_DEVCLASS_PORTS which is not an interface class, now I changed to GUID_DEVINTERFACE_USB_DEVICE and I get a proper string with VID & PID. Problem solved, thanks!
Fine to hear that the problem is solved. If you don't need the VID and PID but just want to be informed of the plugin / -out for the virtual COM ports, there is even no need to register. Then just check for
DBT_DEVTYP_PORT
events. They are one of the always signaled events (as already mentioned):// Assume port changing (serial or parallel). The devicetype field is part of header of all structures.
// The name passed here is always the COM port name (even with virtual ports).
// Note that dwData may be NULL.
PDEV_BROADCAST_PORT pPort = reinterpret_cast(dwData);
if (pPort && DBT_DEVTYP_PORT == pPort->dbcp_devicetype)
{
// pPort->dbcp_name is "COMx" or "LPTx"
} -
Fine to hear that the problem is solved. If you don't need the VID and PID but just want to be informed of the plugin / -out for the virtual COM ports, there is even no need to register. Then just check for
DBT_DEVTYP_PORT
events. They are one of the always signaled events (as already mentioned):// Assume port changing (serial or parallel). The devicetype field is part of header of all structures.
// The name passed here is always the COM port name (even with virtual ports).
// Note that dwData may be NULL.
PDEV_BROADCAST_PORT pPort = reinterpret_cast(dwData);
if (pPort && DBT_DEVTYP_PORT == pPort->dbcp_devicetype)
{
// pPort->dbcp_name is "COMx" or "LPTx"
}Thanks for the tip. You've been very helpful.