usb hid 设备

这段代码实现了一个USB设备类,用于根据vid和pid搜索并打开USB设备。通过SetupDiGetClassDevs和SetupDiEnumDeviceInfo遍历设备,找到匹配的设备后,使用CreateFile打开设备。还包含了读写设备的基本操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#pragma once
#ifndef USB_DEVICE_H
#define USB_DEVICE_H


class UsbDevice
{
    int mvid;
    int mpid;
    void* dev_handler;
    bool usb_ok = false;
public:
    UsbDevice();
    ~UsbDevice();
    int open(int pid, int vid);
    int close();
    int write(const unsigned char* buf, const int l);
    int read(unsigned char* buf, const int l, const int timeout_ms);
    int reconnect();

private:
    static void*  getDeviceHandle(unsigned short vendor, unsigned short product, unsigned int MI = 0x0000);
    static bool    IsMatchingDevice(wchar_t *pDeviceID, unsigned int uiVID, unsigned int uiPID, unsigned int uiMI);
};

#endif

///---------------------------------------------usbdevice.cpp--------------------------------------------------------

///------------------------------------------------------------------------------------------------------------------------


#include <cstdio>
#include <sstream>
#include <wchar.h>
#include <string.h>
#include <Windows.h>
#include <hidsdi.h>
#include <SetupAPI.h>
#include <cfgmgr32.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include <iostream>
#include <string>
#include <Windows.h>
#include "UsbDevice.h"

#pragma comment(lib, "hid.lib")
#pragma comment(lib, "setupapi.lib")

HANDLE UsbDevice::getDeviceHandle(unsigned short uiVID, unsigned short uiPID, unsigned int uiMI) {
    printf("Attempting to open: vid=%04x pid=%04x mid=%04x\n", uiVID, uiPID, uiMI);
    const GUID GUID_DEVINTERFACE_HID = { 0x4D1E55B2L, 0xF16F, 0x11CF, 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 };
    HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_HID, 0, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
    //std::cout << hDevInfo << std::endl;
    if (hDevInfo == INVALID_HANDLE_VALUE)
        return 0;

    HANDLE hReturn = 0;

    SP_DEVINFO_DATA deviceData = { 0 };
    deviceData.cbSize = sizeof(SP_DEVINFO_DATA);

    for (unsigned int i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &deviceData); ++i) {
        wchar_t wszDeviceID[MAX_DEVICE_ID_LEN];
        if (CM_Get_Device_IDW(deviceData.DevInst, wszDeviceID, MAX_DEVICE_ID_LEN, 0))
            continue;

        if (!IsMatchingDevice(wszDeviceID, uiVID, uiPID, uiMI))
            continue;

        SP_INTERFACE_DEVICE_DATA interfaceData = { 0 };
        interfaceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);

        if (!SetupDiEnumDeviceInterfaces(hDevInfo, &deviceData, &GUID_DEVINTERFACE_HID, 0, &interfaceData))
            break;

        DWORD dwRequiredSize = 0;
        SetupDiGetDeviceInterfaceDetail(hDevInfo, &interfaceData, 0, 0, &dwRequiredSize, 0);

        SP_INTERFACE_DEVICE_DETAIL_DATA *pData = (SP_INTERFACE_DEVICE_DETAIL_DATA *)new unsigned char[dwRequiredSize];
        pData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);

        if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &interfaceData, pData, dwRequiredSize, 0, 0))
        {
            delete pData;
            break;
        }

        // get device handle(with and without overlapping mode)
        HANDLE hDevice = CreateFile(pData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, NULL, 0);
        //HANDLE hDevice = CreateFile(pData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);

        if (hDevice == INVALID_HANDLE_VALUE)
        {
            delete pData;
            printf("    Failed open: vid=%04x pid=%04x mid=%04x\n", uiVID, uiPID, uiMI);
            break;
        }

        hReturn = hDevice;
        printf("!!! Opened: vid=%04x pid=%04x mid=%04x\n", uiVID, uiPID, uiMI);
        break;
    }

    SetupDiDestroyDeviceInfoList(hDevInfo);

    return hReturn;
}

