使用winUSB进行USB开发

news2024/11/20 19:42:26

在这里插入图片描述

什么是winUSB

WinUSB是Windows操作系统提供的一种通用USB驱动程序,用于简化USB设备的开发和使用。它是一个用户模式驱动程序,可以在Windows XP及更高版本的操作系统上使用。WinUSB提供了一组API和工具,使开发人员能够与USB设备进行通信,包括数据传输和设备控制。

以下是WinUSB的一些主要特点和功能:

  1. 简化开发:WinUSB提供了一组易于使用的API,使开发人员能够更容易地与USB设备进行通信。它提供了基于异步I/O的数据传输接口,支持批量传输、中断传输和控制传输。开发人员可以使用标准的Win32编程技术(如C/C++)来编写应用程序,与USB设备进行交互。

  2. 无需驱动程序开发经验:使用WinUSB,开发人员无需具备深入的驱动程序开发知识。相比于传统的内核模式驱动程序开发,WinUSB的用户模式驱动程序更容易理解和使用。这使得USB设备的开发变得更加简单和快速。

  3. 驱动程序自动安装:当使用WinUSB驱动程序时,Windows操作系统可以自动安装所需的驱动程序,无需手动安装或配置驱动程序。这大大简化了使用USB设备的过程,减少了用户的繁琐操作。

  4. 兼容性:WinUSB驱动程序在Windows XP及更高版本的操作系统上都可以使用。这使得开发人员可以编写一次代码,并在不同版本的Windows系统上运行,提高了应用程序的兼容性。

需要注意的是,WinUSB适用于直接与USB设备进行通信的应用程序,而不适用于USB设备的传统功能,例如打印机、扫描仪等。对于这些设备,通常需要使用特定的设备类驱动程序或供应商提供的驱动程序。

举了例子

以下是一个使用WinUSB进行批量传输(Bulk Transfer)的示例代码:

#include <Windows.h>
#include <SetupAPI.h>
#include <winusb.h>
#include <iostream>

// USB设备的Vendor ID和Product ID
#define VENDOR_ID 0x1234
#define PRODUCT_ID 0x5678

// 批量传输管道的端点地址
#define BULK_IN_ENDPOINT 0x81
#define BULK_OUT_ENDPOINT 0x02

int main()
{
    // 初始化WinUSB库
    BOOL result = WinUsb_Initialize(NULL, NULL, NULL, NULL);
    if (!result)
    {
        std::cout << "Failed to initialize WinUSB." << std::endl;
        return 1;
    }

    // 枚举USB设备
    HDEVINFO deviceInfoSet = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);
    if (deviceInfoSet == INVALID_HANDLE_VALUE)
    {
        std::cout << "Failed to enumerate USB devices." << std::endl;
        WinUsb_Free(NULL);
        return 1;
    }

    // 遍历设备列表,查找指定的USB设备
    SP_DEVINFO_DATA deviceInfoData = { 0 };
    deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
    for (DWORD index = 0; SetupDiEnumDeviceInfo(deviceInfoSet, index, &deviceInfoData); ++index)
    {
        // 获取设备的USB描述符
        SP_DEVICE_INTERFACE_DATA interfaceData = { 0 };
        interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
        if (!SetupDiEnumDeviceInterfaces(deviceInfoSet, &deviceInfoData, &GUID_DEVINTERFACE_USB_DEVICE, 0, &interfaceData))
        {
            continue;
        }

        // 获取设备路径
        DWORD requiredSize = 0;
        SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &interfaceData, NULL, 0, &requiredSize, NULL);
        PSP_DEVICE_INTERFACE_DETAIL_DATA interfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(requiredSize);
        interfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
        if (!SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &interfaceData, interfaceDetailData, requiredSize, NULL, NULL))
        {
            free(interfaceDetailData);
            continue;
        }

        // 打开设备
        HANDLE deviceHandle = CreateFile(interfaceDetailData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
        if (deviceHandle == INVALID_HANDLE_VALUE)
        {
            free(interfaceDetailData);
            continue;
        }

        // 获取WinUSB接口句柄
        WINUSB_INTERFACE_HANDLE winusbHandle = NULL;
        result = WinUsb_Initialize(deviceHandle, &winusbHandle);
        if (result)
        {
            // 获取USB设备的描述符
            USB_DEVICE_DESCRIPTOR deviceDescriptor;
            result = WinUsb_GetDescriptor(winusbHandle, USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, (PUCHAR)&deviceDescriptor, sizeof(deviceDescriptor), NULL);
            if (result)
            {
                // 检查Vendor ID和Product ID是否匹配
                if (deviceDescriptor.idVendor == VENDOR_ID && deviceDescriptor.idProduct == PRODUCT_ID)
                {
                    // 发送数据
                    UCHAR outBuffer[64] = { 0 }; // 要发送的数据
                    DWORD bytesTransferred = 0;
                    result = WinUsb_WritePipe(winusbHandle, BULK_OUT_ENDPOINT, outBuffer, sizeof(outBuffer), &bytesTransferred, NULL);
                    if (result)
                    {
                        std::cout << "Data sent successfully." << std::endl;
                    }
                    else
                    {
                        std::cout << "Failed to send data." << std::endl;
                    }

                    // 接收数据
                    UCHAR inBuffer[64] = { 0 }; // 用于接收数据
                    result = WinUsb_ReadPipe(winusbHandle, BULK_IN_ENDPOINT, inBuffer, sizeof(inBuffer), &bytesTransferred, NULL);
                    if (result)
                    {
                        std::cout << "Data received successfully." << std::endl;
                    }
                    else
                    {
                        std::cout << "Failed to receive data." << std::endl;
                    }
                }
            }

            // 关闭WinUSB接口
            WinUsb_Free(winusbHandle);
        }

        // 关闭设备句柄
        CloseHandle(deviceHandle);
        free(interfaceDetailData);
    }

    // 释放资源
    SetupDiDestroyDeviceInfoList(deviceInfoSet);
    WinUsb_Free(NULL);

    return ;
    }

