USB HID 小记

最近帮同事搞一个项目,他的USBHID设备不断向主机发送实时数据,让我帮忙写一个上位机程序实时读取他的数据并进行处理。结果拿到设备后,发现可以通过Bus Hound读取出数据,例如0d,db,80,ff,01 ,这些都是该设备传回的实时数据。由于对USBHID设备不熟悉,

开始研究USBHID设备,查找了几篇文献和网上的一些文章,终于有些眉目。这里先记下来。

首先,我去书店看了一眼《圈圈教你玩转USB》,貌似是第二版?主要看了前面USB1.1协议中的几个描述符,和HID特有的报告描述符。

单从硬件上来说,各个USB从设备对主机都是一样的,因为只有4根线而已。所以这么多USB设备的分类就只能靠软件来区分。具体的就是通过各种描述符来进行配置、区分。说简单点就是从设备在刚与主机连接时(USB枚举过程),进行了设备描述符、配置描述符、接口描述符、端点描述符、字符串描述符和报告描述符的提交,从设备通过这些描述符把自己的配置、特点、功能等等告诉主机。

明白了这点后,在百度上查了下“如何读取USBHID设备”,搜到了大把的文章,大多数都是利用hid.dll、kernel32.dll、setup.dll这三个库的API来完成读写。过程的话大同小异,都是先获得path,再createfile得到handler,最后通过handler读写。这里国外有几个网站有开源的C#程序,网址的话。。自己搜吧。。。

紧接着,我的问题出现了,readfile时永远返回0,getlasterror不是1784就是87,网上或者MSDN都可以查到错误代表什么,调了半天最后卡在一个问题上,我利用hid_getcaps读到了buffer长度,也就是readfile(...,buffer,bufferlength,...)其中的应该读取的长为61,当我设定bufferlength的值小于这个61时,出现1784号error,当我这个值大于等于61时,卡死在readfile这个函数(因为我是同步读取(readfile最后一个参数))。。。百思不得其解。

于是又重新看了一下USB1.1的协议和描述符说明,尤其是报告描述符说明。其中报告描述符描述了返回数据的报告种类,以及每种报告的数据格式。看到这里时,我怀疑有可能是因为设备的报告描述符配置错了,导致其返回给我的5字节数据例如0d,db,80,ff,01,被windowsHID驱动自动过滤掉了,因此一直无法获取数据。

因此将下位机程序要来,以及其开发环境。打开下位机程序,发现其报告描述符与上传的数据完全不符,其中报告ID即报告种类没有0d,因此上传的0d,db,80,ff,01会被主机驱动过滤掉。当然,修改报告ID,并将数据补齐,就可以通过readfile的方式读取端点2上的数据了(当然是中断传输)。

另外,readfile和writefile的读写方法都是中断传输,只能读写中断端点,设备的0端点不是中断端点,其他端点需要配置。另外,每个端点可以同时被配置为中断输出和中断输入端点。

