BOOL Cusbhid::ReadDatafromHidDevice(int devicepid, int devicevid, CString* readdata)
{
        CString temp = NULL;
        DWORD strSize = 0,requiredSize = 0;
        BOOL result1, result2, success;
        //定义一些变量,以后会用到
        SP_DEVINFO_DATA DeviceInfoData;
        SP_DEVICE_INTERFACE_DATA  DeviceInterfaceData;
        PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData;
        //PSP_DEVICE_INTERFACE_DETAIL_DATA test;
        HIDD_ATTRIBUTES devAttr;
        PHIDP_PREPARSED_DATA PreparsedData;
        HIDP_CAPS Capabilities;
        //第一步:获取deviceID
        GUID deviceId;
        HidD_GetHidGuid(&deviceId);        //第二步:获取设备信息
        HDEVINFO handle;        
        handle = SetupDiGetClassDevs(&deviceId, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); //Get only HID devices
        
        //第三步:对所有的设备进行枚举
        //SetupDiEnumDeviceInterfaces();
        result1 = false; //定义一些变量
        result2 = false;
        success = false;        int index = 0;        do
        {
                DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
                result1 = SetupDiEnumDeviceInterfaces(
                                                                                                        handle,
                                                                                                        NULL, // IN PSP_DEVINFO_DATA  DeviceInfoData,  OPTIONAL
                                                                                                        &deviceId,
                                                                                                        index++,
                                                                                                        &DeviceInterfaceData        //指定设备的信息
                                                                                         );
                if(result1)
                {
                                                        
                        //获得设备详细数据(获取详细信息所需的存储空间)
                        SetupDiGetDeviceInterfaceDetail(
                                                                                                handle,
                                                                                                &DeviceInterfaceData,
                                                                                                NULL,
                                                                                                0,
                                                                                                &strSize,
                                                                                                NULL
                                                                                        );                        requiredSize = strSize;
                        DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(requiredSize);
                        DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
                        DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);                        //再次获得详细数据
                        SetupDiGetDeviceInterfaceDetail(
                                                                                                handle,
                                                                                                &DeviceInterfaceData,
                                                                                                DeviceInterfaceDetailData,
                                                                                                strSize,
                                                                                                &requiredSize,
                                                                                                &DeviceInfoData
                                                                                        );                        //获得设备路径(最重要的部分)
                        temp = DeviceInterfaceDetailData->DevicePath;
                        free(DeviceInterfaceDetailData);                        HANDLE hCom = CreateFile(
                                                                                 temp,
                                                                                 GENERIC_READ | GENERIC_WRITE,
                                                                                 FILE_SHARE_READ | FILE_SHARE_WRITE,
                                                                                 NULL,
                                                                                 OPEN_EXISTING, 
                                                                                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
                                                                                 NULL
                                                                        );
                        if(hCom == INVALID_HANDLE_VALUE) continue;
                        
                        devAttr.Size = sizeof(HIDD_ATTRIBUTES);                        if (!HidD_GetAttributes(hCom,&devAttr))
                        {
                                CloseHandle(hCom);
                                continue;
                        }
                        if((devicepid != devAttr.ProductID) || (devicevid != devAttr.VendorID))
                        {
                                CloseHandle(hCom);
                                continue;
                        }                        
                        if(!HidD_GetPreparsedData(hCom,&PreparsedData))
                        {
                                CloseHandle(hCom);
                                continue;
                        }
                        if(!HidP_GetCaps(PreparsedData,&Capabilities))
                        {
                                CloseHandle(hCom);
                                continue;
                        }
                        int readsize = Capabilities.InputReportByteLength;
                        unsigned long numbytesreturned;
                        unsigned char *readbuffer = (unsigned char *)malloc(readsize); 
                        memset(readbuffer, 0, readsize);
                        OVERLAPPED Overlapped;  
                        Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);  
                        Overlapped.Offset = 0;  
                        Overlapped.OffsetHigh = 0;
                        if(ReadFile(hCom, readbuffer, readsize, &numbytesreturned, &Overlapped))
                        {
                                free(readbuffer);
                                CloseHandle(hCom);
                                success = true;
                                break;
                        }
                        free(readbuffer);
                        CloseHandle(hCom);
                }        
        }while(result1);        return success;
}上面是我需要在线程里开启的循环读取指定HID设备上传的数据;但现在遇到两个问题:
1、unsigned char *readbuffer = (unsigned char *)malloc(readsize); 动态分配的内存在ReadFile函数出错,程序崩溃,为什么?是分配的内存小了?但是我使用局部定义一样大小的数组就没问题
2、当ReadFile使用同步读取数据时每次都能够成功读取(即用NULL替换掉CrearFile的FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED和ReadFile的&Overlapped),但是当使用异步读取时偶尔能读到数据,但大部分时间经常读不到数据,为什么?难道是数据上传后还未执行到ReadFile时执行了什么函数将缓冲区的数据清空了,但是在ReadFile死等也读不到数据
上面的问题都是都是确保确实有IN数据,麻烦大牛们给解释下,谢谢

解决方案 »

  1.   

    你不会每次执行读都要对设备枚举一下,一锤子买卖?
    异步USB读写在初始化时建立设备连接和读、写事件响应线程,按读写事件响应相应的操作。例// 创建USB设备连接
    void CHidUsbThread::BuildConnectUSB(CString devName)
    {
    // ==========  取设备句柄  ===========
    hDev=OpenDevice(devName);
    if(hDev==INVALID_HANDLE_VALUE)
    {
    // 无效的句柄
    ErrorReport(DEV_HANDLE_NULL);
    return;
    }
    // =======  创建USB读线程  =======
    if(!BulidReadEvent())
    {
    // 读事件线程创建失败
    ErrorReport(READ_EVENT_BULID_FAILED);
    return;
    }
    // =======  创建USB写事件线程  =======
    if(!BulidWriteEvent())
    {
    // 写事件线程创建失败
    ErrorReport(WRITE_EVENT_BULID_FAILED);
    return;
    }
    //===========  报告设备连接成功  ============
    ShowDeviceStatus(true);
    }