以上示例代码展示了如何使用WinUSB进行批量传输(Bulk Transfer)。在示例代码中,我们首先初始化WinUSB库,然后通过SetupAPI枚举连接到计算机的USB设备,并查找与指定的Vendor ID和Product ID匹配的设备。

如果设备匹配成功,我们可以使用WinUsb_WritePipe函数发送数据,以及使用WinUsb_ReadPipe函数接收数据。在示例代码中,我们使用了BULK_OUT_ENDPOINT和BULK_IN_ENDPOINT来指定批量传输的输入和输出端点地址。

你可以根据自己的需求修改示例代码,例如更改发送和接收的数据缓冲区大小、使用异步传输等。

请注意,上述示例代码仅展示了WinUSB进行批量传输的基本用法。实际使用时,你需要根据具体设备的通信协议和要求进行适当的修改和扩展。此外,WinUSB还提供了其他功能和API,例如控制传输、同步传输等,可以根据需要进行进一步的学习和使用。

在实际开发中,建议参考Microsoft官方文档和示例代码,以获取更详细和全面的WinUSB使用说明。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1094620.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++11可变参数模板

文章目录 1.可变参数模板的介绍1.1C语言中的可变参数1.2C98/C11的类模板和函数模板1.3可变参数的函数模板1.4展开参数包递归展开初始化列表展开 2.可变参数模板的应用 1.可变参数模板的介绍 1.1C语言中的可变参数 1.2C98/C11的类模板和函数模板 C98/03&#xff0c;类模版和函…

Numpy(一)简介与基本使用

Numpy&#xff08;一&#xff09;简介与基本使用 一、Numpy简介 1.Numpy是一个运行速度非常快的数学库&#xff0c;主要用于数组计算 2.包含&#xff1a;N维数组对象ndarray、广播功能函数、整合C/C/Fortran代码工具、包含线性代数/傅里叶变换/随机数生成等功能 3.优点&…

ChatGPT快速入门

ChatGPT快速入门 一、什么是ChatGPT二、ChatGPT底层逻辑2.1 实现原理2.2 IO流程 三、ChatGPT应用场景3.1 知心好友3.2 文案助理3.3 创意助理3.4 角色扮演 一、什么是ChatGPT ChatGPT指的是基于GPT&#xff08;Generative Pre-trained Transformer&#xff09;模型的对话生成系…

python字典、列表排序,从简单到复杂

因工作原因&#xff0c;需要频繁对python字典(dict)、列表(list)等进行各种各样的排序&#xff0c;发现网上这块的资料又多又杂&#xff0c;尤其涉及到lambda的&#xff0c;让人觉得难以理解看不下去&#xff0c;因此写了这篇文章&#xff0c;从简单到复杂&#xff0c;配合例子…

【Eclipse】安装教程

首先打开官网&#xff1a;Eclipse Downloads | The Eclipse Foundation 这里我选择了下载最新版本 下载好后&#xff0c;双击下载的文件 &#xff0c;即可进入到安装页面 点击第一个进行安装&#xff1a; 最后安装成功&#xff01; 补充&#xff1a; 【Eclipse】安装JAVA EE插…

Jmter接口网站压力测试工具使用记录

1.首先下载Jmeter 官方地址&#xff1a;Apache JMeter - Apache JMeter™ 回到顶部 2.安装Jmeter 把下载的文件进行解压&#xff0c;产生如下目录&#xff1a; 打开bin文件夹下的jmeter.bat文件及进入程序的主界面窗体jmeter.log是日志文件。 主意&#xff1a;需要配置java环…

河北专升本(C语言)

目录 一&#xff1a;C语言的构成特点 二: 数据类型 三: 常量、变量、运算符及表达式 &#xff08;一&#xff09;标识符 &#xff08;二&#xff09;常量 &#xff08;三&#xff09;变量&#xff1a;其值可以改变的量 &#xff08;四&#xff09;各种类型数据混合运算 &…