先写到这,后面的程序和链接有空补上。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
HID 设备类读写 #include //! Defines the maximum length of a serial number #define SERNUM_LEN 40 //! Defines the maximum number of physical devices #define MAX_PHYS_DEVICES 6 //! \name HID Device return codes //! @{ // //! HID action/transfer was successful #define HID_DEVICE_SUCCESS 0x00 //! HID device was not found #define HID_DEVICE_NOT_FOUND 0x01 //! HID device is not opened #define HID_DEVICE_NOT_OPENED 0x02 //! HID device is allready opened #define HID_DEVICE_ALREADY_OPENED 0x03 //! Timeout occurs during transfer #define HID_DEVICE_TRANSFER_TIMEOUT 0x04 //! HID transfer failed #define HID_DEVICE_TRANSFER_FAILED 0x05 //! Invalid handle #define HID_DEVICE_HANDLE_ERROR 0x06 //! Unknown error #define HID_DEVICE_UNKNOWN_ERROR 0xFF //! @} // Enabled only when debugging HID connection issues //#define DEBUG_MODE //****************************************************************************** // //! \brief Device information structure. // //****************************************************************************** struct strHidDevice{ //! Handle for hid device HANDLE hndHidDevice; //! Indicator if device is opened BOOL bDeviceOpen; //! Timeout for GetReport requests UINT uGetReportTimeout; //! Timeout for SetReport requests UINT uSetReportTimeout; //! Asynchronous I/O structure OVERLAPPED oRead; //! Asynchronous I/O structure OVERLAPPED oWrite; //! Maximum length of InReport's WORD wInReportBufferLength; //! Maximum length of OutReport's WORD wOutReportBufferLength; //! InBuffer contains data, if InReport provides more data then the application actual need BYTE inBuffer[8192]; //! Number of current used bytes in inBuffer WORD inBufferUsed; }; //****************************************************************************** // //! A structure that tracks the number of serial numbers // //****************************************************************************** struct strTrackSerialNumbers { //! Index number DWORD deviceNum; //! Serial number of physical device char serialNum[SERNUM_LEN]; }; //****************************************************************************** // //! \addtogroup hiddevice_api //! @{ // //****************************************************************************** //****************************************************************************** // //! \brief Close a HID Device. //! //! This function will close a HID device based on the HID structure //! //! \param pstrHidDevice Structure which contains important data of an HID //! device //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_NOT_OPENED //! \n \b HID_DEVICE_HANDLE_ERROR // //****************************************************************************** BYTE HID_Close(struct strHidDevice* pstrHidDevice); //****************************************************************************** // //! \brief Flush USB buffer for the given device //! //! \param pstrHidDevice Structure which contains important data of an HID //! device. //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_HANDLE_ERROR //! \n \b HID_DEVICE_UNKNOWN_ERROR // //****************************************************************************** BYTE HID_FlushBuffer(struct strHidDevice* pstrHidDevice); //****************************************************************************** // //! \brief Gets the number of HID devices //! //! This function will return the number of interfaces connected with a //! specified VID, PID and serial number, if no devices are connected, //! it will return a 0 //! //! \param vid Vendor-Id of the device //! \param pid Product-Id of the device //! \param numSerNums Total number of connected physical devices //! //! \return Return the number of connected devices with the specific VID, PID, //! and serial number. // //****************************************************************************** DWORD HID_GetNumOfInterfaces(WORD vid, WORD pid, DWORD numSerNums); //****************************************************************************** // //! \brief Gets the number of serial number and serial number list //! //! Scans the HID Devices on the system for any whose VID/PID match the //! ones specified. For every one it finds, it returns that device's //! serial number in serialNumList. Every physical USB device within a //! given VID/PID space has a unique serial number; therefore, each //! item in the list corresponds with a separate physical USB device //! attached to this host; that is, different physical instances of the //! same product or design. The function returns the total number of //! serial numbers found; if none are found, it returns 0. //! //! \param vid Vendor-ID of the device //! \param pid Product-ID of the device //! \param serialNumList List of serial numbers corresponding to the passed //! VID and PID //! //! \return Returns the number of connected physical devices with the specific //! VID and PID // //****************************************************************************** DWORD HID_GetSerNums(WORD vid, WORD pid, struct strTrackSerialNumbers * serialNumList); //****************************************************************************** // //! \brief Returns the version number of a device. //! //! \param pstrHidDevice Structure which contains important data of an HID //! device. //! \param VersionNumber Pointer to USHORT variable. //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_HANDLE_ERROR // //****************************************************************************** BYTE HID_GetVersionNumber(struct strHidDevice* pstrHidDevice, USHORT * VersionNumber); //****************************************************************************** // //! \brief Init structure with default values. //! //! It is important to call HID_Init() before calling HID_Open() to //! avoid unpredictable behavoir. //! //! \param pstrHidDevice Structure which contains important data of a HID //! device //! //! \return None // //****************************************************************************** void HID_Init(struct strHidDevice* pstrHidDevice); //****************************************************************************** // //! \brief This has to be called inside WM_ON_DEVICECHANGE notification window //! //! This function checks if the particular HID device structure is //! still connected or disconnected. //! //! \param pstrHidDevice Structure which contains important data of an HID //! device. //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_HANDLE_ERROR // //****************************************************************************** BOOL HID_IsDeviceAffected(struct strHidDevice* pstrHidDevice); //****************************************************************************** // //! \brief Open a HID Device. //! //! This function opens the HID device associated with the HID interface //! 'deviceIndex' (0-7), on the physical device described by the VID, //! PID, and serial number. //! \param pstrHidDevice Structure which contains important data of an HID //! device //! \param vid Vendor-ID of the device //! \param pid Product-ID of the device //! \param deviceIndex Index of the device.If only one HID is connected, //! deviceIndex is 0. //! - Starts with zero //! - Maximum value is (HID_GetNumOfInterfaces() - 1) //! \param serialNumber Serial number of device to be opened. //! \param totalDevNum Total number of interfaces associated with the //! serial number //! \param totalSerNum Total number of physical devices associated with //! the VID/PID //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_NOT_FOUND //! \n \b HID_DEVICE_ALREADY_OPENED // //****************************************************************************** BYTE HID_Open(struct strHidDevice* pstrHidDevice, WORD vid, WORD pid, DWORD deviceIndex, char serialNumber[SERNUM_LEN], DWORD totalDevNum, DWORD totalSerNum); //****************************************************************************** // //! \brief Reads a data stream from the given HID device. //! //! Prefixed report ID will be skipped. //! //! \param pstrHidDevice Structure which contains important data of an HID //! device //! \param buffer Pointer to buffer in which will be written //! \param bufferSize Number of bytes to read //! \param bytesReturned Number of actual read bytes //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_NOT_OPENED //! \n \b HID_DEVICE_TRANSFER_TIMEOUT //! \n \b HID_DEVICE_TRANSFER_FAILED // //****************************************************************************** BYTE HID_ReadFile(struct strHidDevice* pstrHidDevice, BYTE* buffer, DWORD bufferSize, DWORD* bytesReturned); //****************************************************************************** // //! \brief Registers a device for program Windows notification. //! //! Registers the window pointed to by handle hWnd to receive //! notification when devices are added or removed from the system. //! //! \param hWnd Windows handle //! \param diNotifyHandle Device notification handle pointer address //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_HANDLE_ERROR // //****************************************************************************** BYTE HID_RegisterForDeviceNotification(HWND hWnd, HDEVNOTIFY* diNotifyHandle); //****************************************************************************** // //! \brief Un-Registers a device from Windows notification. //! //! Un-registers the window pointed to by handle hWnd to receive //! notification when devices are added or removed from the system. //! //! \param diNotifyHandle: Device notification handle pointer address. //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_HANDLE_ERROR // //****************************************************************************** BYTE HID_UnRegisterForDeviceNotification(HDEVNOTIFY* diNotifyHandle); //****************************************************************************** // //! \brief Writes a data stream to the given HID device. //! //! Needed report IDs will be generated automatically. //! //! \param pstrHidDevice Structure which contains important data of an HID //! device //! \param buffer Buffer which will be send //! \param bufferSize Number of bytes to send //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_NOT_OPENED //! \n \b HID_DEVICE_TRANSFER_TIMEOUT //! \n \b HID_DEVICE_TRANSFER_FAILED // //****************************************************************************** BYTE HID_WriteFile(struct strHidDevice* pstrHidDevice, BYTE* buffer, DWORD bufferSize);

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值