C++监控USB设备

这个程序前阵子帮一个朋友实现的,之前从未用消息队列做过类似的事情,做完后感觉其在线程同步,通信发面很好用,难怪COM也用这套机制。

程序稍微修改便能用作一般性的处理,目前实现的功能类似于监控Windows USB设备的插拔操作。

可以直接注释掉CString的使用后使用 cl /EHsc /W4 /Zi 编译,或粘贴到任意的VS中做编译。


#include <Windows.h>
#include <tchar.h>
#include <Dbt.h>
#include <setupapi.h>
#include <iostream>
#include <atlstr.h> // CString
using namespace std;

#pragma comment (lib, "Kernel32.lib")
#pragma comment (lib, "User32.lib")

#define THRD_MESSAGE_EXIT WM_USER + 1
const _TCHAR CLASS_NAME[]  = _T("Sample Window Class");

HWND hWnd;

static const GUID GUID_DEVINTERFACE_LIST[] =
{
    // GUID_DEVINTERFACE_USB_DEVICE
    { 0xA5DCBF10, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } },
    // GUID_DEVINTERFACE_DISK
    { 0x53f56307, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b } },
    // GUID_DEVINTERFACE_HID,
    { 0x4D1E55B2, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } },
    // GUID_NDIS_LAN_CLASS
    { 0xad498944, 0x762f, 0x11d0, { 0x8d, 0xcb, 0x00, 0xc0, 0x4f, 0xc3, 0x35, 0x8c } }
    GUID_DEVINTERFACE_COMPORT
    //{ 0x86e0d1e0, 0x8089, 0x11d0, { 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73 } },
    GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
    //{ 0x4D36E978, 0xE325, 0x11CE, { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } },
    GUID_DEVINTERFACE_PARALLEL
    //{ 0x97F76EF0, 0xF883, 0x11D0, { 0xAF, 0x1F, 0x00, 0x00, 0xF8, 0x00, 0x84, 0x5C } },
    GUID_DEVINTERFACE_PARCLASS
    //{ 0x811FC6A5, 0xF728, 0x11D0, { 0xA5, 0x37, 0x00, 0x00, 0xF8, 0x75, 0x3E, 0xD1 } }
};

void UpdateDevice(PDEV_BROADCAST_DEVICEINTERFACE pDevInf, WPARAM wParam)
{
    CString szDevId = pDevInf->dbcc_name + 4;
    int idx = szDevId.ReverseFind(_T('#'));
    szDevId.Truncate(idx);
    szDevId.Replace(_T('#'), _T('\\'));
    szDevId.MakeUpper();

    CString szClass;
    idx = szDevId.Find(_T('\\'));
    szClass = szDevId.Left(idx);

    CString szTmp;
    if ( DBT_DEVICEARRIVAL == wParam ) \
        szTmp.Format(_T("Adding %s\r\n"), szDevId.GetBuffer());
    else
        szTmp.Format(_T("Removing %s\r\n"), szDevId.GetBuffer());

    _tprintf(szTmp);
}

LRESULT DeviceChange(UINT message, WPARAM wParam, LPARAM lParam)
{
    if ( DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam )
    {
        PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam;
        PDEV_BROADCAST_DEVICEINTERFACE pDevInf;
        PDEV_BROADCAST_HANDLE pDevHnd;
        PDEV_BROADCAST_OEM pDevOem;
        PDEV_BROADCAST_PORT pDevPort;
        PDEV_BROADCAST_VOLUME pDevVolume;
        switch( pHdr->dbch_devicetype )
        {
            case DBT_DEVTYP_DEVICEINTERFACE:
                pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;
                UpdateDevice(pDevInf, wParam);
                break;

            case DBT_DEVTYP_HANDLE:
                pDevHnd = (PDEV_BROADCAST_HANDLE)pHdr;
                break;

            case DBT_DEVTYP_OEM:
                pDevOem = (PDEV_BROADCAST_OEM)pHdr;
                break;

            case DBT_DEVTYP_PORT:
                pDevPort = (PDEV_BROADCAST_PORT)pHdr;
                break;

            case DBT_DEVTYP_VOLUME:
                pDevVolume = (PDEV_BROADCAST_VOLUME)pHdr;
                break;
        }
    }
    return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
    case WM_PAINT:
        break;
    case WM_SIZE:
        break;
    case WM_DEVICECHANGE:
        return DeviceChange(message, wParam, lParam);
    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}

