【QT】windows下QT使用HIDAPI

news/2024/5/20 9:40:06 标签: qt, windows, 开发语言, HID, hidapi

文章目录

  • 前言
  • 一、HIDAPI是什么?
  • 二、添加HIDAPI库
    • 1.下载HIDAPI相关库文件
    • 2.重新编译x64库文件
  • 三、使用函数介绍
    • 1.初始化以及释放函数
    • 2.遍历HID USB函数
    • 3.打开USB函数
    • 4.读写USB函数
  • 四、HID USB链表结构体介绍
  • 五、获取指定VID和PID的HID USB设备信息
    • 1.获取设备的VID和PID
    • 2.代码
  • 六、指定HID USB设备端口读写
    • 1.端口的选择
    • 2.数据发送hid_write()函数详解
    • 3.数据接收hid_read()函数详解
  • 七、总结

前言

HID设备介绍可以看这里。
usb 不仅仅hid通信方式,还有其余的usb通信方式,但hid的好处就是无需安装驱动,热插拔直接用。


HIDAPI_8">一、HIDAPI是什么?

HIDAPI 是一个 USB 和蓝牙的 hid 类设备在 Windows、Linux、FreeBSD 和 Mac 的 C 语言通用库,使用 HIDAPI可以在 Windows、Linux、FreeBSD 和 Mac 平台进行 USB 和蓝牙的 hid 类设备通信,非常简单实用。


HIDAPI_12">二、添加HIDAPI库

HIDAPI_13">1.下载HIDAPI相关库文件

文件连接可以去github查看:https://github.com/libusb/hidapi/tree/hidapi-0.12.0
在这里插入图片描述
打开window文件夹里的文件就是源码,里面包含的lib、dll为32位,需要64位的需要自己编译。
或者直接下载已经编译好的:https://download.csdn.net/download/cao_jie_xin/86827407

2.重新编译x64库文件

新建一个控制台程序,在配置类型中改成dll,把源代码内容拷贝过来重新编译生成dll.
在这里插入图片描述


三、使用函数介绍

1.初始化以及释放函数

//非必要函数,调用hid_enumerate()和hid_open()都会自动调用它
hid_init(void);
//释放hidapi
hid_exit(void);

HID_USB_34">2.遍历HID USB函数

//传入vid和pid可以遍历该id下的所有接口号地址等数据并形成链表返回
//若是vid和pid=0则遍历所有hid usb数据并形成链表返回
hid_enumerate(unsigned short vendor_id, unsigned short product_id);

3.打开USB函数

//指定vid和pid打开,最后一个参数可以是NULL,返回句柄(不建议使用)
//该操作使用默认端口,不能自主选择
hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number);
//指定路径打开usb设备,返回句柄(建议使用)
hid_open_path(const char *path);
//释放链表,参数为hid_enumerate()返回的链表
hid_free_enumeration(struct hid_device_info *devs);

4.读写USB函数

//写操作
hid_write(hid_device *dev, const unsigned char *data, size_t length);
//设定阻塞读与非阻塞读 0为阻塞 1为非阻塞
hid_set_nonblocking(hid_device *dev, int nonblock);
//读操作
hid_read(hid_device *dev, unsigned char *data, size_t length);

HID_USB_65">四、HID USB链表结构体介绍

结构如下:

/** hidapi信息结构 */
struct hid_device_info {
	/** 设备路径 */
	char *path;
	/** VID */
	unsigned short vendor_id;
	/** PID */
	unsigned short product_id;
	/** 序列号 */
	wchar_t *serial_number;
	/** 以二进制编码的十进制表示的设备版本号 */
	unsigned short release_number;
	/** 制造商字符串 */
	wchar_t *manufacturer_string;
	/** 产品字符串 */
	wchar_t *product_string;
	/** 此设备/界面的使用页面
	(仅限Windows/Mac/hidraw) */
	unsigned short usage_page;
	/** 此设备/接口的用法
	(仅限Windows/Mac/hidraw) */
	unsigned short usage;
	/** 设备接口号 */
	int interface_number;

	/** 连接到下一个 */
	struct hid_device_info *next;
};

HID_USB_100">五、获取指定VID和PID的HID USB设备信息

