#include "stdafx.h" #include "Hid_File.h" #include #include #include #include #include #include #include #include "AutoFunc.h" #pragma comment(lib, "shlwapi.lib") #pragma comment(lib, "hid.lib") //#pragma comment(lib, "hidclass.lib") //#pragma comment(lib, "hidparse.lib") #pragma comment(lib, "setupapi.lib") #define VENDOR_ID 0x413D//test device vendorId #define PRODUCT_ID 0x2107//test device productId #define DEVICE_UNIQ_KEY "mi_02" #define REPORT_ID_EXIST (1) #define REPORT_ID (0x00) #define HID_PACKET_SIZE (17) #define CLIENT_RUNNING_MSG Hid_File::Hid_File() { _hEventObject = CreateEvent( NULL, 0, 0, ""); _hIDOverlapped.hEvent = _hEventObject; _hIDOverlapped.Offset = 0; _hIDOverlapped.OffsetHigh = 0; memset(&_hidDevice, 0, sizeof(HID_DEVICE)); _hidDevice.ReportIDExist = REPORT_ID_EXIST; _hidDevice.ReportID = REPORT_ID; _hidDevice.HidDevice = INVALID_HANDLE_VALUE; } Hid_File::~Hid_File() { CloseHid(); CloseHandle(_hEventObject); } bool Hid_File::OpenHid() { if (_hidDevice.HidDevice != INVALID_HANDLE_VALUE) { CloseHid(); } if (_hidDevice.DevicePath[0] == 0) { if (FindHid() == false) { return false; } } _hidDevice.HidDevice = CreateFile( _hidDevice.DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, //FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if (_hidDevice.HidDevice == INVALID_HANDLE_VALUE) { return false; } return true; } void Hid_File::CloseHid() { if (_hidDevice.HidDevice != INVALID_HANDLE_VALUE) { CloseHandle(_hidDevice.HidDevice); _hidDevice.HidDevice = INVALID_HANDLE_VALUE; } } bool Hid_File::FindHid() { int vendorID = VENDOR_ID; int productID = PRODUCT_ID; DWORD required; GUID hidGuid; HDEVINFO hDevInfo; SP_DEVICE_INTERFACE_DATA devInfoData; int memberIndex = 0; LONG result; bool lastDevice = false; DWORD length; PSP_DEVICE_INTERFACE_DETAIL_DATA detailData = NULL; bool deviceDetected = false; HidD_GetHidGuid(&hidGuid); hDevInfo = SetupDiGetClassDevs (&hidGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); //当应用程序不再需要使用SetupDiGetClassDevs函数的传回值hDevInfo所指的数组时,应该调用SetupDiDeStroyDeviceInfoList函数来释放资源 if (hDevInfo == INVALID_HANDLE_VALUE) { //printf("Failed to open device handle!"); return false; } devInfoData.cbSize = sizeof(devInfoData); do { result = SetupDiEnumDeviceInterfaces( hDevInfo, 0, &hidGuid, memberIndex, &devInfoData); if (result != 0) { result = SetupDiGetDeviceInterfaceDetail( hDevInfo, &devInfoData, NULL, 0, &length, NULL); detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(length); if (!detailData) { //printf("Device information allacation failed!"); return false; } detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); result = SetupDiGetDeviceInterfaceDetail( hDevInfo, &devInfoData, detailData, length, &required, NULL); if (!result) { //printf("Device information reallocation failed!"); free(detailData); break; } _hidDevice.HidDevice = CreateFile( detailData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, //FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); //if (_hidDevice.HidDevice == INVALID_HANDLE_VALUE) //{ // //wirte可以打开,带read属性就不能打开 // _hidDevice.HidDevice = CreateFile( // detailData->DevicePath, // GENERIC_WRITE, // FILE_SHARE_READ | FILE_SHARE_WRITE, // (LPSECURITY_ATTRIBUTES)NULL, // OPEN_EXISTING, // //FILE_ATTRIBUTE_NORMAL, // FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // NULL); //} //printf("Hid:%s\n", detailData->DevicePath); if (_hidDevice.HidDevice == INVALID_HANDLE_VALUE) { free(detailData); memberIndex = memberIndex + 1; continue; } //printf("Opened Hid:%s\n", detailData->DevicePath); _hidDevice.Attributes.Size = sizeof(HIDD_ATTRIBUTES); result = HidD_GetAttributes( _hidDevice.HidDevice, &_hidDevice.Attributes); if ((_hidDevice.Attributes.VendorID == vendorID) && (_hidDevice.Attributes.ProductID == productID) && (StrStr(detailData->DevicePath, DEVICE_UNIQ_KEY) != 0)) { int status; PHIDP_PREPARSED_DATA PreparsedData; //获取USB设备的预解析数据 result = HidD_GetPreparsedData(_hidDevice.HidDevice, &PreparsedData); if (!result) { //printf("无法获取USB设备的预解析数据!"); free(detailData); CloseHid(); break; } deviceDetected = true; //printf("Hid:%s\n", detailData->DevicePath); strcpy_s(_hidDevice.DevicePath,MAX_PATH, detailData->DevicePath); status = HidP_GetCaps(PreparsedData, &_hidDevice.Caps); HidD_FreePreparsedData(PreparsedData); PreparsedData = NULL; CloseHid(); } else { //printf("没有找到设备!"); CloseHid(); } free(detailData); detailData = NULL; } else { lastDevice = true; } memberIndex = memberIndex + 1; } while ((lastDevice == false) && (deviceDetected == false)); SetupDiDestroyDeviceInfoList(hDevInfo); return deviceDetected; } /* *写入数据为MCD设备状态通知,把标识位放在第1位 */ DWORD Hid_File::AddReportID(char *pInputBuff, DWORD BuffLen) { DWORD ret = 0; if (BuffLen + 1 >= MAX_PATH) { return ret; } if (_hidDevice.HidDevice != INVALID_HANDLE_VALUE) { if (_hidDevice.ReportIDExist) { _hidDevice.DataBuff[0] = _hidDevice.ReportID; memcpy(&(_hidDevice.DataBuff[1]), pInputBuff, BuffLen); ret = BuffLen + 1; } } return ret; } bool Hid_File::WriteToHid(char *pInputBuff, DWORD BuffLen) { bool ret = false; Sleep(5); if (OpenHid()) { int result = 0; DWORD numberOfBytesWrite = 0; if (BuffLen > 10) { return ret; } memset(_hidDevice.DataBuff, 0, MAX_PATH); DWORD CopyLen = AddReportID(pInputBuff, BuffLen); //同步WRITE BOOL bWriteStat = WriteFile(_hidDevice.HidDevice, _hidDevice.DataBuff, HID_PACKET_SIZE, &numberOfBytesWrite, 0); if (!bWriteStat) { DWORD error = GetLastError(); printf("HID IO WRITE FAILED.ERROR:%d\n", error); CloseHid(); return ret; } CloseHid(); return true; bWriteStat = WriteFile(_hidDevice.HidDevice, _hidDevice.DataBuff, HID_PACKET_SIZE, &numberOfBytesWrite, (LPOVERLAPPED)&_hIDOverlapped); if (!bWriteStat) { DWORD error = GetLastError(); if (error == ERROR_IO_PENDING) { int waitResult = 0; waitResult = WaitForSingleObject( _hEventObject, MAX_DELAY); switch (waitResult) { case WAIT_OBJECT_0: { if (!GetOverlappedResult(_hidDevice.HidDevice, (LPOVERLAPPED)&_hIDOverlapped, &numberOfBytesWrite, FALSE)) { //getlasterror CancelIo(_hidDevice.HidDevice); } else { //if (numberOfBytesWrite != _hidDevice.Caps.OutputReportByteLength) if (numberOfBytesWrite != HID_PACKET_SIZE) { //Warning!! CancelIo(_hidDevice.HidDevice); } else { ret = true; } } } break; case WAIT_TIMEOUT: { CancelIo(_hidDevice.HidDevice); } break; default: { break; } } //ResetEvent(_hEventObject); } else if (error == WAIT_TIMEOUT) { //timeout CancelIo(_hidDevice.HidDevice); } else { //unknown error CancelIo(_hidDevice.HidDevice); } } else { if (numberOfBytesWrite == HID_PACKET_SIZE) { ret = true; } } CloseHid(); } return ret; } INT Hid_File::ReadFromHid(char *pOutputBuff, DWORD BuffLen,DWORD timeout) { INT ret = -1; Sleep(5); if (OpenHid()) { BOOL result = 0; DWORD numberOfBytesRead; memset(_hidDevice.DataBuff, 0, MAX_PATH); //同步READ result = ReadFile(_hidDevice.HidDevice, _hidDevice.DataBuff, HID_PACKET_SIZE, &numberOfBytesRead, 0); if (!result) { DWORD error = GetLastError(); printf("HID IO READ FAILED.ERROR:%d\n", error); CloseHid(); return ret; } if (numberOfBytesRead == HID_PACKET_SIZE) { //according protocol, //[0] = report ID //[1] = packet size unsigned char PacketLen = (unsigned char)_hidDevice.DataBuff[1]; memcpy(pOutputBuff, &(_hidDevice.DataBuff[1]), PacketLen); ret = PacketLen; } CloseHid(); return ret; result = ReadFile(_hidDevice.HidDevice, _hidDevice.DataBuff, HID_PACKET_SIZE, &numberOfBytesRead, (LPOVERLAPPED)&_hIDOverlapped); if (!result) { DWORD error = GetLastError(); if (error == ERROR_IO_PENDING) { int waitResult = 0; waitResult = WaitForSingleObject( _hEventObject, timeout); switch (waitResult) { case WAIT_OBJECT_0: { if (!GetOverlappedResult(_hidDevice.HidDevice, (LPOVERLAPPED)&_hIDOverlapped, &numberOfBytesRead, FALSE)) { //getlasterror CancelIo(_hidDevice.HidDevice); } else { //if (numberOfBytesWrite != _hidDevice.Caps.OutputReportByteLength) if (numberOfBytesRead != HID_PACKET_SIZE) { //Warning!! CancelIo(_hidDevice.HidDevice); } else { ret = numberOfBytesRead; } } } break; case WAIT_TIMEOUT: { // CancelIo(_hidDevice.HidDevice); } break; default: { break; } } } else if (error == WAIT_TIMEOUT) { //timeout //CancelIo(_hidDevice.HidDevice); } else { //unknown error CancelIo(_hidDevice.HidDevice); } } else { if (numberOfBytesRead == HID_PACKET_SIZE) { ret = numberOfBytesRead; } } CloseHid(); } if (ret == HID_PACKET_SIZE) { //according protocol, //[0] = report ID //[1] = packet size unsigned char PacketLen = (unsigned char)_hidDevice.DataBuff[1]; memcpy(pOutputBuff, &(_hidDevice.DataBuff[1]), PacketLen); ret = PacketLen; } return ret; }