Sometimes the application needs to check the loading and unloading messages of the USB device, such as the plugging and unplugging of the U disk. One method is to call the device interface in a polling manner to try to access the device, but this approach is very inefficient and has low real-time performance. This article will introduce a more general method, through the system API function RequestDeviceNotificaTIons, read the device message, get the message of device loading and removal.
Find the device IClass valueEvery USB device has an IClass value, which is equivalent to the number in the system. The IClass value can be obtained by querying the board's registry. Take the U disk as an example:
As shown in the figure, [HKEY_LOCAL_MACHINE\Drivers\USB\ClientDrivers] contains all the USB device type information. Mass_Storage_Class is the IClass value of the USB flash drive {A4E7EDDA-E575-4252-9D6B-4195D48BB865}
Expressed in code that is
GUID guid = {0xA4E7EDDA, ​​0xE575, 0x4252, {0x9D, 0x6B, 0x41, 0x95, 0xD4, 0x8B, 0xB8, 0x65} };
Call API to monitor device messages
The monitoring process is as follows:
Create message queue -> bind device and message queue -> read message queue
Take U disk as an example, the code is as follows
MSGQUEUEOPTIONS msgopts;
//{A4E7EDDA-E575-4252-9D6B-4195D48BB865} This is for USB storage
GUID guid = {0xA4E7EDDA, ​​0xE575, 0x4252, {0x9D, 0x6B, 0x41, 0x95, 0xD4, 0x8B, 0xB8, 0x65} };
msgopts.dwSize = sizeof(MSGQUEUEOPTIONS);
msgopts.dwFlags = 0;
msgopts.dwMaxMessages = 10; //?
msgopts.cbMaxMessage = sizeof(MYDEV);
msgopts.bReadAccess = TRUE;
HANDLE m_hReadMsgQ = CreateMsgQueue(NULL, &msgopts);
HANDLE hNoTIfy;
DWORD ret;
hNotify = RequestDeviceNotifications(&guid, m_hReadMsgQ, TRUE);
flags = 0;
size = 0;
//while(true){
ret = WaitForSingleObject(m_hReadMsgQ, INFINITE);
if(ret == WAIT_OBJECT_0)
{
while (ReadMsgQueue(m_hReadMsgQ, &detail, sizeof(detail), &size, 1, &flags) == TRUE) //Parameter "1" means 1ms timeout
{
if (detail.d.fAttached)
{
wprintf(L"%s %s,f=0x%x", detail.d.szName, detail.d.fAttached? L"appeared": L"was removed", flags);
}
Else
{
wprintf(L"%s %s,f=0x%x", detail.d.szName, detail.d.fAttached? L"appeared": L"was removed", flags);
}// if (detail.d.fAttached)
}//while
}//if(ret == WAIT_OBJECT_0)
//}while(true)
CloseMsgQueue(m_hReadMsgQ);
Note: If it is a U disk, the detail.d.szName read here is the name of the U disk in the drive, such as "DSK1", not the letter of the U disk.
The messages read in the message queue include loading messages of loaded devices.
Obtain accurate device information according to device loading messages
Take the U disk as an example, its device type is "DSK", and the device type of SD card and NANDFLASH is also DSK, so after reading the device name such as "DSK1" and "DSK2" from the device message, it is not intuitive to determine which one is The device name of the USB flash drive.
At this time, you can call the storage-related API function OpenStore to query the U disk letter and other information based on the device name.
Necessary header files and lib libraries
#include "Storemgr.h"
#pragma comment(lib,"Storeapi.lib")
Encapsulate OpenStore functions
Increasing the timeout is necessary because the device loads messages faster, and the storage device may not be fully loaded yet. It may be as slow as 1ms at the longest, so a slight delay is enough.
HANDLE WINAPI OpenStoreEx(LPCTSTR szDeviceName, DWORD timeout = 3)
{
HANDLE hStore;
int i;
for(i=0;i
{
hStore = OpenStore(szDeviceName);
if (hStore != INVALID_HANDLE_VALUE)
{
break;;
}
Sleep(1);
}
return hStore;
}
Get detailed informationGetStoreInfo(hStore, &StoreInfo);
//if(wcscmp(StoreInfo.szStoreName, L"SD Memory Card") == 0) // judge it is an SD card
//else if(wcscmp(StoreInfo.szStoreName, L"NANDFS") == 0) // judge it is NandFlash
//else if (wcscmp(StoreInfo.szStoreName, L"USB Hard Disk Drive") == 0) // judge it is a U disk
wprintf(L"%s %s %s,f=0x%x", detail.d.szName, StoreInfo.szStoreName, detail.d.fAttached? L"appeared": L"was removed", flags);
Use linked list to store device informationWhen the U disk is loaded, you can query the device information by accessing the storage driver API. But when the device is removed, the device information does not exist in the drive, so the removed device information cannot be found using OpenStore and GetStoreInfo.
If you want to know the details of the removed device, you only need to store the information in the data structure when it is loaded. In this way, when removing, by querying the data in the data structure, you can obtain detailed device information.
Shenzhen Scodeno Technology Co.,Ltd , https://www.scodenonet.com