How to Know When a New Usb Storage Device Is Connected in Qt

How to know when a new USB storage device is connected in Qt?

I believe what you may be missing is the call to register for device notification. Here is code that I use to do the same thing, though I override the winEvent() method of the QWidget class and not the winEventFilter.

// Register for device connect notification
DEV_BROADCAST_DEVICEINTERFACE devInt;
ZeroMemory( &devInt, sizeof(devInt) );
devInt.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
devInt.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
devInt.dbcc_classguid = GUID_DEVINTERFACE_VOLUME;

m_hDeviceNotify =
RegisterDeviceNotification( winId(), &devInt, DEVICE_NOTIFY_WINDOW_HANDLE );
if(m_hDeviceNotify == NULL)
{
qDebug() << "Failed to register device notification";
} // end if

NOTE: You will most likely need to change the values of the DEV_BROADCAST_DEVICEINTERFACE to fit your needs.

EDIT: To use this code you will need to include the proper header files and perform the proper setup. DEV_BROADCAST_DEVICEINTERFACE requires the Dbt.h header to be included. Also, the focal point of this code is on the RegisterDeviceNotification function. Info is available on MSDN

Is there a Qt solution for detecting USB events (insertion and removal)?

As already pointed out, Qt itself does not provide such a module. There is however a user-made class called QDeviceWatcher. I have no experience with it personally and it is not updated regularly but you could give it a try.

You can find the forum post here and the git repository here.

Find current connected USB storage path in C++

First you need to get removable drives:

void EnumUsbDrives() {
DWORD drv = ::GetLogicalDrives();
if (drv == 0) return;

DWORD mask = 1;
TCHAR szDrive[] = _TEXT("?:\\");

for (uint_t i = 0; i < ('Z' - 'A' + 1); i++, mask <<= 1) {
if (drv & mask) {
szDrive[0] = (TCHAR)(_T('A') + i);
if (::GetDriveType(szDrive) == DRIVE_REMOVABLE) {
bool bUSB = IsDriveUSB(szDrive);
if (bUSB) {
// Time do to something useful
}
}
}
}
}

Function IsDriveUSB is a bit more complicated. I have teared it from an in-house library; the function uses custom helper classes xregistry and xstring_nocase. Their purpose is pretty obvious, I believe you will have no trouble replacing it with other similar classes or API calls.

bool IsDriveUSB (LPCTSTR szDrive) throw() {
TCHAR szLogicalDrive[] = _TEXT("\\\\.\\x:");
szLogicalDrive[4] = szDrive[0];
HANDLE hDrive = ::CreateFile(szLogicalDrive, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hDrive == INVALID_HANDLE_VALUE) return false; // Can't open drive so we have to assume the drive is fixed

VOLUME_DISK_EXTENTS vde;
DWORD dwBytesReturned = 0;
BOOL br = ::DeviceIoControl(hDrive, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &vde, sizeof(vde), &dwBytesReturned, NULL);
::CloseHandle(hDrive);
if (!br) return false; // Can't get extents info so we have to assume the drive is fixed

if (vde.NumberOfDiskExtents != 1) return false;
ULONG uPhysDrive = vde.Extents[0].DiskNumber;
TCHAR szPhysDrive[16];
_stprintf(szPhysDrive, _TEXT("%u"), uPhysDrive);

try {
xregistry rk(HKEY_LOCAL_MACHINE, OS.Is64bit());
rk.open(_TEXT("SYSTEM\\CurrentControlSet\\services\\Disk\\Enum"), KEY_QUERY_VALUE);
if (!rk.value_exists(szPhysDrive)) return false;
xstring_nocase strInterface = rk.get_string(szPhysDrive).substring(0, 7);
return strInterface == _TEXT("USBSTOR");
}
catch (...) {
return false;
}
}


Related Topics



Leave a reply



Submit