C++MFC界面读写USBHID设备数据程序文件
- 格式:doc
- 大小:42.00 KB
- 文档页数:12
第一步:列举所有的HID设备:(); .");continue;}=sizeof(HIDD_ATTRIBUTES);if (!HidD_GetAttributes(hCom,&devAttr)){CloseHandle(hCom);AfxMessageBox("Cannot get the parameters of the HID..."); return 0;}.");return 0;}if(!HidP_GetCaps(PreparsedData,&Capabilities)){CloseHandle(hCom);AfxMessageBox("Cannot get the Cap Data...");return 0;}if == venderID && == productID){while(1){result1 = ReadFile(hCom, &inbuffer[0], , &numBytesReturned, 0); temp=inbuffer;.");return 0;readValue=inbuffer[1];p->("%d",readValue);.");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; .");continue;}=sizeof(HIDD_ATTRIBUTES);if (!HidD_GetAttributes(hCom,&devAttr)){CloseHandle(hCom);AfxMessageBox("Cannot get the parameters of the HID...");return;}.");return;if(!HidP_GetCaps(PreparsedData,&Capabilities)) {CloseHandle(hCom);AfxMessageBox("Cannot get the Cap Data..."); return;}.");return;}AfxMessageBox("Suncess...");break;}}if (i==j){AfxMessageBox("There is no such HID device..."); }return;。
由于要写个游戏工具方便编程,要用到文件类的操作,看到这篇文章不错,特转载计算机室如何管理自身所存放着的大量的信息的呢?windows的磁盘管理程序为我们提供了一套严密而又高效的信息组织形式--硬盘上的信息是以文件的形式被管理的。
面向存储的文件技术什么是文件?计算机中,一篇文章、一幅图片、一个程序等都是以文件的形式存储在磁盘上的,每个文件都有一个文件名。
计算机就是对文件按名存取的。
文件名的格式如下:主文件名.扩展名。
为什么要在程序中使用文件?通常,程序中的数据在程序运行结束之后,就会从内存中清除,再次运行程序时不会自动出现。
在编制程序的过程中不可避免的会遇到将某些数据永久保存的问题,当程序关闭后,依然可以使用这些数据,这时就需要进行文件操作。
文件类型Visual C++处理的文件通常分为两种:文本文件:只可被任意文本编辑器读取ASCII文本。
二进制文件:指对包含任意格式或无格式数据的文件的统称。
这里只介绍文本文件的读写,INI文件也属于文本文件的范畴,且INI文件的结构和用途与普通的文本文件不同,所以会单独介绍。
第一部分:文本文件文本文件的读写认识CFile类;认识文本文件;能够正确灵活应用文本文件存取信息;避免文本文件读写的常见误区。
CFile是MFC的文件操作基本类,它直接支持无缓冲的二进制磁盘I/O操作,并通过其派生类支持文本文件、内存文件和socket文件。
客户操作记录实例功能预览及关键知识点许多系统,出于安全或其他原因,常常要求随时对键盘进行监控,利用Hook(钩子)技术编写的应用程序能够很好地达到这个目的。
本软件就制作了一个客户操作记录软件,即在软件运行过程中,用户在键盘上的按键操作会被记录下来,这样对维护软件的正常运行非常有利。
只要启动客户操作记录软件后,不管输入焦点是否在本软件上,按键都会被记录下来。
我们需要的是键盘的系统监控,只要本软件在运行,无论当前计算机在做什么,都能监测到用户按键的行为并做出反应,这就要用到Hook技术。
用VC++实现USB接口读写数据的程序用VC++实现USB接口读写数据的程序使用一个GUIDguidHID_1查找并打开一个USB设备extern "C" int PASCAL SearchUSBDevice(){HANDLE hUsb;int nCount, i, j;//标记同一设备个数HDEVINFO hDevInfoSet;BOOL bResult;PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail =NULL;memset(m_sysversion, 0, 20);GetSysVersion(m_sysversion);// 检索相关GUID的USB设备总设备个数if (!GetUSBList()){return 0;}// 取得一个该GUID相关的设备信息集句柄hDevInfoSet = ::SetupDiGetClassDevs((LPGUID)&guidHID_1,//GUID_CLASS_USB_DEVICE, // class GUIDNULL, // 无关键字NULL, // 不指定父窗口句柄DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); // 目前存在的设备// 失败...if (hDevInfoSet == INVALID_HANDLE_VALUE){return NULL;}// 申请设备接口数据空间nCount = 0;bResult = TRUE;for (i=0; i< 34; i++){bDeviceOpen = FALSE;memset(m_DeviceDesc, 0, 256);}SP_DEVICE_INTERFACE_DATA ifdata;// 设备序号=0,1,2... 逐一测试设备接口,到失败为止while (bResult){ifdata.cbSize = sizeof(ifdata);// 枚举符合该GUID的设备接口bResult = ::SetupDiEnumDeviceInterfaces(hDevInfoSet, // 设备信息集句柄NULL, // 不需额外的设备描述(LPGUID)&guidHID_1,//GUID_CLASS_USB_DEVICE, // GUID(ULONG)nCount, // 设备信息集里的设备序号&ifdata); // 设备接口信息if (bResult){ULONG predictedLength = 0;ULONG requiredLength = 0;// 取得该设备接口的细节(设备路径)bResult = SetupDiGetInterfaceDeviceDetail(hDevInfoSet, // 设备信息集句柄&ifdata, // 设备接口信息NULL, // 设备接口细节(设备路径)0, // 输出缓冲区大小&requiredLength, // 不需计算输出缓冲区大小(直接用设定值)NULL); // 不需额外的设备描述// 取得该设备接口的细节(设备路径)predictedLength=requiredLength;// if(pDetail)// {// pDetail =NULL;// }pDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA)::GlobalAlloc(LMEM_ZEROINIT, predictedLength);pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);bResult = SetupDiGetInterfaceDeviceDetail(hDevInfoSet, // 设备信息集句柄&ifdata, // 设备接口信息pDetail, // 设备接口细节(设备路径)predictedLength, // 输出缓冲区大小&requiredLength, // 不需计算输出缓冲区大小(直接用设定值)NULL); // 不需额外的设备描述if (bResult){// 复制设备路径到输出缓冲区//::strcpy(pszDevicePath[nCount], pDetail->DevicePath);if (strcmp(m_sysversion, "winnt")==0){char ch[18];for(i=0;i<17;i++){ch=*(pDetail->DevicePath+8+i);}ch[17]='\0';if (strcmp(ch,"vid_0471&pid_0666")==0)//比较版本号,防止意外出错{memset( &READ_OS, 0, sizeof( OVERLAPPED ) ) ;memset( &WRITE_OS, 0, sizeof( OVERLAPPED ) ) ;READ_OS.hEvent = CreateEvent( NULL, // no securityTRUE, // explicit reset reqFALSE, // initial event resetNULL ) ; // no nameif (READ_OS.hEvent == NULL){break;}WRITE_OS.hEvent = CreateEvent( NULL, // no securityTRUE, // explicit reset reqFALSE, // initial event resetNULL ) ; // no nameif (NULL == WRITE_OS.hEvent){CloseHandle( READ_OS.hEvent );break;}hUsb=CreateFile(pDetail->DevicePath,//&guidHID_1,//GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL/*|FILE_FLAG_OVERLAPPED*/,NULL);if (hUsb != NULL){// 比较定位找到的USB在哪个USB PORT上char id[30];memset(id, 0, 30);i=0;do{id=*(pDetail->DevicePath+26+i);i++;}while(id!='#');id = '\0';for (j=0; j<34; j++){if(strcmp(id, m_USBList[j])==0){sprintf(m_DeviceDesc[j+1], "%s", pDetail->DevicePath); m_USBPositionMap[nCount] = j+1;break;}}CloseHandle(hUsb);nCount++;// break;}}// 比较驱动版本}// 比较操作系统版本else{memset( &READ_OS, 0, sizeof( OVERLAPPED ) ) ;memset( &WRITE_OS, 0, sizeof( OVERLAPPED ) ) ;READ_OS.hEvent = CreateEvent( NULL, // no security TRUE, // explicit reset reqFALSE, // initial event resetNULL ) ; // no nameif (READ_OS.hEvent == NULL){break;}WRITE_OS.hEvent = CreateEvent( NULL, // no securityTRUE, // explicit reset reqFALSE, // initial event resetNULL ) ; // no nameif (NULL == WRITE_OS.hEvent){CloseHandle( READ_OS.hEvent );break;}hUsb=CreateFile(pDetail->DevicePath,//&guidHID_1,// GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL/*|FILE_FLAG_OVERLAPPED*/,NULL);if (hUsb != NULL){if(strcmp(pDetail->DevicePath, m_USBList[j])==0){sprintf(m_DeviceDesc[j+1], "%s", pDetail->DevicePath); m_USBPositionMap[nCount] = j+1;break;}CloseHandle(hUsb);nCount++;// break;}}}}}// 释放设备接口数据空间::GlobalFree(pDetail);// 关闭设备信息集句柄::SetupDiDestroyDeviceInfoList(hDevInfoSet); iDeviceCount = nCount;return nCount;}// 写BOOL Writestr(char *buf,int buflen, int index){BOOL fWriteStat;DWORD dwErrorFlags;DWORD dwError;COMSTAT ComStat;char szError[ 10 ] ;DWORD ret;int len, i, j, packet;div_t div_result;BYTE sendpacket[65];BYTE xorcode="0x00";if (m_gphdCom[index] == NULL) // no usb device(jk100c) {return -1;}div_result = div(buflen, 58);if (div_result.rem == 0){packet = div_result.quot;}else{packet = div_result.quot+1;}for (i=0; i<packet; i++){memset(sendpacket, 0, 65);if(i==packet-1){// end packetif (div_result.rem == 0){len = 58;}else{len = div_result.rem;}}else{len = 58;}sendpacket[0] = 0x13;sendpacket[1] = 3+len;sendpacket[2] = 0x01;sendpacket[3] = packet*16+i+1;memcpy(sendpacket+4, buf+(i*58), len);for(j=0;j<len+3;j++){xorcode^=sendpacket[j+1];}sendpacket[len+4] = (char)xorcode;sendpacket[len+5] = 0x23;PurgeComm(m_gphdCom[index],PURGE_RXCLEAR|PURGE_TXCLEAR);// Sleep(10);fWriteStat = WriteFile(m_gphdCom[index], sendpacket, len+6,&ret, NULL); if (!fWriteStat){if(GetLastError() == ERROR_IO_PENDING){dwError = GetLastError();// an error occurred, try to recoverwsprintf( szError, "\n\r <CE-%u>", dwError ) ;OutputDebugString(szError);ClearCommError(m_gphdCom[index], &dwErrorFlags, &ComStat ) ;if (dwErrorFlags >0){wsprintf( szError, "\n\r <CE-%u>", dwErrorFlags ) ; OutputDebugString(szError);}}else{// some other error occurredClearCommError(m_gphdCom[index], &dwErrorFlags, &ComStat ) ;if (dwErrorFlags > 0){wsprintf( szError, "\n\r <CE-%u>", dwErrorFlags ) ; OutputDebugString(szError);}return FALSE;}}if (i != packet-1){// should be receive ackif (ReceivePacketAnswer(index) != 0){return FALSE;}}}return TRUE;}// 读int Readstr(char *buf,int nMaxLength, int index){BOOL fReadStat ;COMSTAT ComStat;DWORD dwErrorFlags;DWORD dwLength;DWORD dwError;char szError[ 10 ];if (fCOMMOpened==0){return FALSE; //串口未打开}// only try to read number of bytes in queueClearCommError(m_gphdCom[index], &dwErrorFlags, &ComStat) ;//dwLength = min( (DWORD) nMaxLength, ComStat.cbInQue ) ;dwLength=nMaxLength;if (dwLength > 0){if (olap==TRUE){fReadStat = ReadFile(m_gphdCom[index],buf, dwLength, &dwLength,&READ_OS) ; if (!fReadStat){if (GetLastError() == ERROR_IO_PENDING){OutputDebugString("\n\rIO Pending");while(!GetOverlappedResult(m_gphdCom[index], &READ_OS,&dwLength, TRUE )){dwError = GetLastError();if(dwError == ERROR_IO_INCOMPLETE) continue;else{// an error occurred, try to recoverClearCommError(m_gphdCom[index],&dwErrorFlags, &ComStat ) ;break;}}}else // end-----if (GetLastError() == ERROR_IO_PENDING){// some other error occurreddwLength = 0 ;ClearCommError(m_gphdCom[index], &dwErrorFlags, &ComStat ) ;if (dwErrorFlags >0){wsprintf( szError, "\n\r <CE-%u>", dwErrorFlags ) ;OutputDebugString(szError);}}} // end-----if (!fReadStat)} // end-----if (olap==TRUE)else{fReadStat = ReadFile( m_gphdCom[index],buf, dwLength, &dwLength, NULL ) ; if (!fReadStat){dwError = GetLastError();ClearCommError(m_gphdCom[index],&dwErrorFlags, &ComStat ) ;if (dwErrorFlags >0){wsprintf( szError, "\n\r <CE-%u>", dwErrorFlags ) ;OutputDebugString(szError);}}PurgeComm(m_gphdCom[index],PURGE_RXCLEAR|PURGE_TXCLEAR);}}return dwLength;。
第一步:列举所有的HID设备:m_ctllHIDdevices、ResetContent(); //这就是MFC里面一个list控件,用来显示所有的HID设备的,如果您没有界面,可以不需要此行UpdateData(FALSE); //更新界面CString temp;int Count = 0; //Total number of devices foundDWORD strSize=0,requiredSize=0;BOOL result1,result2;ULONG DeviceInterfaceDetailDataSize;//定义一些变量,以后会用到SP_DEVINFO_DA TA DeviceInfoData;SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData;//PSP_DEVICE_INTERFACE_DETAIL_DATA test;//第一步:获取deviceIDGUID 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_DA TA 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=s第一步:列举所有的HID设备:m_ctllHIDdevices、ResetContent(); //这就是MFC里面一个list控件,用来显示所有的HID设备的,如果您没有界面,可以不需要此行UpdateData(FALSE); //更新界面CString temp;int Count = 0; //Total number of devices foundDWORD strSize=0,requiredSize=0;BOOL result1,result2;ULONG DeviceInterfaceDetailDataSize;//定义一些变量,以后会用到SP_DEVINFO_DA TA DeviceInfoData;SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData;//PSP_DEVICE_INTERFACE_DETAIL_DATA test;//第一步:获取deviceIDGUID 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_DA TA 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);izeof(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);第二步:循环读取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_DA TA 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 == INV ALID_HANDLE_V ALUE){//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 foundDWORD strSize=0,requiredSize=0;BOOL result1,result2;ULONG DeviceInterfaceDetailDataSize;SP_DEVINFO_DA TA 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=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);//2HDEVINFO handle;handle = SetupDiGetClassDevs(&deviceId, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); //Get only HID devicesint 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 == INV ALID_HANDLE_V ALUE){//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;。
MFC和C++关于文件的读写操作以及文件的打开和保存通过近来的学习,总结一下关于C++开发中文件的读写操作以及文件的打开和保存的方法。
一、文件的读写操作:(1)C语言对文件的读写操作在C语言中,对文件的读写操作是用FILE结构体和常用的对文件操作的函数实现的,下面总结一下C语言中对文件操作的常用函数:fopen() 打开以文件名指定的文件fwrite() 写文件fread() 读文件fseek() 移动文件的指针到新的位置通过该函数的参数设定的偏移量和初始位置rewind() 移动文件的指针到文件流的开始位置,在通常情况下可用fseek()实现相同的功能,但二者有区别ftell() 获得当前文件指针的位置,常用该函数获得文件的文件流的长度fflush() 刷新缓冲区中的内容,当文件写入时直接将文件流的内容从缓冲区写入磁盘,当读取文件时直接将磁盘文件写入缓冲区,而不必等程序运行结束或关闭程序。
fclose() 关闭文件memset() 在一段内存块中填充某个给定的值示例代码如下:/*********************************************************** C语言实现文件写操作 ************************************************************/FILE *pFile=fopen("CLanguage.txt","w");fwrite("CLanguage",1,strlen("CLanguage"),pFile);//fseek(pFile,0,SEEK_SET);//fwrite("实现文件写操作",1,strlen("实现文件写操作"),pFile);fclose(pFile);/*********************************************************** C语言实现文件读操作 ************************************************************/FILE *pFile=fopen("CLanguage.txt","r");//char ch[100];//memset(ch,0,100);//fread(ch,1,100,pFile);//MessageBox(ch);char* pBuf;int length;fseek(pFile,0,SEEK_END);length=ftell(pFile);pBuf=new char[length+1];//fseek(pFile,0,SEEK_SET);rewind(pFile);fread(pBuf,1,length,pFile);pBuf[length]=0;MessageBox(pBuf);fclose(pFile);注意:在用C语言实现文件的读操作时,要注意文件的指针位置。
第一步:列举所有的HID设备:m_ctllHIDdevices.ResetContent(); //这是MFC里面一个list控件,用来显示所有的HID 设备的,如果你没有界面,可以不需要此行UpdateData(FALSE); //更新界面CString 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;//第一步:获取deviceIDGUID 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=s第一步:列举所有的HID设备:m_ctllHIDdevices.ResetContent(); //这是MFC里面一个list控件,用来显示所有的HID 设备的,如果你没有界面,可以不需要此行UpdateData(FALSE); //更新界面CString 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;//第一步:获取deviceIDGUID 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);izeof(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);第二步:循环读取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 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=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);//2HDEVINFO handle;handle = SetupDiGetClassDevs(&deviceId, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); //Get only HID devicesint 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;。
第一步:列举所有的HID设备:m_ctllHIDdevices.ResetContent(); //这是MFC里面一个list控件,用来显示所有的HID设备的,如果你没有界面,可以不需要此行UpdateData(FALSE); //更新界面CString temp;int Count = 0; //Total number of devices foundDWORD strSize=0,requiredSize=0;BOOL result1,result2;ULONG DeviceInterfaceDetailDataSize;//定义一些变量,以后会用到SP_DEVINFO_DA TA DeviceInfoData;SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData;//PSP_DEVICE_INTERFACE_DETAIL_DATA test;//第一步:获取deviceIDGUID 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_DA TA);result1 = SetupDiEnumDeviceInterfaces(handle,NULL, // IN PSP_DEVINFO_DA TA 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=s第一步:列举所有的HID设备:m_ctllHIDdevices.ResetContent(); //这是MFC里面一个list控件,用来显示所有的HID设备的,如果你没有界面,可以不需要此行UpdateData(FALSE); //更新界面CString temp;int Count = 0; //Total number of devices foundDWORD strSize=0,requiredSize=0;BOOL result1,result2;ULONG DeviceInterfaceDetailDataSize;//定义一些变量,以后会用到SP_DEVINFO_DA TA DeviceInfoData;SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData;//PSP_DEVICE_INTERFACE_DETAIL_DATA test;//第一步:获取deviceIDGUID 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_DA TA);result1 = SetupDiEnumDeviceInterfaces(handle,NULL, // IN PSP_DEVINFO_DA TA 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_DA TA);//再次获得详细数据result2=SetupDiGetDeviceInterfaceDetail(handle,&DeviceInterfaceData,DeviceInterfaceDetailData,strSize,&requiredSize,&DeviceInfoData);//获得设备路径(最重要的部分)temp=DeviceInterfaceDetailData->DevicePath;UpdateData(FALSE);m_ctllHIDdevices.AddString(temp);Count++;} while (result1);UpdateData(false);izeof(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);第二步:循环读取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_DA TA 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 == INV ALID_HANDLE_V ALUE){//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 foundDWORD strSize=0,requiredSize=0;BOOL result1,result2;ULONG DeviceInterfaceDetailDataSize;SP_DEVINFO_DA TA 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=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);//2HDEVINFO handle;handle = SetupDiGetClassDevs(&deviceId, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); //Get only HID devicesint 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 == INV ALID_HANDLE_V ALUE){//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;。
USB HID设备读写代码实现c++ 收藏源代码如下:(生成.dll .lib)1.MCDInterface.h/**MCDInterface.h*author:*data:*/#ifndef MCDBOX_H_INCLUDED#define MCDBOX_H_INCLUDED#pragma once#define MCD_IOCTRL_OPEN_SIG 0x1001#define MCD_IOCTRL_CLOSE_SIG 0x1002#define MCD_IOCTRL_FIND_SIG 0x1003#define MCD_IOCTRL_READY 0x1003#define MCD_IOCTRL_UNREADY 0x1004#define KEY_0 0x3A#define KEY_1 0x3B#define KEY_2 0x3C#define KEY_3 0x3D#define KEY_4 0x3E#define KEY_5 0x3F#define KEY_6 0x40#define KEY_7 0x41#define KEY_8 0x42#define KEY_9 0x43#define KEY_STAR 0x44#define KEY_POUND 0x45#define MSG_HOOKOFF 0x16#define MSG_HOOKON 0x12#define MSG_RINGING 0x15#define HID_DEVICE_REMOVE 0x76 //硬件被移走#define CLIENT_READY_WRITE_SIG 0x92 //通知设备软件正在运行,每隔一段时间向缓冲区写该数据#define DLL_EXPORT __declspec(dllexport)#define DLL_IMPORT __declspec(dllimport)//定义用于回调的枚举消息enum{MCD_CALLBACK_MSG_VERSION,//not usedMCD_CALLBACK_MSG_SERIALNO,//not usedMCD_CALLBACK_DEVICE_FOUND,MCD_CALLBACK_DEVICE_NOT_FOUND,MCD_CALLBACK_DEVICE_REMOVE,MCD_CALLBACK_KEYDOWN,MCD_CALLBACK_KEYBUFFER_CHANGED,MCD_CALLBACK_HOOKOFF,MCD_CALLBACK_HOOKON,MCD_CALLBACK_RINGING,MCD_CALLBACK_MSG_WARNING = -2,MCD_CALLBACK_MSG_ERROR = -1,};DLL_EXPORT unsigned long MCD_DeviceIoControl(unsigned long dwIoControlCode,void* lpInBuffer = 0, unsigned long nInBufferSize = 0,void* lpOutBuffer = 0, unsigned long nOutBufferSize = 0);//定义设备状态返回信息enum{MCD_RETURN_SUCCESS = 0,MCD_RETURN_FOUND_HID,MCD_RETURN_NO_FOUND_HID,MCD_RETURN_HID_IS_OPENED,//?MCD_RETURN_HID_NO_OPEN,//?};#endif // MCDBOX_H_INCLUDED2.mcdHid.h#ifndef MCDHID_H_INCLUDED#define MCDHID_H_INCLUDEDextern "C"{#include "setupapi.h"#include "hidsdi.h"#include "dbt.h"}typedef struct _HID_DEVICE {PCHAR DevicePath;HANDLE HidDevice; // A file handle to the hid device.HIDP_CAPS Caps; // The Capabilities of this hid device.HIDD_ATTRIBUTES Attributes;} HID_DEVICE, *PHID_DEVICE;class MCDHid{public:static MCDHid & getInstance(){static MCDHid mcdHid;return mcdHid;}MCDHid(MCDHid & mcdHid);MCDHid & operator=(MCDHid &mcdHid);~MCDHid();unsigned long openMCDHid();void closeMCDHid();void startComm(void * pParam);int writeToHid();int readFromHid();char * getHidDeviceName(){return _hidDeviceName;}bool findMCDHid();HID_DEVICE* getHidDevice(){return & _hidDevice;}bool getUsbCommRunning(){return _fUsbCommRunning;}bool getOffHookSignal(){return _offHookSignal;}unsigned long getDataWaitProcess(){return _dataWaitProcess;}void setUsbCommRunning(bool usbCommRunning) {_fUsbCommRunning = usbCommRunning;}unsigned char _inputReportBuffer[9];unsigned char _outputReportBuffer[2];private:MCDHid();void copy(MCDHid & mcdHid);char *_hidDeviceName;HANDLE _hEventObject;OVERLAPPED _hIDOverlapped;HID_DEVICE _hidDevice;bool _fUsbCommRunning;bool _offHookSignal;unsigned long _dataWaitProcess;unsigned long _inputReportByteLength;unsigned long _outputReportByteLength;};#endif // MCDHID_H_INCLUDED3.mcdHid.cpp/*mcdhid.cppfunction: open HID device ,close HID device ,read data from HID device , write data to HID deviceauthor:date:version:*/#include <stdlib.h>#include <windows.h>#include <stdio.h>#include "mcdhid.h"#include "MCDInterface.h"#include "mcdbox.h"#include "pthread.h"void *getDataThread(void *pParam);#define VENDOR_ID 0x1241//test device vendorId#define PRODUCT_ID 0xe001//test device productId#define CLIENT_RUNNING_MSGMCDHid::MCDHid(){_hidDeviceName = "MCD Human Interface Device";_fUsbCommRunning = false;_offHookSignal = false;_dataWaitProcess = 1;memset(_inputReportBuffer,0,sizeof(_inputReportBuffer));memset(_outputReportBuffer,0,sizeof(_outputReportBuffer));}MCDHid::MCDHid(MCDHid & mcdHid){copy(mcdHid);}MCDHid & MCDHid::operator=(MCDHid & mcdHid){copy(mcdHid);return *this;}void MCDHid::copy(MCDHid & mcdHid){_hidDeviceName = mcdHid._hidDeviceName;_hEventObject = mcdHid._hEventObject;_hIDOverlapped = mcdHid._hIDOverlapped;_hidDevice = mcdHid._hidDevice;_fUsbCommRunning = mcdHid._fUsbCommRunning;_offHookSignal = mcdHid._offHookSignal;_dataWaitProcess = mcdHid._dataWaitProcess;_inputReportByteLength = mcdHid._inputReportByteLength;_outputReportByteLength = mcdHid._outputReportByteLength; for(int i = 0; i<s izeof(_inputReportBuffer); i++){_inputReportBuffer[i] = mcdHid._inputReportBuffer[i];}for(int i = 0; i<s izeof(_outputReportBuffer); i++){_inputReportBuffer[i] = mcdHid._outputReportBuffer[i];}}MCDHid::~MCDHid(){}unsigned long MCDHid::openMCDHid(){if(findMCDHid()){//采用重叠传输方式//if( _hEventObject == 0)// {_hEventObject = CreateEvent(NULL,true,true,"");_hIDOverlapped.hEvent = _hEventObject;_hIDOverlapped.Offset = 0;_hIDOverlapped.OffsetHigh =0;// }return MCD_RETURN_SUCCESS;}elsereturn MCD_RETURN_NO_FOUND_HID;}void MCDHid::closeMCDHid(){CloseHandle(_hidDevice.HidDevice);_hidDevice.HidDevice = INVALID_HANDLE_VALUE;}void MCDHid::startComm(void *pParam){int thr_id;pthread_t m_processT;if((thr_id=pthread_create(&m_processT, NULL, getDataThread, pParam) != 0)){//printf("pthread_create error:%s\n", strerror(thr_id));return;}}bool MCDHid::findMCDHid(){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!");return false;}_hidDevice.HidDevice = CreateFile(detailData->DevicePath,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,(LPSECURITY_ATTRIBUTES)NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);_hidDevice.Attributes.Size = sizeof(HIDD_ATTRIBUTES);result = HidD_GetAttributes(_hidDevice.HidDevice,&_hidDevice.Attributes);if ((_hidDevice.Attributes.VendorID == vendorID) &&(_hidDevice.Attributes.ProductID == productID)){int status;PHIDP_PREPARSED_DATA PreparsedData ;deviceDetected = true;//获取USB设备的预解析数据result =HidD_GetPreparsedData(_hidDevice.HidDevice,&PreparsedData);if(!result){//printf("无法获取USB设备的预解析数据!");return false;}status= HidP_GetCaps(PreparsedData, &_hidDevice.Caps); _fUsbCommRunning = true;HidD_FreePreparsedData(PreparsedData);PreparsedData = NULL;}else//printf("没有找到设备!");closeMCDHid();}free(detailData);detailData = NULL;}else{lastDevice = true;}memberIndex = memberIndex + 1;}while((lastDevice == false)&&(deviceDetected == false));SetupDiDestroyDeviceInfoList(hDevInfo);return deviceDetected;}/**写入数据为MCD设备状态通知,把标识位放在第1位*/int MCDHid::writeToHid(){return 0;}int MCDHid::readFromHid()//int readFromHid(){if(_hidDevice.HidDevice != INVALID_HANDLE_VALUE){int result = 0;DWORD numberOfBytesRead;result = ReadFile(_hidDevice.HidDevice,&_inputReportBuffer,_hidDevice.Caps.InputReportByteLength,&numberOfBytesRead,(LPOVERLAPPED)&_hIDOverlapped);_inputReportByteLength = _hidDevice.Caps.InputReportByteLength; }int waitResult = 0;waitResult = WaitForSingleObject(_hEventObject,10);switch(waitResult)case WAIT_OBJECT_0: break;case WAIT_TIMEOUT:{CancelIo(_hidDevice.HidDevice);break;}default:{break;}}ResetEvent(_hEventObject);return 0;}/************************************************************* **************启动一个读取数据线程,读取数据为拨打电话号码*启动一个写入数据线程, 写入数据为MCD设备状态通知,现在还没有写数据************************************************************** *************/void *getDataThread(void *pParam){MCDBox *ht = (MCDBox *)pParam;MCDHid *hr = &(MCDHid::getInstance());while(hr->getUsbCommRunning())//USB设备running,并且有摘机信号{hr->readFromHid();//readFromHid();//printf("获取缓冲区的数据\n");if(hr->getDataWaitProcess() > 0)//可以定义_dataWaitProcess为一次拨号数据的长度{unsigned long i = 0;for(i = 0; i < 9; i++){ht->_inputReportBuffer[i] = hr->_inputReportBuffer[i];//printf("read data from device is:%d\n",ht->_inputReportBuffer[1]);}ht->processData();memset(hr->_inputReportBuffer,0,sizeof(hr->_inputReportBuffer));//printf("数据处理!\n");}int status = 0;//PHIDP_PREPARSED_DATA PreparsedData ;//status = HidD_GetPreparsedData(_hidDevice.HidDevice,&PreparsedData); status = HidD_GetAttributes(hr->getHidDevice()->HidDevice,&hr->getHidDevice()->Attributes);if(!status){hr->setUsbCommRunning(false);memset(ht->_inputReportBuffer,0,sizeof(ht->_inputReportBuffer));ht->_inputReportBuffer[2] = HID_DEVICE_REMOVE;ht->processData();printf("设备移走!");//return false;break;}//HidD_FreePreparsedData (PreparsedData);// PreparsedData = NULL;Sleep(100);}return 0;}4.mcdbox.h#ifndef MCDMAIN_H_INCLUDED#define MCDMAIN_H_INCLUDEDclass MCDHid;class MCDCallBack;class MCDBox{public:static MCDBox & getInstance(){static MCDBox mcdBox;return mcdBox;}~MCDBox();unsigned long deviceIOControl(unsigned long dwIoControlCode,void* lpInBuffer, unsigned long nInBufferSize,void* lpOutBuffer, unsigned long nOutBufferSize);void findDevice(void* lpInBuffer, unsigned long nInBufferSize,void* lpOutBuffer, unsigned long nOutBufferSize);unsigned long openDevice(void* lpInBuffer, unsigned long nInBufferSize, void* lpOutBuffer, unsigned long nOutBufferSize);void closeDevice();void processData();unsigned char _inputReportBuffer[9];unsigned char _outputReportBuffer[9];unsigned long _inputBufferByteLength;unsigned long _outputBufferByteLength;bool isDeviceOpen(){return _openDevice;}void setDeviceOpen(bool deviceOpen){_openDevice = deviceOpen;}private:MCDBox();char * _mcdHidName;unsigned long _mcdStatus;MCDHid & _mcdHid;MCDCallBack &_mcdCallback;bool _openDevice;//char _key;};/**定义回调函数*/typedef void (*CALLBACK_MCDBOX)(void* wParam, void* lParam, unsigned long ParameterOfApp);class MCDCallBack{public:static MCDCallBack & getInstance(){static MCDCallBack mcdCallback;return mcdCallback;}MCDCallBack(MCDCallBack & mcdCallback);MCDCallBack & operator=(MCDCallBack & mcdCallback);virtual ~MCDCallBack();void create(void* pCallBackFunction = 0, unsigned long dwParameterOfApplication = 0);void callBack(unsigned long wParam,void* lParam = 0);private:MCDCallBack();void copy(MCDCallBack & mcdCallback);struct {CALLBACK_MCDBOX func;unsigned long lParam;}_fCallBack;};//extern MCDCallBack mcdCallBack;#endif // MCDMAIN_H_INCLUDED5.cpp/*mcdbox.cppfunction description: 数据处理接口author:date:version:*/#ifndef MCDBOX_CPP_INCLUDED#define MCDBOX_CPP_INCLUDED#include <windows.h>#include <stdio.h>#include "mcdbox.h"#include "MCDInterface.h"#include "mcdhid.h"#include "pthread.h"void *findDeviceThread(void *param);unsigned long MCD_DeviceIoControl(unsigned long dwIoControlCode,void* lpInBuffer, unsigned long nInBufferSize,void* lpOutBuffer, unsigned long nOutBufferSize) {unsigned long br = 0;MCDBox *ht = (MCDBox *)&(MCDBox::getInstance());//MCDBox ht = getInstance();;try{br =ht->deviceIOControl(dwIoControlCode,lpInBuffer,nInBufferSize,lpOutBuffer,n OutBufferSize);}catch (unsigned long BytesReturned){br = BytesReturned;}return br;}MCDBox::MCDBox():_mcdHid(MCDHid::getInstance()),_mcdCallback(MCDCallBack::getInstance()){_openDevice =false;_inputBufferByteLength = 8;_outputBufferByteLength = 8;for (int i = 0; i < (int)_inputBufferByteLength; i++){_inputReportBuffer[i] = 0;}for (int j = 0;j < (int)_outputBufferByteLength; j++){_outputReportBuffer[j] = 0;}}MCDBox::~MCDBox(){}unsigned long MCDBox::deviceIOControl(unsigned long dwIoControlCode,void* lpInBuffer, unsigned long nInBufferSize,void* lpOutBuffer, unsigned long nOutBufferSize) {switch (dwIoControlCode){case MCD_IOCTRL_FIND_SIG:findDevice(lpInBuffer,nInBufferSize,lpOutBuffer,nOutBufferSize);break;case MCD_IOCTRL_CLOSE_SIG:if (_openDevice){closeDevice();}_mcdHid.closeMCDHid();_openDevice = false;return 0;case MCD_IOCTRL_OPEN_SIG:if (_openDevice)return MCD_RETURN_HID_IS_OPENED;openDevice(lpInBuffer,nInBufferSize,lpOutBuffer,nOutBufferSize);break;//case CLIENT_READY_WRITE_SIG://软件运行正常,通知硬件设备// _mcdHid.writeToHid();// return 0;default:if (!_openDevice) return MCD_RETURN_HID_NO_OPEN;break;}return 0;}void MCDBox::findDevice(void* lpInBuffer, unsigned long nInBufferS ize,void* lpOutBuffer, unsigned long nOutBufferSize) {pthread_t m_processT;int threadID;_mcdCallback.create(lpInBuffer,nInBufferSize);if((threadID=pthread_create(&m_processT, NULL, findDeviceThread, this) != 0)){return ;}}unsigned long MCDBox::openDevice(void* lpInBuffer, unsigned long nInBufferSize,void* lpOutBuffer, unsigned long nOutBufferSize) {_mcdCallback.create(lpInBuffer,nInBufferSize);unsigned long dwReturnValue = _mcdHid.openMCDHid();if(dwReturnValue == MCD_RETURN_SUCCESS){_openDevice = true;// _mcdCallback.create(lpInBuffer,nInBufferSize);_mcdStatus = MCD_IOCTRL_READY;//_mcdHid.writeToHid();//软件运行正常,通知硬件设备//_key = 0;_mcdHid.startComm(this);_mcdHidName = _mcdHid.getHidDeviceName();}else{_mcdHid.closeMCDHid();}return dwReturnValue;}void MCDBox::closeDevice(){_mcdHid.closeMCDHid();}/************************************************************* *******************/***读取缓冲区,第二个字节为有效数据,buffer size = 8bytes。
VC++6.0 中使用libUsb库进行Hid USB设备通讯1、首先在/wiki/libusb-win32#下载得到libusb-win32库和一些例子,插上需通讯的HID USB设备,打开下载的库,里面有个可执行文件,运行它,根据提示(注意PID和VID选好你所插的设备)生成inf文件并安装它。
2、完成上一步就可以打开vc++6.0 开发应用程序和HID USB设备通讯了,注意要把与刚才生成的inf文件同文件夹下的lib文件、dll文件和usb.h文件添加到工程文件夹下,并在Project-》Settings-》Link下的Object/library modules 中添加libusb.lib库文件,还有添加usb.h头文件。
3、程序中用到的全局变量:#define MY_VID 0x8888#define MY_PID 0x0006usb_dev_handle *handle;HANDLE m_hDevice=INVALID_HANDLE_VALUE;CWinThread *m_pReadReportThread=NULL;OVERLAPPED ReadOverlapped;char ReadReportBuffer[16]={0};BYTE KeyStatus=0;volatile BOOL m_bReadReportRunFlag=FALSE;4、然后在OnInitDialog()下添加如下代码:struct usb_bus *busses, *bus;// usb_dev_handle *handle = NULL; //这个需定义为全局变量,在读线程中也许使用usb_init();usb_find_busses();usb_find_devices();busses = usb_get_busses();for(bus = busses; bus; bus = bus->next) {struct usb_device *dev;for(dev = bus->devices; dev; dev = dev->next) {struct usb_device_descriptor *desc = &(dev->descriptor);if((desc->idVendor == 0x8888) && (desc->idProduct == 0x0006)) { handle = usb_open(dev);if (!handle ){MessageBox("error opening device: \n%s\n", usb_strerror());return false;}}}}usb_set_configuration(handle,1);usb_claim_interface(handle,0);这是libusb的初始化代码,接下来就可以读写USB数据了。
如何编写应用程序与USB HID 设备通讯(读写USB HID设备)说明:本实例所使用的上位机程序开发工具为Visual C++6.0。
一、修改下位机固件程序我们如果想实现一个USB的HID类设备,不需要在Windows下开发自己的驱动程序。
HID 不一定要是标准的外设类型,唯一的要求是交换的数据存储在报文的结构内,设备固件必须支持报文的格式。
任何工作在该限制之内的设备都可以成为一个HID,例如温度计、电压计、读卡机等。
报文的格式是由报告描述符决定的,所以只要修改描述符就能实现我们需要的报文格式。
下面我们来实现一个简单的报文格式:上位机发送固定64字节数据给设备,这个数据可以是命令,也可是数据,具体含义并不是由报告描述符来决定的,是由开发人员事先约定好的。
设备返回的数据也是64个字节,同样这个数据流的每个字节(甚至每个位)的具体含义由开发人员事先约定好。
1、修改报告描述符A、在Descriptor.C中找到以MouseReportDescriptor函数,将其内容修改如下:1.code char MouseReportDescriptor[29] = {2. 0x06,0x00,0xFF, //USAGE_PAGE (Vendor Defined Page 1)3. 0x09,0x01, //USAGE (Vendor Usage 1)4. 0xA1,0x01, //COLLECTION (Application)5.6. 0x19,0x01, //(Vendor Usage 1)7. 0x29,0x08, //(Vendor Usage 1)8. 0x15,0x00, //LOGICAL_MINIMUM (0)9. 0x26,0xFF,0x00, //LOGICAL_MAXIMUM (255)10. 0x75,0x08, //REPORT_SIZE (8)11. 0x95,0x40, //REPORT_COUNT (64)12. 0x81,0x02, //INPUT (Data,Var,Abs)13.14. 0x19,0x01, //(Vendor Usage 1)15. 0x29,0x08, //(Vendor Usage 1)16. 0x91,0x02, //OUTPUT (Data,Var,Abs)17.18. 0xC0 // END_COLLECTION19.};此报告描述符定义了64个字节的输入输出数据。
第一步:列举所有的HID设备:m_ctllHIDdevices.ResetContent(); //这是MFC里面一个list控件,用来显示所有的HID 设备的,如果你没有界面,可以不需要此行UpdateData(FALSE); //更新界面CString 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;//第一步:获取deviceIDGUID 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=s第一步:列举所有的HID设备:m_ctllHIDdevices.ResetContent(); //这是MFC里面一个list控件,用来显示所有的HID 设备的,如果你没有界面,可以不需要此行UpdateData(FALSE); //更新界面CString 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;//第一步:获取deviceIDGUID 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);izeof(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);第二步:循环读取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 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=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);//2HDEVINFO handle;handle = SetupDiGetClassDevs(&deviceId, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); //Get only HID devicesint 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;。