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資料,麻煩大牛們給解釋下,謝謝
uj5u.com熱心網友回復:
你不會每次執行讀都要對設備列舉一下,一錘子買賣?異步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);
}
uj5u.com熱心網友回復:
如果每次執行都列舉是不是會有問題?
uj5u.com熱心網友回復:
你不覺的這是資源浪費嗎?還會影響運行速度。uj5u.com熱心網友回復:
我想問的是如果撇開執行效率速度的問題,這樣做對讀取資料有沒有什么致命的影響,比如說資料讀取不到等等,謝謝
uj5u.com熱心網友回復:
是有可能讀取不到的, 這個完全要看驅動怎么做. 看驅動里,在設備關閉時是否要清除已有但未被讀走的資料.
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/42146.html
標籤:基礎類
