GeekIMU/4.Software/GeekIMUDriver 1.1/Src/USB_Win32_HIDDevice.c

246 lines
6.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/***************************************************************************
* 描 述: USBHID设备驱动代码
* 作 者: 詹力
* 时 间: 2016/10/29
***************************************************************************/
#include <Windows.h>
#include <Dbt.h>
#include <hidsdi.h>
#include <SetupAPI.h>
#include <stdio.h>
#include <usbioctl.h>
#include "USB_Win32_HIDDevice.h"
#include "MagCalibrate.h"
#include "SensorImpl.h"
#pragma comment(lib,"setupapi.lib")
#pragma comment(lib, "hid.lib")
unsigned char usb_output_buffer[65];
unsigned char usb_input_buffer[256];
unsigned char usb_feature_report_buffer[256];
unsigned char buffer[255];
/* 主函数,程序的入口 */
HANDLE dematrix_usb_handle = INVALID_HANDLE_VALUE;
HDEVINFO device_info_set;
GUID HidGuid;
SP_DEVICE_INTERFACE_DATA device_interface_data;
HIDP_CAPS dematrix_device_capabilities;
HANDLE DM_HID_Read_HANDLE;
HANDLE DM_HID_Write_HANDLE;
int i=5;
BOOL device_is_found;
OVERLAPPED usb_read_over_lapped;
PSP_DEVICE_INTERFACE_DETAIL_DATA pData;
BOOL HIDFindDeviceFromVendor(USHORT PID,USHORT VID,CHAR *Path)
{
HANDLE DM_USB_HANDLE;
HIDD_ATTRIBUTES Dev_Attr;
Dev_Attr.Size = sizeof(Dev_Attr);
DM_USB_HANDLE = CreateFileA(Path, (DWORD)NULL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, (DWORD)NULL, NULL);
if(DM_USB_HANDLE != INVALID_HANDLE_VALUE)
{
if (HidD_GetAttributes(DM_USB_HANDLE, &Dev_Attr) == FALSE) return FALSE;
HidD_GetNumInputBuffers(DM_USB_HANDLE, &i);
//printf("BufferSize[%d]\n",i);
dematrix_usb_get_capabilities(DM_USB_HANDLE);
//printf("Cap.out.length[%d]\n", dematrix_device_capabilities.OutputReportByteLength);
//printf("(PID=%x,VID=%x,VersionTest=%x)\n", Dev_Attr.ProductID, Dev_Attr.VendorID, Dev_Attr.VersionNumber);
if (Dev_Attr.ProductID == PID && Dev_Attr.VendorID == VID)
{
//printf("(PID=%x,VID=%x,VersionTest=%x)\n", Dev_Attr.ProductID, Dev_Attr.VendorID, Dev_Attr.VersionNumber);
return TRUE;
}
}
return FALSE;
}
BOOL InitPathFromInterfaceData(HDEVINFO hdevInfoSet, SP_DEVICE_INTERFACE_DATA* pidata)
{
DWORD detailSize = 0;
BOOL Result;
Result = SetupDiGetDeviceInterfaceDetail(hdevInfoSet,pidata, NULL, (DWORD)NULL, &detailSize, NULL);
pData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(detailSize);
if (pData == NULL){
printf("内存不足!\n");
SetupDiDestroyDeviceInfoList(hdevInfoSet);
return FALSE;
}
pData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
Result = SetupDiGetDeviceInterfaceDetail(hdevInfoSet, pidata, pData, detailSize, NULL, NULL);
if(Result==TRUE)
{
//printf("Path = %s\n",(char *)(pData->DevicePath));
return TRUE;
}
return FALSE;
}
/*给定USB设备,对USB设备进行枚举如果PID和VID都符合就打开USB设备并创建句柄*/
BOOL DM_HIDDeviceEnumerate(USHORT PID,USHORT VID)
{
HDEVINFO hdevInfoSet;
SP_DEVICE_INTERFACE_DATA interfaceData;
int deviceIndex = 0;
interfaceData.cbSize = sizeof(interfaceData);
/* 先取得GUID */
HidD_GetHidGuid(&HidGuid);
hdevInfoSet = SetupDiGetClassDevs(&HidGuid, NULL, NULL, DIGCF_INTERFACEDEVICE | DIGCF_PRESENT);
if (hdevInfoSet == INVALID_HANDLE_VALUE) return FALSE;
for(deviceIndex = 0;
SetupDiEnumDeviceInterfaces(hdevInfoSet, NULL, &HidGuid, deviceIndex, &interfaceData);
deviceIndex++)
{
//printf("index = %d\n",deviceIndex);
if (!InitPathFromInterfaceData(hdevInfoSet, &interfaceData))
continue;
// 下面的函数需要路径
if(HIDFindDeviceFromVendor(PID,VID,(CHAR*)(pData->DevicePath)))
{
//printf("Path = %s\n",(char *)(pData->DevicePath));
DM_HID_Read_HANDLE = CreateFileA((char *)(pData->DevicePath), (DWORD)GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ |
FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
DM_HID_Write_HANDLE = CreateFileA((char *)(pData->DevicePath), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, 0, NULL);
device_is_found = TRUE;
SetEvent(usb_read_over_lapped.hEvent);
printf("打开设备成功!\n");
break;
}else
continue;
}
SetupDiDestroyDeviceInfoList(hdevInfoSet);
if(device_is_found==TRUE)return TRUE;
else
return FALSE;
}
void USB_HID_Init()
{
//初始化读报告时用的Overlapped结构体
//偏移量设置为0
usb_read_over_lapped.Offset = 0;
usb_read_over_lapped.OffsetHigh = 0;
//创建一个事件提供给ReadFile使用当ReadFile完成时
//会设置该事件为触发状态。
usb_read_over_lapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
start_thread(dematrix_usb_private_read_thread, NULL);
}
int globalpacklen = 0;
DWORD dematrix_usb_private_read_thread(LPVOID param)
{
DWORD length;
//该线程是个死循环,直到程序退出时,它才退出
while (1)
{
//设置事件为无效状态
ResetEvent(usb_read_over_lapped.hEvent);
//如果设备已经找到
if (device_is_found == TRUE)
{
if (DM_HID_Read_HANDLE == INVALID_HANDLE_VALUE) {
printf("无效的读报告句柄,可能是打开设备时失败");
}
else {
CancelIo(DM_HID_Read_HANDLE);
// DKHD2这里使用62DK2一定要使用64否则无法读取数据
ReadFile(DM_HID_Read_HANDLE, usb_input_buffer,globalpacklen, NULL, &usb_read_over_lapped);
}
//等待事件触发
WaitForSingleObject(usb_read_over_lapped.hEvent, INFINITE);
//如果等待过程中设备被拔出也会导致事件触发但此时MyDevFound
//被设置为假因此在这里判断MyDevFound为假的话就进入下一轮循环。
if (device_is_found == FALSE) continue;
//如果设备没有被拔下则是ReadFile函数正常操作完成。
//通过GetOverlappedResult函数来获取实际读取到的字节数。
GetOverlappedResult(DM_HID_Read_HANDLE, &usb_read_over_lapped, &length, TRUE);
//如果字节数不为0则将读到的数据显示到信息框中
if (length != 0)
{
int useful_length = usb_input_buffer[1];
GetControllerSensor(usb_input_buffer);
}
}
else {
//阻塞线程,直到下次事件被触发
WaitForSingleObject(usb_read_over_lapped.hEvent, INFINITE);
}
}
return 0;
}
void dematrix_usb_get_capabilities(HANDLE hid_usb_handle)
{
PHIDP_PREPARSED_DATA PreparsedData;
if (hid_usb_handle == NULL) return;
HidD_GetPreparsedData(hid_usb_handle, &PreparsedData);
HidP_GetCaps(PreparsedData, &dematrix_device_capabilities);
HidD_FreePreparsedData(PreparsedData);
}
DWORD start_thread(void *function_address, void *param)
{
DWORD temp;
#ifdef _WIN32
HANDLE hThread;
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)function_address, param, 0, &temp);
if (hThread != NULL) return (DWORD)hThread;
else return 0x00;
#else
#ifdef linux
pthread_t hThread;
int Result;
Result = pthread_create(&hThread, NULL, (void *)function_address, param);
if (Result != NULL) return Result;
else return -NULL;
#endif
#endif
}