/*************************************************************************** * 描 述: USBHID设备驱动代码 * 作 者: 詹力 * 时 间: 2016/10/29 ***************************************************************************/ #include #include #include #include #include #include #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这里使用62,DK2一定要使用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 }