VC++ HIDAPI实现USB数据读写

目录

引入hidapi

主要函数

初始化和退出

hid_enumerate

hid_open

读数据

写数据

项目下载



hidapi是一个开源的C语言实现的usb通信库,支持Linux,MAC,windows系统,但是也有一段时间没有更新了。
在windows系统上的实现是依赖winusb实现的
github 地址 https://github.com/signal11/hidapi


引入hidapi

主要引入三个文件

`usb_hid.h`:头文件,include引入
`hidapi.dll`:dll文件,放在执行程序同级目录下
`hidapi.lib`:lib库文件,在附件依赖项中添加或使用`#pragma comment(lib,"hidapi.lib")`加进来

主要函数

初始化和退出

`hid_init()`和`hid_exit()`成对出现,分别是初始化和退出,所有的hid操作都要包括在两者之间

hid_enumerate

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_open


打开设备返回设备操作的句柄,设备数据的读取和写入都要使用到这个句柄
打开设备是独占方式的,使用过后需要使用`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

相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页