C++ MFC界面读写USB HID设备数据程序
生活随笔
收集整理的這篇文章主要介紹了
C++ MFC界面读写USB HID设备数据程序
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
C++ MFC界面讀寫USB HID設備數據程序 發一個簡單易用的界面,用來對USB HID設備(比如說游戲手柄,控制面板等)讀寫數據,一般情況下面板上有一些LED,可以幫助我們測試讀寫是否正確。另外,需要可以修改vendorID和prodcutID,這樣一個界面,可以用于測試多個HID設備。
過程分成3步:1: 列舉出所有的HID設備,2: 循環讀取HID設備數據,3: 向HID設備寫數據,下面我把三部分的程序單獨分開,方便大家學習!
在講具體程序之前,先說一下visual studio的環境配置(我用的是2008版本)!
<下面程序需要包含DDK一部分頭文件和庫文件>
第一步:列舉所有的HID設備:
```cpp m_ctllHIDdevices.ResetContent(); //這是MFC里面一個list控件,用來顯示所有的HID設備的,如果你沒有界面,可以不需要此行 UpdateData(FALSE); //更新界面 CString temp; int Count = 0; //Total number of devices found DWORD strSize=0,requiredSize=0; BOOL result1,result2; ULONG DeviceInterfaceDetailDataSize; //定義一些變量,以后會用到 SP_DEVINFO_DATA DeviceInfoData; SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData; //PSP_DEVICE_INTERFACE_DETAIL_DATA test; //第一步:獲取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; CString temp11=""; do {DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);result1 = SetupDiEnumDeviceInterfaces(handle,NULL, // IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL&deviceId,Count,&DeviceInterfaceData);//獲得設備詳細數據(初步)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);//再次獲得詳細數據result2=SetupDiGetDeviceInterfaceDetail(handle,&DeviceInterfaceData,DeviceInterfaceDetailData,strSize,&requiredSize,&DeviceInfoData);//獲得設備路徑(最重要的部分)temp=DeviceInterfaceDetailData->DevicePath;UpdateData(FALSE);m_ctllHIDdevices.AddString(temp);Count++;} while (result1);UpdateData(false);到這個時候為止,所有的設備路徑,都會顯示在窗口的listbox里面!第二步:循環讀取HID設備數據(根據用戶提供的HID的vendorID和productID),并且把字節解碼成二進制,在MFC界面上用LED展示:為了不影響主線程的運行,我把讀取數據的操作,放在一個子線程里!每隔50ms去讀取一次數據!首先創建一個線程:HANDLE hThread1;bStopHID=false; //這個變量,以后用來停止線程UpdateData(true); //更新界面,獲取變量UpdateData(false);hThread1 = CreateThread(NULL,0,Thread_Enable_Read,(LPVOID)this, NULL, NULL);在線程的程序里:CusbhidDlg *p = ( CusbhidDlg *)pvParam; //獲取主窗口的指針,用來調用主窗口的變量和函數p->UpdateData(true);p->bStopHID=false;CString temp;CString DevicePath;temp="";int Count = 0; //Total number of devices foundDWORD strSize=0,requiredSize=0;BOOL result1,result2;ULONG DeviceInterfaceDetailDataSize; SP_DEVINFO_DATA DeviceInfoData;SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData;//PSP_DEVICE_INTERFACE_DETAIL_DATA test;//1GUID deviceId;HidD_GetHidGuid(&deviceId);int venderID=p->v_eVendorID; //從窗口里獲取用戶輸入的VendorIDint productID=p->v_eProductID;//從窗口里獲取用戶輸入的ProductIDunsigned char inbuffer[2]; //用來存放讀取的數據,請在這里定義你自己需要的長度,我每次讀一個字節進來unsigned long numBytesReturned;HIDD_ATTRIBUTES devAttr;PHIDP_PREPARSED_DATA PreparsedData;HIDP_CAPS Capabilities;int readValue;bool LED;int flag=0;//2HDEVINFO handle;handle = SetupDiGetClassDevs(&deviceId, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); //Get only HID devicesint i=0;int j=p->m_ctllHIDdevices.GetCount();for (i=0;i<p->m_ctllHIDdevices.GetCount();i++){p->m_ctllHIDdevices.GetText(i,temp);DevicePath=temp;//CreateFile是非常重要的一步,用來建立于HID通信的句柄HANDLE hCom = CreateFile (DevicePath,GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING, 0,NULL);if (hCom == INVALID_HANDLE_VALUE){ //AfxMessageBox("Invalide Device Path...");continue;}devAttr.Size=sizeof(HIDD_ATTRIBUTES);if (!HidD_GetAttributes(hCom,&devAttr)){CloseHandle(hCom);AfxMessageBox("Cannot get the parameters of the HID...");return 0; }//temp.Format("Vendor ID: %d, Product ID:%d",devAttr.VendorID,devAttr.ProductID); //Compare with the Vendor ID and Product ID from Nakamura-san//AfxMessageBox(temp);if (!HidD_GetPreparsedData(hCom,&PreparsedData)){CloseHandle(hCom);AfxMessageBox("Cannot get the Preparsed Data...");return 0; }if(!HidP_GetCaps(PreparsedData,&Capabilities)){CloseHandle(hCom);AfxMessageBox("Cannot get the Cap Data...");return 0; }if (devAttr.VendorID == venderID && devAttr.ProductID == productID) {while(1){result1 = ReadFile(hCom, &inbuffer[0], Capabilities.InputReportByteLength, &numBytesReturned, 0);temp=inbuffer;//p->m_eDataRead=CString(inbuffer);//p->UpdateData(false);if(!result1){AfxMessageBox("Cannot Read Data...");return 0; }readValue=inbuffer[1];p->m_eDataRead.Format("%d",readValue);//下面是我把數據從10進制轉換成二進制,并且點亮LED (一個字節有8個bits,可以點亮8個LEDfor (int k=0;k<8;k++){flag=readValue%2;readValue=readValue/2; if (k==0){if (flag==0)p->m_sDynLED0.SwitchOff();elsep->m_sDynLED0.SwitchOn();}else if (k==1){if (flag==0)p->m_sDynLED1.SwitchOff();elsep->m_sDynLED1.SwitchOn();}else if (k==2){if (flag==0)p->m_sDynLED2.SwitchOff();elsep->m_sDynLED2.SwitchOn();}else if (k==3){if (flag==0)p->m_sDynLED3.SwitchOff();elsep->m_sDynLED3.SwitchOn();}else if (k==4){if (flag==0)p->m_sDynLED4.SwitchOff();elsep->m_sDynLED4.SwitchOn();}else if (k==5){if (flag==0)p->m_sDynLED5.SwitchOff();elsep->m_sDynLED5.SwitchOn();}else if (k==6){if (flag==0)p->m_sDynLED6.SwitchOff();elsep->m_sDynLED6.SwitchOn();}else if (k==7){if (flag==0)p->m_sDynLED7.SwitchOff();elsep->m_sDynLED7.SwitchOn();}}p->UpdateData(false);::Sleep(50);//判斷用戶是否點擊停止按鈕,若是,則退出if(p->bStopHID) {AfxMessageBox("stopped...");return 0;}}}}if (i==j){AfxMessageBox("There is no such HID device...");}return 0;第三步:向HID設備寫數據(根據用戶提供的HID的vendorID和productID),用戶輸入的是二進制數據:與讀的程序一樣,唯一區別就是紅色那部分!UpdateData(true); bStopHID=false;CString temp; CString DevicePath; temp=""; int Count = 0; //Total number of devices found DWORD strSize=0,requiredSize=0; BOOL result1,result2; ULONG DeviceInterfaceDetailDataSize; SP_DEVINFO_DATA DeviceInfoData; SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData; //PSP_DEVICE_INTERFACE_DETAIL_DATA test; //1 GUID deviceId; HidD_GetHidGuid(&deviceId);int venderID=v_eVendorID; int productID=v_eProductID;unsigned char inbuffer[2]; unsigned long numBytesReturned; HIDD_ATTRIBUTES devAttr; PHIDP_PREPARSED_DATA PreparsedData; HIDP_CAPS Capabilities; int readValue; bool LED; int flag=0; inbuffer[0]=0; //把界面里的二進制轉換成10進制 inbuffer[1]=m_eByte0*1+m_eByte1*2+m_eByte2*4+m_eByte3*8+m_eByte4*16+m_eByte5*32+m_eByte6*64+m_eByte7*128;v_eDataToWrite=inbuffer[1]; UpdateData(false);//2 HDEVINFO handle; handle = SetupDiGetClassDevs(&deviceId, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); //Get only HID devices int i=0; int j=m_ctllHIDdevices.GetCount(); for (i=0;i<m_ctllHIDdevices.GetCount();i++) {m_ctllHIDdevices.GetText(i,temp);DevicePath=temp;HANDLE hCom = CreateFile (DevicePath,GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING, 0,NULL);if (hCom == INVALID_HANDLE_VALUE){ //AfxMessageBox("Invalide Device Path...");continue;}devAttr.Size=sizeof(HIDD_ATTRIBUTES);if (!HidD_GetAttributes(hCom,&devAttr)){CloseHandle(hCom);AfxMessageBox("Cannot get the parameters of the HID...");return; }//temp.Format("Vendor ID: %d, Product ID:%d",devAttr.VendorID,devAttr.ProductID); //Compare with the Vendor ID and Product ID from Nakamura-san//AfxMessageBox(temp);if (!HidD_GetPreparsedData(hCom,&PreparsedData)){CloseHandle(hCom);AfxMessageBox("Cannot get the Preparsed Data...");return; }if(!HidP_GetCaps(PreparsedData,&Capabilities)){CloseHandle(hCom);AfxMessageBox("Cannot get the Cap Data...");return; }// Write Fileif (devAttr.VendorID == venderID && devAttr.ProductID == productID) {result1 = WriteFile(hCom, inbuffer, 2, &numBytesReturned, NULL);//temp=inbuffer;//p->m_eDataRead=CString(inbuffer);//p->UpdateData(false);if(!result1){AfxMessageBox("Cannot Write Data...");return; }AfxMessageBox("Suncess...");break;} } if (i==j) {AfxMessageBox("There is no such HID device..."); } return; 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的C++ MFC界面读写USB HID设备数据程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 软件和硬件的关系以及软件调动硬件的工作原
- 下一篇: USB的pid和vid以及usb路径名字