打印编译程序固件的环境信息

在编译程序固件的时候&#xff0c;我们常常会有一个软件版本号&#xff0c;用来区分不同的版本&#xff0c;有时候又没变化软件版本号&#xff0c;重新发两个debug版本给测试验证&#xff0c;那我们就需要在程序中埋入一些环境信息&#xff0c;下面有两种方法来加入一下简单的信…

APP 备案公钥、签名 MD5、SHA-1、SHA-256获取方法。

公钥和 MD5 值可以通过安卓开发工具、Keytool、Jadx-GUI 等多种工具获取&#xff0c;最简单的就是以 jadx-gui 为例。 1.下载 jadx-gui 工具 &#xff0c;点击此处 下载 jadx-gui 工具。 2.下载完成后&#xff0c;解压压缩包&#xff0c;双击 jadx-gui-1.4.7.exe 运行。 3.…

Neo4j入门基础:CREATE,DELETE,SET,REMOVE(看不懂我直接吃...)

1. 创建节点 1.1 创建一个节点 create (s:student1)创建一个标签为student1的节点 1.2 创建多个节点 create (s2:student2),(s3:student3)同时创建两个节点&#xff0c;标签分别为&#xff1a;student2&#xff0c;student3 1.3 创建节点并附带&#xff08;多个&#xff0…

MAC上设置IDEA如何一个窗口打开多个项目,多个tab

1、IDEA一个窗口打开多个项目 如果你打开了多个项目、每次切换都要半天&#xff0c;想让项目都汇聚到top栏 点击 Window - Merge All Project Windows 即可 但是这样比较挫&#xff0c;每次打开新的项目都还是会重新打开一个IDEA窗口 so&#xff0c;如何设置项目在同一个窗口…

树模型(一)孤立森林

孤立森林&#xff08;Isolation Forest&#xff09;算法是西瓜书作者周志华老师的团队研究开发的算法&#xff0c;一般用于结构化数据的异常检测。 异常的定义 针对于不同类型的异常&#xff0c;要用不同的算法来进行检测&#xff0c;而孤立森林算法主要针对的是连续型结构化…

Junit单元测试之Maven项目集成Jacoco,查看覆盖率报告

关于单元测试以及本文Calculate类等内容&#xff0c;请见前述文章Junit单元测试_Joy T的博客-CSDN博客 要学Jacoco&#xff0c;首先要知道测试覆盖率是什么&#xff01; 测试覆盖率 测试覆盖率表示的是测试用例所能触及&#xff08;或“覆盖”&#xff09;的代码百分比。换句…

2023年起重信号司索工(建筑特殊工种)证考试题库及起重信号司索工(建筑特殊工种)试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年起重信号司索工(建筑特殊工种)证考试题库及起重信号司索工(建筑特殊工种)试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特…

kafka安装和使用的入门教程

这篇文章简单介绍如何在ubuntu上安装kafka&#xff0c;并使用kafka完成消息的发送和接收。 一、安装kafka 访问kafka官网Apache Kafka&#xff0c;然后点击快速开始 紧接着&#xff0c;点击Download 最后点击下载链接下载安装包 二、启动kafka 经过上一步下载完成后&#xff…

新网站如何快速接入百度推荐

百度站长工具 在百度站长工具中点击“自动推送”&#xff0c;如下截图: 推送代码放网站的底部 将百度平台提交的主动推送代码放在自己的网站的底部模板中&#xff1b; <script> (function(){ var bp document.createElement(script); var curProtocol window.locati…

基于算术优化优化的BP神经网络(分类应用) - 附代码

基于算术优化优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录 基于算术优化优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.算术优化优化BP神经网络3.1 BP神经网络参数设置3.2 算术优化算法应用 4.测试结果…

KOSMOS-2.5:密集文本的多模态读写模型

Overview 总览摘要1 引言2 KOSMOS-2.52.1 模型结构2.1 图像和文本表征2.3 预训练数据2.4 数据处理2.5 过滤与质量控制 3 实验3.1 评估3.2 实现细节3.3 结果3.4 讨论 4 相关工作4.1 多模态大语言模型4.2 图文理解 5 总结与展望 总览 题目: KOSMOS-2.5: A Multimodal Literate M…

中断机制-通过volatile实现线程中断停止

4.1.4 大厂面试题中断机制考点 如何停止中断运行中的线程&#xff1f; 通过一个volatile变量实现 package com.nanjing.gulimall.zhouyimo.test;import java.util.concurrent.TimeUnit;/*** author zhou* version 1.0* date 2023/10/15 2:34 下午*/ public class InterruptD…

选择排序(学习笔记)

选择排序 选择排序的基本思想是冒泡排序&#xff0c;记录当前位置i和最小值k的位置&#xff0c;使用一个变量j往后寻找。 每一轮找到最小值后与第一个元素进行交换&#xff0c;以此类推。 不使用辅助变量交换两个元素的值方法 package com.company.sort;import java.util.Ra…