目录
引入hidapi
主要函数
初始化和退出
hid_enumerate
hid_open
读数据
写数据
项目下载
hidapi是一个开源的C语言实现的usb通信库,支持Linux,MAC,windows系统,但是也有一段时间没有更新了。
在windows系统上的实现是依赖winusb实现的
github 地址 https://github.com/signal11/hidapi
主要引入三个文件
`usb_hid.h`:头文件,include引入
`hidapi.dll`:dll文件,放在执行程序同级目录下
`hidapi.lib`:lib库文件,在附件依赖项中添加或使用`#pragma comment(lib,"hidapi.lib")`加进来
`hid_init()`和`hid_exit()`成对出现,分别是初始化和退出,所有的hid操作都要包括在两者之间
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
读取设备信息,需要设备的vid和pid,返回设备信息的结构体`hid_device_info`,是链表结构。实际是查询所有连接设备然后根据vid和pid进行匹配,如果vid或pid是0的话则默认匹配成功,即如果vid和pid都是0的话返回所有设备信息。
struct hid_device_info {
/** Platform-specific device path */
char *path;
/** Device Vendor ID */
unsigned short vendor_id;
/** Device Product ID */
unsigned short product_id;
/** Serial Number */
wchar_t *serial_number;
/** Device Release Number in binary-coded decimal,
also known as Device Version Number */
unsigned short release_number;
/** Manufacturer String */
wchar_t *manufacturer_string;
/** Product string */
wchar_t *product_string;
/** Usage Page for this Device/Interface
(Windows/Mac only). */
unsigned short usage_page;
/** Usage for this Device/Interface
(Windows/Mac only).*/
unsigned short usage;
/** The USB interface which this logical device
represents. Valid on both Linux implementations
in all cases, and valid on the Windows implementation
only if the device contains more than one interface. */
int interface_number;
/** Pointer to the next device */
struct hid_device_info *next;
};
hid_device_info结构体的数据需要使用下面这个方法释放
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs);
打开设备返回设备操作的句柄,设备数据的读取和写入都要使用到这个句柄
打开设备是独占方式的,使用过后需要使用`hid_close`关闭
在windows其底层的实现方式是用的winusb的api `CreateFile`
//通过设备vid和pid打开
HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number);
//通过设备路径打开
HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path);
`hid_read`
读取数据,一次读取一个报文
/**
* @param device 设备句柄
* @param data 读取数据存放的buffer
* @param length 读取数据的最大长的
*
* @return 实际读取到的数据长度,-1表示读取失败
*/
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length);
一般使用时要开辟线程,在线程中循环读取,代码如下
unsigned int _stdcall usb_hid::usb_read_proc(LPVOID lp_param)
{
usb_hid * params = (usb_hid *)lp_param;
unsigned char buf[30];
memset(buf, 0, sizeof(buf));
int res = 0;
while (params->is_run_)
{
if (!params || !params->dev_handle_)
{
break;
}
res = hid_read(params->dev_handle_, buf, sizeof(buf));
if (res > 0)
{
for (int i = 0; i < res; i++)
printf("%02hhx ", buf[i]);
printf("\n");
}
if (res < 0)
{
}
Sleep(500);
}
return 0;
}
`hid_write`
写数据的方法,一次写一个报文。写数据时注意数据buffer的头部是报文id,如果设备只支持单报文的形式,则设置为0x0。这就导致写数据的长度要比实际需要写入的数据长1个字节;
/**
@param device 设备句柄
@param data 发送的数据,首位为报文id
@param length 发送数据的长度(字节|byte)
@returns 实际写入的数据长度,-1表示出错
*/
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length);
实现代码如下,是否异步根据情况选择。推荐异步进行操作,实际使用过程中发现写数据时有可能发生堵塞。
int usb_hid::usb_write_data_test(){
//准备写入的数据(hex):20 00 02 00 07 00 00 00
unsigned char buffer[9];
memset(buffer, 0, sizeof(buffer));
buffer[0] = 0x00;//首位添加 report id
buffer[1] = 0x20;//数据开始
buffer[2] = 0x00;
buffer[3] = 0x02;
buffer[4] = 0x00;
buffer[5] = 0x07;
int res = hid_write(dev_handle_, buffer, 9);
printf("hid_write data res: %d\n",res);
}
项目中包含usb热拔插响应的代码
https://download.csdn.net/download/lhangtk/10670821