ATOM MyRegisterClass()
{
    WNDCLASS wc = {0};
    wc.lpfnWndProc   = WndProc;
    wc.hInstance     = GetModuleHandle(NULL);
    wc.lpszClassName = CLASS_NAME;
    return RegisterClass(&wc);
}

bool CreateMessageOnlyWindow()
{
    hWnd = CreateWindowEx(0, CLASS_NAME, _T(""), WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        NULL,       // Parent window    
        NULL,       // Menu
        GetModuleHandle(NULL),  // Instance handle
        NULL        // Additional application data
        );

    return hWnd != NULL;
}

void RegisterDeviceNotify()
{
    HDEVNOTIFY hDevNotify;
    for (int i = 0; i < sizeof(GUID_DEVINTERFACE_LIST) / sizeof(GUID); i++)
    {
        DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
        ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) );
        NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
        NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
        NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_LIST[i];
        hDevNotify = RegisterDeviceNotification(hWnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
    }
}

DWORD WINAPI ThrdFunc( LPVOID lpParam )
{
    if (0 == MyRegisterClass())
        return -1;

    if (!CreateMessageOnlyWindow())
        return -1;

    RegisterDeviceNotify();

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (msg.message == THRD_MESSAGE_EXIT)
        {
            cout << "worker receive the exiting Message..." << endl;
            return 0;
        }

        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

int main(int argc, char** argv)
{
    DWORD iThread;
    HANDLE hThread = CreateThread( NULL, 0, ThrdFunc, NULL, 0, &iThread);
    if (hThread == NULL) {
        cout << "error" << endl;
        return -1;
    }

    char chQtNum;
    do
    {
        cout << "enter Q/q for quit: " << endl;
        cin >> chQtNum;

    } while (chQtNum != 'Q' && chQtNum != 'q');

    PostThreadMessage(iThread, THRD_MESSAGE_EXIT, 0, 0);
    WaitForSingleObject(hThread, INFINITE);
    CloseHandle(hThread);
    return 0;
}


  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
HID 设备类读写 #include //! Defines the maximum length of a serial number #define SERNUM_LEN 40 //! Defines the maximum number of physical devices #define MAX_PHYS_DEVICES 6 //! \name HID Device return codes //! @{ // //! HID action/transfer was successful #define HID_DEVICE_SUCCESS 0x00 //! HID device was not found #define HID_DEVICE_NOT_FOUND 0x01 //! HID device is not opened #define HID_DEVICE_NOT_OPENED 0x02 //! HID device is allready opened #define HID_DEVICE_ALREADY_OPENED 0x03 //! Timeout occurs during transfer #define HID_DEVICE_TRANSFER_TIMEOUT 0x04 //! HID transfer failed #define HID_DEVICE_TRANSFER_FAILED 0x05 //! Invalid handle #define HID_DEVICE_HANDLE_ERROR 0x06 //! Unknown error #define HID_DEVICE_UNKNOWN_ERROR 0xFF //! @} // Enabled only when debugging HID connection issues //#define DEBUG_MODE //****************************************************************************** // //! \brief Device information structure. // //****************************************************************************** struct strHidDevice{ //! Handle for hid device HANDLE hndHidDevice; //! Indicator if device is opened BOOL bDeviceOpen; //! Timeout for GetReport requests UINT uGetReportTimeout; //! Timeout for SetReport requests UINT uSetReportTimeout; //! Asynchronous I/O structure OVERLAPPED oRead; //! Asynchronous I/O structure OVERLAPPED oWrite; //! Maximum length of InReport's WORD wInReportBufferLength; //! Maximum length of OutReport's WORD wOutReportBufferLength; //! InBuffer contains data, if InReport provides more data then the application actual need BYTE inBuffer[8192]; //! Number of current used bytes in inBuffer WORD inBufferUsed; }; //****************************************************************************** // //! A structure that tracks the number of serial numbers // //****************************************************************************** struct strTrackSerialNumbers { //! Index number DWORD deviceNum; //! Serial number of physical device char serialNum[SERNUM_LEN]; }; //****************************************************************************** // //! \addtogroup hiddevice_api //! @{ // //****************************************************************************** //****************************************************************************** // //! \brief Close a HID Device. //! //! This function will close a HID device based on the HID structure //! //! \param pstrHidDevice Structure which contains important data of an HID //! device //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_NOT_OPENED //! \n \b HID_DEVICE_HANDLE_ERROR // //****************************************************************************** BYTE HID_Close(struct strHidDevice* pstrHidDevice); //****************************************************************************** // //! \brief Flush USB buffer for the given device //! //! \param pstrHidDevice Structure which contains important data of an HID //! device. //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_HANDLE_ERROR //! \n \b HID_DEVICE_UNKNOWN_ERROR // //****************************************************************************** BYTE HID_FlushBuffer(struct strHidDevice* pstrHidDevice); //****************************************************************************** // //! \brief Gets the number of HID devices //! //! This function will return the number of interfaces connected with a //! specified VID, PID and serial number, if no devices are connected, //! it will return a 0 //! //! \param vid Vendor-Id of the device //! \param pid Product-Id of the device //! \param numSerNums Total number of connected physical devices //! //! \return Return the number of connected devices with the specific VID, PID, //! and serial number. // //****************************************************************************** DWORD HID_GetNumOfInterfaces(WORD vid, WORD pid, DWORD numSerNums); //****************************************************************************** // //! \brief Gets the number of serial number and serial number list //! //! Scans the HID Devices on the system for any whose VID/PID match the //! ones specified. For every one it finds, it returns that device's //! serial number in serialNumList. Every physical USB device within a //! given VID/PID space has a unique serial number; therefore, each //! item in the list corresponds with a separate physical USB device //! attached to this host; that is, different physical instances of the //! same product or design. The function returns the total number of //! serial numbers found; if none are found, it returns 0. //! //! \param vid Vendor-ID of the device //! \param pid Product-ID of the device //! \param serialNumList List of serial numbers corresponding to the passed //! VID and PID //! //! \return Returns the number of connected physical devices with the specific //! VID and PID // //****************************************************************************** DWORD HID_GetSerNums(WORD vid, WORD pid, struct strTrackSerialNumbers * serialNumList); //****************************************************************************** // //! \brief Returns the version number of a device. //! //! \param pstrHidDevice Structure which contains important data of an HID //! device. //! \param VersionNumber Pointer to USHORT variable. //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_HANDLE_ERROR // //****************************************************************************** BYTE HID_GetVersionNumber(struct strHidDevice* pstrHidDevice, USHORT * VersionNumber); //****************************************************************************** // //! \brief Init structure with default values. //! //! It is important to call HID_Init() before calling HID_Open() to //! avoid unpredictable behavoir. //! //! \param pstrHidDevice Structure which contains important data of a HID //! device //! //! \return None // //****************************************************************************** void HID_Init(struct strHidDevice* pstrHidDevice); //****************************************************************************** // //! \brief This has to be called inside WM_ON_DEVICECHANGE notification window //! //! This function checks if the particular HID device structure is //! still connected or disconnected. //! //! \param pstrHidDevice Structure which contains important data of an HID //! device. //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_HANDLE_ERROR // //****************************************************************************** BOOL HID_IsDeviceAffected(struct strHidDevice* pstrHidDevice); //****************************************************************************** // //! \brief Open a HID Device. //! //! This function opens the HID device associated with the HID interface //! 'deviceIndex' (0-7), on the physical device described by the VID, //! PID, and serial number. //! \param pstrHidDevice Structure which contains important data of an HID //! device //! \param vid Vendor-ID of the device //! \param pid Product-ID of the device //! \param deviceIndex Index of the device.If only one HID is connected, //! deviceIndex is 0. //! - Starts with zero //! - Maximum value is (HID_GetNumOfInterfaces() - 1) //! \param serialNumber Serial number of device to be opened. //! \param totalDevNum Total number of interfaces associated with the //! serial number //! \param totalSerNum Total number of physical devices associated with //! the VID/PID //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_NOT_FOUND //! \n \b HID_DEVICE_ALREADY_OPENED // //****************************************************************************** BYTE HID_Open(struct strHidDevice* pstrHidDevice, WORD vid, WORD pid, DWORD deviceIndex, char serialNumber[SERNUM_LEN], DWORD totalDevNum, DWORD totalSerNum); //****************************************************************************** // //! \brief Reads a data stream from the given HID device. //! //! Prefixed report ID will be skipped. //! //! \param pstrHidDevice Structure which contains important data of an HID //! device //! \param buffer Pointer to buffer in which will be written //! \param bufferSize Number of bytes to read //! \param bytesReturned Number of actual read bytes //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_NOT_OPENED //! \n \b HID_DEVICE_TRANSFER_TIMEOUT //! \n \b HID_DEVICE_TRANSFER_FAILED // //****************************************************************************** BYTE HID_ReadFile(struct strHidDevice* pstrHidDevice, BYTE* buffer, DWORD bufferSize, DWORD* bytesReturned); //****************************************************************************** // //! \brief Registers a device for program Windows notification. //! //! Registers the window pointed to by handle hWnd to receive //! notification when devices are added or removed from the system. //! //! \param hWnd Windows handle //! \param diNotifyHandle Device notification handle pointer address //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_HANDLE_ERROR // //****************************************************************************** BYTE HID_RegisterForDeviceNotification(HWND hWnd, HDEVNOTIFY* diNotifyHandle); //****************************************************************************** // //! \brief Un-Registers a device from Windows notification. //! //! Un-registers the window pointed to by handle hWnd to receive //! notification when devices are added or removed from the system. //! //! \param diNotifyHandle: Device notification handle pointer address. //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_HANDLE_ERROR // //****************************************************************************** BYTE HID_UnRegisterForDeviceNotification(HDEVNOTIFY* diNotifyHandle); //****************************************************************************** // //! \brief Writes a data stream to the given HID device. //! //! Needed report IDs will be generated automatically. //! //! \param pstrHidDevice Structure which contains important data of an HID //! device //! \param buffer Buffer which will be send //! \param bufferSize Number of bytes to send //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_NOT_OPENED //! \n \b HID_DEVICE_TRANSFER_TIMEOUT //! \n \b HID_DEVICE_TRANSFER_FAILED // //****************************************************************************** BYTE HID_WriteFile(struct strHidDevice* pstrHidDevice, BYTE* buffer, DWORD bufferSize);
### 回答1: 模拟USB摄像头是指通过模拟的方式将非USB接口的摄像头模拟成USB接口的摄像头。 在实现模拟USB摄像头功能时,首先需要一个连接电脑的USB转接器或者USB控制器,用于将模拟的摄像头信号转换为USB信号。这样,计算机就能够识别并与摄像头进行通信。 其次,需要通过编程将模拟的摄像头信号进行处理和转发。可以使用C或其他编程语言来实现这个功能。首先,需要编写程序来读取模拟摄像头的信号,例如通过读取视频流。然后,将读取到的信号封装成符合USB协议的数据包,并通过USB转接器或控制器发送给计算机。计算机接收到数据包后,会将其识别为一个USB摄像头,并进行相应的操作,例如显示图像或进行录像等。 值得注意的是,模拟USB摄像头需要保证摄像头的信号与USB摄像头的信号兼容性。这意味着需要通过适当的电路或设备来实现信号的转换和适配。同时,还需要考虑USB接口的传输速率、驱动程序的兼容性等问题,以确保模拟USB摄像头的稳定性和性能。 总之,模拟USB摄像头是一种将非USB摄像头模拟成USB摄像头的技术,通过适当的硬件和软件实现,可以使计算机与非USB摄像头进行通信和操作。这种技术可以扩展和应用于多种领域,例如监控摄像系统、工业检测等。 ### 回答2: C模拟USB摄像头是指通过软件模拟出一个虚拟的USB摄像头设备。 首先,我们需要一个能够将计算机的图像数据输出为视频流的软件。可以通过使用现有的图像处理库,如OpenCV,来实现图像数据的获取和处理。 然后,我们需要将处理后的图像数据传输到虚拟的USB设备中。这可以通过创建一个虚拟的USB摄像头设备驱动程序来实现。我们可以使用一些开发者工具,如libusb和DDK,来构建这个驱动程序。这个驱动程序的作用是将经过处理的图像数据发送给操作系统,使其将其识别为USB摄像头设备。 在创建了虚拟USB设备驱动程序之后,我们需要将它与计算机系统进行连接和安装。这可以通过通过系统管理工具或自定义软件来实现。一旦连接并安装成功,计算机系统就会将其识别为一个真实的USB摄像头设备。 最后,我们可以使用系统自带的应用程序或第三方应用程序来打开并使用这个虚拟的USB摄像头设备。通过这个设备,我们可以进行拍照、录制视频等操作,就像使用真实的USB摄像头一样。 总之,C模拟USB摄像头是一种通过软件模拟出一个虚拟的USB摄像头设备的方法,它可以通过一系列的步骤来实现。这样,我们就可以使用计算机来处理图像数据,并将其传输到虚拟设备中,从而实现类似真实USB摄像头的功能。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值