1.获取设备的VID和PID

windows下打开usb应该是需要root权限,建议用管理员模式打开QT不然容易异常退出。

两种方式:
1.自己写的下位机VID和PID自己决定。
2.使用Bus Hound获取,具体使用方式就不说了。
在这里插入图片描述

2.代码

 int USB::hid_print(void)
{
    hid_device_info *hid_info;//usb链表
    /*打开指定VID PID设备*/
    hid_info = hid_enumerate(0x5511,0x0011);
    /*遍历所有信息并打印*/
    for(;hid_info != nullptr;hid_info = hid_info->next){
        qDebug("设备接口号:%d",hid_info->interface_number);
        qDebug("厂商字符串:%ls",hid_info->manufacturer_string);
        qDebug("设备字符串:%ls",hid_info->product_string);
        qDebug("版本号:%d",hid_info->release_number);
        qDebug("地址:%s",hid_info->path);
    }
    /*释放链表*/
    hid_free_enumeration(hid_info);
    return 0;
}

运行后可以看到以下数据:
在这里插入图片描述
和Bus Hound读取到的对比一致,证明读取每出错。
在这里插入图片描述


HID_USB_138">六、指定HID USB设备端口读写

1.端口的选择

在第五点中我们已经遍历了该USB设备内的所有端口,这些端口被保存在上述USB链表内,因此我们需要找到我们要操作的端口号,并通过hid_open_path()这个函数来打开,这样才能指定端口收发数据。

#define	TX_MAXSIZE   64;
int USB::usb_write(void)
{
   int res;
   uint8_t buf[TX_MAXSIZE + 1];
   hid_device *handle;//usb句柄
   hid_device_info *hid_info;//usb链表

   /*打开指定VID PID设备*/
   hid_info = hid_enumerate(0x5511,0x0011);
   for(;hid_info != nullptr;hid_info = hid_info->next){
       if(hid_info->interface_number == 2)//接口匹配
       {
           qDebug("interface_number:%s",hid_info->path);//打印地址
           break;
       }
   }
   return 0;
}

2.数据发送hid_write()函数详解

int hid_write(hid_device *device, const unsigned char *data, size_t length);

在Windows中使用 hid_write()这个函数时,一定要注意!写入的数据大小一定要再加1bytes,首字节用来存放REPORT ID,并且写入 的数据大小"length"只能固定为设备对应ReportID定义的OUT报告的大小!我的下位机设定了端口收发最大字节为64,所以hid_write()发送的数组长度为64+1;读写的一些注意事项在这。

int USB::usb_write(void)
{
   int res;
   uint8_t buf[TX_MAXSIZE + 1];
   hid_device *handle;//usb句柄
   hid_device_info *hid_info;//usb链表

   /*打开指定VID PID设备*/
   hid_info = hid_enumerate(0x5511,0x0011);
   for(;hid_info != nullptr;hid_info = hid_info->next){
       if(hid_info->interface_number == 2)//接口匹配
       {
           qDebug("interface_number:%s",hid_info->path);//打印地址
           break;
       }
   }
   /*打开指定地址的设备*/
   handle = hid_open_path(hid_info->path);
   /*释放链表*/
   hid_free_enumeration(hid_info);
   buf[0] = 0x3f;//Report ID(自定义)
   buf[1] = 0x21;//随便一点东西
   buf[2] = 0x03;
   buf[3] = 0x00;
   buf[4] = 0x00;
   buf[5] = 0x00;
   res = hid_write(handle, buf, TX_MAXSIZE + 1);
   if(res < 0){
       /*返回值查看*/
       qDebug("err_string = %ls\n",hid_error(handle));
   }
   return 0;
}

3.数据接收hid_read()函数详解

阻塞式接收代码,不收到消息不会退出:

