USB学习:hidapi库使用

hidapi是一个开源的操作 HID 设备的库,使用 C 语言实现,适用于 Windows、Linux 和 Mac OSX 平台。注意,这个库是针对 HID 设备的,其它 USB 设备(如 U 盘)不一定适合。

hidapi 介绍

hidapi 源码仓库为:https://github.com/libusb/hidapi 。主要目录介绍如下:

hidapi: 头文件(所有平台共用一份头文件)hidapi.h
libusb:Linux系统实现源码文件hid.c,使用libusb库实现的方式
linux:Linux系统实现源码文件hid.c,使用内核接口实现方式
windows:Windows系统实现源码文件hid.c
mac:Mac OSX 系统实现源码文件hid.c
hidtest:测试代码 hidtest.c

注意,Linux 系统有两种实现方式,各有秋千,可根据需求选择,笔者使用内核接口的实现方式。

跨平台

hidapi 源码本身根据不同平台实现,但对外提供接口的头文件相同。因此直接使用对应平台的实现源码文件即可。Windows 系统下,官方建议使用 dll 方式,不过笔者发现直接使用源码文件更好,因为可以直接跟踪源码(方便调试阶段)。
如果我们的项目本身需要跨平台,则可以使用 _WIN32__linux__ 这样的宏来区别平台,以便使用不同的源码文件。

主要接口介绍

本文不详细介绍测试示例,根据笔者的实践经验,按流程列出主要的接口。

初始化和退出:
1、hid_init:初始化,无参数,可以不调用,因为在后续接口中会自动判断并调用。
2、hid_exit:退出,实际上是销毁结构体等,如果不调用,会造成内存泄漏。

枚举:
1、hid_enumerate:枚举设备,返回的是hid_device_info链表。一般使用hid_enumerate(0, 0)枚举所有设备。枚举一般用于获取设备ID或者设备路径。如果提前知道这些信息,亦可不用枚举。
2、hid_free_enumeration:释放枚举所用到的链表。

设备打开与关闭:
1、hid_open:打开指定 VID 和 PID 设备,返回设备结构体指针,如 hid_device *handle; handle = hid_open(0x4d8, 0x3f, NULL)。在设备读写和关闭函数,均需要该结构体指针。
2、hid_open_path:根据设备路径打开设备,设备路径由hid_enumerate获取。如Linux下的 /dev/hidraw0
3、hid_close:关闭设备。

feature report 收发:
1、hid_get_feature_report:获取 Feature report。
2、hid_send_feature_report:发送 Feature report。

读写:
1、hid_read:读取数据 Input report。
2、hid_write:写数据 Output report。

获取错误:
hid_error:返回上一次的错误,wchar_t类型字符串形式,注意,该字符串无须调用者释放。

其它如hid_get_manufacturer_stringhid_get_product_string等,似乎重要程度不够,故不列出。

Windows 使用

Windows 系统需要添加setupapi.lib库,可使用如下方式添加:

#ifdef _WIN32
#pragma comment (lib,"setupapi.lib")
#endif

也可以在项目属性->链接器->输入,在依赖项添加这个库。

MFC 工程的使用

由于 hidapi 使用 C 语言实现,需要将源码hidapi.c后缀改为hidapi.cpp,并且在该文件最前面添加头文件包含:

#include "stdafx.h"

同样需要添加setupapi.lib库的支持。

Windows 系统 Qt 工程的使用

添加 hidapi 文件即可,在工程文件.pro中添加相应的依赖库,如下:

win32: LIBS +=  -lsetupapi

开发经验备忘

网上关于 hidapi 的介绍,几乎都是基于官方测试代码的——当然,本文也是。但本节说一说笔者的开发经验。
1、有些 USB HID 设备在系统中可能对应多个设备,此情况下,PID 和 VID 均相同,无法使用,因此,需要使用来打开。

2、有些设备使用读写方式打开会失败,此情况下,会使用读方式打开,详见 hid.c 源码的 hid_open_path 函数。但并不代表该设备不可写,至少笔者曾遇到这种情况。为了验证,换了 Win7 系统,换了 Linux 系统测试,前后花费大概三个晚上调试、实验,最终得到此结论,无须修改源码。

3、一般来说,读写 feature report 类似于命令协议本身的传输(当然命令本身也可带数据),而读写则是读写大量数据。实情如何,取决下位机的实现。比如,可以通过 feature report 来实现固件的更新。

4、feature report 第1个字节必须是 ID 值,且必须与下位机一致,否则无法建立传输,对于 hidapi 而言,即为读写失败。传输的数据也要保证正确。
5、写 feature 报告时,必须额外添加1字节的 ID并且必须在第0位置,否则会失败。获取时,真正数据在 ID 之后,所以要跳过1字节。

小结

本文仅对 hidapi 进行简单的了解及测试,其提供的接口友好并且基本满足一般项目的应用需求。

©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页