//void UsbDevice::readDataFromDevice(HANDLE hFile, unsigned char* buf, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped = NULL) {
//    ReadFile(hFile, buf, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
//}

bool UsbDevice::IsMatchingDevice(wchar_t *pDeviceID, unsigned int uiVID, unsigned int uiPID, unsigned int uiMI) {
    unsigned int uiLocalVID = 0, uiLocalPID = 0, uiLocalMI = 0;
    LPWSTR pszNextToken = 0;
    LPWSTR pszToken = wcstok(pDeviceID, L"\\#&");
    while (pszToken) {
        std::wstring tokenStr(pszToken);
        if (tokenStr.find(L"VID_", 0, 4) != std::wstring::npos) {
            std::wistringstream iss(tokenStr.substr(4));
            iss >> std::hex >> uiLocalVID;
        }
        else if (tokenStr.find(L"PID_", 0, 4) != std::wstring::npos) {
            std::wistringstream iss(tokenStr.substr(4));
            iss >> std::hex >> uiLocalPID;
        }
        else if (tokenStr.find(L"MI_", 0, 3) != std::wstring::npos) {
            std::wistringstream iss(tokenStr.substr(3));
            iss >> std::hex >> uiLocalMI;
        }
        pszToken = wcstok(0, L"\\#&");
    }
    if (uiVID != uiLocalVID || uiPID != uiLocalPID || uiMI != uiLocalMI)
        return false;
    return true;
}


UsbDevice::UsbDevice() {
    usb_ok = false;
    mvid = 0;
    mpid = 0;
    dev_handler = 0;
}
UsbDevice::~UsbDevice() {
    close();
}
int UsbDevice::open(int vid, int pid) {
    mvid = vid;
    mpid = pid;
    dev_handler = getDeviceHandle(vid, pid);
    if (dev_handler == 0) {
        usb_ok = false;
        return -1;
    }
    usb_ok = true;
    return 1;
}


int UsbDevice::reconnect() {
    if (!usb_ok) {
        if (open(mvid, mpid) < 0)
            return -1;
        else
            return 1;
    }
    return 1;
}


int UsbDevice::close() {
    if (dev_handler) {
        int res = CloseHandle(dev_handler);
        if (res) {
            dev_handler = 0;
            usb_ok = false;
        }
        return res;
    }

    return 0;
}

int UsbDevice::write(const unsigned char* buf, const int l) {

    DWORD bytes_written=-1;
    unsigned char innerbuf[65];
    memset(innerbuf, 0, sizeof(innerbuf));
    if (l <= sizeof(innerbuf)) {
        memcpy(innerbuf, buf, l);
    } else {
        memcpy(innerbuf, buf, sizeof(innerbuf));
    }

    BOOL res = WriteFile(dev_handler, innerbuf, sizeof(innerbuf), &bytes_written,0);
    if (res == 0) {
        printf("WriteFile error=%d\n", (int)GetLastError());
    }
    FlushFileBuffers(WriteFile);
//    if (!res) {
//        if (GetLastError() != ERROR_IO_PENDING) {
//            /* WriteFile() failed. Return error. */
//            bytes_written = -1;
//            goto end_of_function;
//        }
//    }
//    /* Wait here until the write is done. This makes
//       hid_write() synchronous. */
//    res = GetOverlappedResult(dev_handler, &ol, &bytes_written, TRUE/*wait*/);
//    if (!res) {
//        /* The Write operation failed. */
//        bytes_written = -1;
//        goto end_of_function;
//    }
//end_of_function:

    return bytes_written;
}
int UsbDevice::read(unsigned char* buf, const int l, const int timeout_ms) {
    DWORD read_byte = 0;
    //readDataFromDevice(dev_handler, buf, l, &read_byte);
    if (0 == ReadFile(dev_handler, buf, l, &read_byte, 0)) {
        return -1;
    }
    return read_byte;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值