int USB::usb_read(void)
{
    int res;
    uint8_t buf[64+1];
    hid_device *handle;//usb句柄
    hid_device_info *hid_info;//usb链表

    /*打开指定VID PID设备*/
    hid_info = hid_enumerate(0x5511,0x0011);
    for(;hid_info != nullptr;hid_info = hid_info->next){
        if(hid_info->interface_number == 2)//接口匹配
        {
            qDebug("interface_number:%s",hid_info->path);//打印地址
            break;
        }
    }
    /*打开指定地址的设备*/
    handle = hid_open_path(hid_info->path);
    /*释放链表*/
    hid_free_enumeration(hid_info);

    res = hid_read(handle, buf, 64+1);
    if(res < 0){
        /*返回值查看*/
        qDebug("err_string = %ls\n",hid_error(handle));
    }

    /*阻塞*/
    hid_set_nonblocking(handle, 0);
    for(int i = 0;i<64;i++){
        qDebug("buf[%d]:%02x",i,buf[i]);
    }
    return 0;
}

使用Bus Hound发送指令,可以看到已经收到下位机返回的消息(当然这个接收指令后返回消息的处理是在下位机写的)
在这里插入图片描述


七、总结

本文就是简单的hidapi收发消息操作,若有错误,欢迎指出。

参考链接:链接1

参考链接:链接2

本文需要的dll ,工具,例程,源码,开源代码,官方例程链接:https://download.csdn.net/download/cao_jie_xin/86827407


http://www.niftyadmin.cn/n/1190.html

相关文章

手写实现Vue3 reative

前言 reative原理详解&#xff1a;https://blog.csdn.net/weixin_39503495/article/details/127058245 环境搭建 使用typescript、vite构建工具 // 初始化项目 npm init -y // 安装依赖 npm i vite typescript -D初始化typescript。 tsc --init 创建index.html、index.ts&am…

Python编程 赋值,逻辑,位运算符

作者简介&#xff1a;一名在校计算机学生、每天分享Python的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.赋值运算符 1.基本赋值运算符 2.注意 二.逻辑运算符 1.逻辑运算符使…

基于javaweb的养老院管理系统(java+springboot+thymeleaf+html+js+mysql)

基于javaweb的养老院管理系统(javaspringbootthymeleafhtmljsmysql) 运行环境 Java≥8、MySQL≥5.7 开发工具 eclipse/idea/myeclipse/sts等均可配置运行 适用 课程设计&#xff0c;大作业&#xff0c;毕业设计&#xff0c;项目练习&#xff0c;学习演示等 功能说明 基于…

2022年计网《宿舍网有线无线一体化项目》总结

2022年计网《宿舍网有线无线一体化项目》总结60分&#xff01;错错错如果有如果2022年&#xff0c;大三上&#xff0c;必修课——《计算机网络》&#xff0c;授课老师又是我们的王老师。相别不过一个暑假&#xff0c;上学期他教的我们班《微型计算机技术及应用》&#xff0c;我…

漏洞复现- - -IIS解析漏洞在fckEditor上传攻击中的利用

目录 一&#xff0c;fckEditor在线编辑器 二&#xff0c;ISS6.0解析漏洞介绍 三&#xff0c;实验环境 四&#xff0c;实验步骤 一&#xff0c;fckEditor在线编辑器 FCKeditor是一个功能强大支持所见即所得功能的文本编辑器&#xff0c;可以为用户提供微软office软件一样的…

梦开始的地方—— C语言指针入门

文章目录指针入门1.指针概念2. 指针和指针类型3. 野指针造成野指针的原因如何避免野指针4. 指针的运算指针加减整数指针的运算关系指针的关系运算5.指针和数组6. 二级指针7. 指针数组指针入门 1.指针概念 指针(Pointer) 是编程语言中的一个对象&#xff0c;利用地址&#xff…

Java多线程(2)

1.jconsole.exe 在介绍多线程状态之前,我们先来认识一个Java JDK自带的工具"jconsole.exe" 它可以让我们很好地观察Java线程的状态. 首先我们需要找到自己安装jdk的目录 然后进入bin目录下.找到名为"jconsole.exe"的程序文件 然后打开程序 这里我们…

Synchronized底层核心原理

前言&#xff1a;大家好&#xff0c;我是小威&#xff0c;24届毕业生&#xff0c;在一家满意的公司实习。本篇文章是关于并发编程中Synchronized锁的底层核心原理知识记录&#xff0c;由于篇幅原因&#xff0c;下篇文章将介绍各种锁的优化原理。 本篇文章记录的基础知识&#x…