The WinUSB user-mode library uses device interface classes to communicate with the kernel-mode USB stack. The INF file that loads winusb.sys specifies a device interface class GUID in the registry. When winusb.sys loads, it calls IoRegisterDeviceInterface to register a device interface that belongs to the device interface class that is specified in the registry.

User-mode software must call SetupDiGetClassDevs to enumerate the registered device interfaces that are associated with one of these device interface classes. The user-mode software must then pass the symbolic link of a device interface to the WinUsb_Initialize routine to obtain a WinUSB handle for the device interface.

The code example in this topic illustrates how user-mode software can enumerate device interfaces and obtain a WinUSB handle. For this example, assume that the INF file stores a device interface class GUID in the registry as follows.

HKR,,DeviceInterfaceGUIDs, 0x10000,"{058815B2-9805-47d3-B7D5-ABC464D3CA06}"

The example user-mode software calls SetupDiGetClassDevs to query for information about all of the registered device interfaces in the device interface class that is associated with this GUID. SetupDiGetClassDevs then returns a handle to a device information set that contains information about the device interfaces.

#include initguid.h
#include setupapi.h

// Example GUID definition. This GUID must match 
// the GUID that was specified in the INF file 
// that loaded winusb.sys.

DEFINE_GUID(InterfaceClassGuidConstant,0x058815B2, 0x9805, 0x47d3, 0xB7, 0xD5, 0xAB, 0xC4, 0x64, 0xD3, 0xCA, 0x06);
GUID InterfaceClassGuid = InterfaceClassGuidConstant;

// Define a handle to a device information set.
HDEVINFO  hdevClassInfo;

// Retrieve a device information set.
hdevClassInfo = SetupDiGetClassDevs
        (&InterfaceClassGuid, NULL, NULL,
        DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hdevClassInfo == INVALID_HANDLE_VALUE) { 
        // ERROR }

The call to SetupDiGetClassDevs in the preceding code
example requests registered device interfaces (DIGCF_DEVICEINTERFACE) for the
device interface class that the InterfaceClassGuid variable specifies.
Only device interfaces for presently installed devices (DIGCF_PRESENT) are
returned.

Next, the example application must iteratively call SetupDiEnumDeviceInterfaces
to determine how many elements are in the device information set.

// Initialize variables.
SP_DEVICE_INTERFACE_DATA  DeviceData;
DeviceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);

for (nMemberIndex = 0; TRUE; nMemberIndex++) {
    nStatus = SetupDiEnumDeviceInterfaces (hdevClassInfo, NULL,
    (LPGUID)&InterfaceGuid, nMemberIndex,
    &DeviceData);
    if (nStatus != TRUE) break;
}

Now, the example application must enumerate the registered device interfaces
that are associated with the device interface class. The example application
calls SetupDiEnumDeviceInterfaces iteratively, once again; but
now it retrieves hardware identifiers (IDs) and symbolic links for each
registered interface. The application will use the symbolic links to obtain a
WinUSB device interface handle.

// Allocate array that will hold information about the devices that
// are associated with this interface class.
struct DeviceData {
  TCHAR  *HardwareId;
  TCHAR  *Path; // symbolic link
  TCHAR  *FriendlyName;
  DWORD  DeviceInstance;
} *DeviceList;
DeviceList = (struct DeviceData *) malloc 
    ((nMemberIndex + 1) * sizeof(struct DeviceData));
if (DeviceList == NULL) { // ERROR }

// Enumerate devices that are associated with the interface.
for (i = 0; i < nMemberIndex; i++) {
    nStatus = SetupDiEnumDeviceInterfaces
                 (hdevClassInfo, NULL,
                 (LPGUID)&InterfaceGuid, i,
                 &DeviceData);
    if (nStatus != TRUE) break;

// Retrieve the size of the device data.
    nStatus = SetupDiGetDeviceInterfaceDetail
                 (hdevClassInfo, &DeviceData, 
                 NULL, 0, &nSize, NULL);                  
    if (nStatus != TRUE) break;

// Allocate memory for the device detail buffer. 
    SP_DEVICE_INTERFACE_DATA  pBuffer;
    pBuffer = (PSP_INTERFACE_DEVICE_DETAIL_DATA)
              malloc (nSize));
    if (pBuffer == NULL) { // ERROR }

// Initialize variables.
    DeviceData.cbSize =
        sizeof(SP_INTERFACE_DEVICE_DATA);
    nStatus = SetupDiGetDeviceInterfaceDetail
                 (hdevClassInfo, &DeviceData,
                 pBuffer, nSize, NULL,&DeviceData));
    if (nStatus = FALSE)) { // ERROR }

//****************************************
    // Save the device interface path: 
    //           This path can be used to open 
    //           the interface with CreateFile.
    //****************************************

// Calculate the length of the path string. 
    // Add 1 for the terminating NULL character.
    nLen = strlen(DeviceData.DevicePath) + 1; 
    DeviceList[i].Path = 
       (TCHAR *) malloc (nLen * sizeof(TCHAR));
    StringCchCopy(DeviceList[i].Path, nLen, 
       DeviceData.DevicePath);

// Save the device instance.
    DeviceList[i].DeviceInstance = 
       DeviceInfoData.DevInst;

//****************************************
    // Retrieve registry values.
    //****************************************

// Initialize variables that are used in registry
    // operations.
    SP_DEVINFO_DATA DevInfoData;

//****************************************
    // Retrieve the device friendly name.
    //****************************************

// Query for the size of the friendly name.
    nStatus = SetupDiGetDeviceRegistryProperty
                (hdevClassInfo, &DevnfoData,
                SPDRP_FRIENDLYNAME, &dwRegType,
                NULL, 0, &dwRegSize);
    if (nStatus == FALSE) { // ERROR }

// Allocate buffer for the friendly name.
    pBuffer = (TCHAR *) malloc 
                  (dwRegSize * sizeof(TCHAR));
    if (pBuffer =  == NULL) { // ERROR }

// Retrieve the friendly name.
    nStatus = SetupDiGetDeviceRegistryProperty
                (hdevClassInfo, &DevInfoData,
                SPDRP_FRIENDLYNAME, NULL,
                (PBYTE) *pBuffer, dwRegSize, NULL);
    if (nStatus == FALSE) { // ERROR }

// Store the friendly name for this device.
    DeviceList[i].FriendlyName = pBuffer;

// ************************************
    // Retrieve the hardware ID.
    // ************************************

// Query for the size of the hardware ID.
    nStatus = SetupDiGetDeviceRegistryProperty
                (hdevClassInfo, &DevnfoData,
                SPDRP_HARDWAREID, &dwRegType,
                NULL, 0, &dwRegSize);
    if (nStatus == FALSE) { // ERROR }

// Allocate a buffer for the hardware ID.
    pBuffer = (TCHAR *) malloc 
       (dwRegSize * sizeof(TCHAR));
    if (pBuffer =  == NULL) { // ERROR }

// Retrieve the hardware ID.
    nStatus = SetupDiGetDeviceRegistryProperty
                (hdevClassInfo, &DevInfoData,
                SPDRP_HARDWAREID, NULL,
                (PBYTE) *pBuffer, dwRegSize, NULL);
    if (nStatus == FALSE) { // ERROR }

// Store the hardware ID for this device.
    DeviceList[i].HardwareId = pBuffer;
}

The example software next opens the first device interface in the device
interface list. The device interface must be opened with the overlapped
flag.

// Create a symbolic link to device interface
LPCTSTR Path; 
HANDLE DeviceInterfaceHandle;

Path = DeviceList[0].Path;
DeviceInterfaceHandle = CreateFile (Path,
                        GENERIC_READ | GENERIC_WRITE,
                        FILE_SHARE_READ |
                        FILE_SHARE_WRITE,
                        NULL,
                        OPEN_EXISTING,
                        FILE_FLAG_OVERLAPPED,
                        NULL);
if (DeviceInterfaceHandle == INVALID_HANDLE_VALUE) { // ERROR }

After the example software opens the device interface, the application must
call WinUsb_Initialize to obtain a WinUSB handle.

WINUSB_INTERFACE_HANDLE WinUSBHandle;
nStatus = WinUsb_Initialize (DeviceInterfaceHandle, &WinUSBHandle);
if (nStatus = FALSE) { // ERROR }

The example software manages a composite USB device, whose first interface
(interface 0) contains bulk transfer endpoints. In the following code example,
the example software:

  1. Calls WinUsb_QueryInterfaceSettings to retrieve the
    interface descriptor (USB_INTERFACE_DESCRIPTOR)
    for interface 0.
  2. Calls WinUsb_QueryPipe to query for information (WINUSB_PIPE_INFORMATION) about the pipe for endpoint 0.
  3. Verifies that the pipe is a bulk transfer pipe.
  4. Calls WinUsb_SetPipePolicy to set the time-out
    interval for the pipe.

// ********************************************
// The first interface is for bulk transfers.
// ********************************************

USB_INTERFACE_DESCRIPTOR interface;
nStatus = WinUsb_QueryInterfaceSettings
            (WinUSBHandle, 0, &interface);
if (nStatus = FALSE) { // ERROR }

WINUSB_PIPE_INFORMATION pipe;
nStatus = WinUsb_QueryPipe (WinUSBHandle, 0, 
            (UCHAR) 0, &pipe);
if (nStatus == FALSE) { // ERROR }

Verify that the pipe type is set to the correct USBD_PIPE_TYPE
enumeration value before calling WinUsb_SetPipePolicy.

if (pipe.PipeType != UsbdPipeTypeBulk) { // ERROR }

// Set the transfer time-out interval for endpoint 0
// to 10000 milliseconds.
UCHAR timeout = 10000;
nStatus = WinUsb_SetPipePolicy (WinUSBHandle,
            pipe.PipeId, PIPE_TRANSFER_TIMEOUT,
            sizeof (timeout), &timeout);
if (nStatus == FALSE) { // ERROR }

The second interface (interface 1) contains interrupt transfer endpoints. In
the following code example, the example software

  1. Calls WinUsb_GetAssociatedInterface to obtain a
    handle to interface 1.
  2. Calls WinUsb_QueryInterfaceSettings to retrieve the
    interface descriptor for interface 1.
  3. Calls WinUsb_QueryPipe to query for information about the
    pipe for endpoint 0.
  4. Verifies that the pipe is an interrupt transfer pipe.

// *************************************************
// The second interface is for interrupt transfers
// *************************************************

WINUSB_INTERFACE_HANDLE WinUSBHandleAlt;
nStatus = WinUsb_GetAssociatedInterface (WinUSBHandle, 0, 
                        &WinUSBHandleAlt);
if (nStatus == FALSE) { // ERROR }

nStatus = WinUsb_QueryInterfaceSettings (WinUSBHandleAlt, 0,
                        &interface);
if (nStatus == FALSE) { // ERROR }

nStatus = WinUsb_QueryPipe (WinUSBHandleAlt, 0, (UCHAR) 0, &pipe);
if (nStatus == FALSE) { // ERROR }

if (pipe.PipeType != UsbdPipeTypeInterrupt) { // ERROR }

MSDN WinUSB Example的更多相关文章

  1. Visual Studio 2010的MSDN帮助文档离线使用

    如果没有在安装vs过程中安装帮助,也可通过Visual Studio帮助菜单中的Manage Help Settings来对帮助进行设置或安装. 可以选择从磁盘安装内容,如果选择从磁盘安装可能会要求提 ...

  2. MSDN文档篇

    很多人网上下载3~10G不等的MSDN文档,发现,下载完成了不会用 很多人每次都得在线下载文档,手上万千PC,都重新下载不是得疯了? so==> 先看几张图 推荐一个工具:https://vsh ...

  3. "Installation failed !" in GUI but not in CLI (/usr/bin/winusb: line 78: 18265 Terminated )

    "Installation failed !" in GUI but not in CLI (/usr/bin/winusb: line 78: 18265 Terminated ...

  4. 使用SHFB(Sandcastle Help File Builder)建立MSDN风格的代码文档

    使用SHFB(Sandcastle Help File Builder)建立MSDN风格的代码文档 下载地址:http://sandcastle.codeplex.com/ 下载地址2:http:// ...

  5. MSDN杂志上Wix相关的文章

    使用 MSBuild 和 Windows Installer XML 执行自动发布: http://msdn.microsoft.com/zh-cn/magazine/cc163456.aspx 用于 ...

  6. 使用 Async 和 Await 的异步编程(C# 和 Visual Basic)[msdn.microsoft.com]

    看到Microsoft官方一篇关于异步编程的文章,感觉挺好,不敢独享,分享给大家. 原文地址:https://msdn.microsoft.com/zh-cn/library/hh191443.asp ...

  7. [已解决]从微软合作伙伴资源和MSDN下载系统和软件Microsoft download Manager无效

    有个itellyou,更新了所有MSDN的软件包.如果自己有微软的注册账户,还是从微软官网下载比较好.而且对自己账户里的系统和itellyou里的做了对比.发现SHA1码不相同,估计官方分配的序列号也 ...

  8. diff/merge configuration in Team Foundation - common Command and Argument values - MSDN Blogs

    One of the extensibility points we have in Team Foundation V1 is that you can configure any other di ...

  9. 源码网站(msdn.itellyou.cn) good

    verysource 100万源码http://www.verysource.com/category/delphi-vcl/ MSDN DOWNLOADhttp://msdn.itellyou.cn ...

随机推荐

  1. 【转】XMPP_3920_最靠谱的中文翻译文档

    CHENYILONG Blog XMPP_3920_最靠谱的中文翻译文档 Fullscreen © chenyilong. Powered by Postach.io Blog

  2. Linux - ssh 连接慢解决

    解决 ssh 链接慢 sed -i 's/GSSAPIAuthentication yes/GSSAPIAuthentication no/' /etc/ssh/sshd_config sed -i ...

  3. HDU 4508 湫湫系列故事——减肥记I (完全背包)

    题意:有n种食物,每种食物可以给湫湫带来一个幸福感a,同时也会给她带来b的卡路里的摄入,然后规定她一天摄入的卡路里的量不能超过m,一共有n种食物,问可以得到的 最大的幸福感是多少? 解题报告:一开始以 ...

  4. Python 装饰器入门(下)

    继续上次的进度:https://www.cnblogs.com/flashBoxer/p/9847521.html 正文: 装饰类 在类中有两种不通的方式使用装饰器,第一个和我们之前做过的函数非常相似 ...

  5. 洛谷 P2089 烤鸡

    看了前面大佬的代码,发现这道题的解题思路都大同小异. 首先肯定要定义一个变量累加方案数量,因为方案数量要最先输出,所以所有方案要先储存下来.个人不喜欢太多数组,就只定义一个字符串. 然后我们发现只有1 ...

  6. python selenium - web自动化环境搭建

    前提: 安装python环境. 参考另一篇博文:https://www.cnblogs.com/Simple-Small/p/9179061.html web自动化:实现代码驱动浏览器进行点点点的操作 ...

  7. oracle 级联查询 根路径

    级联查询有很多教程示例,但是没有找到求特定子孙到根的路径的例子,折腾了一番总算想出方法了. 现假设我们拥有一个菜单表t_menu,其中只有三个字段:id.name和parent_id.它们是具有父子关 ...

  8. 【题解】BZOJ 1901: Zju2112 Dynamic Rankings

    题目传送门(权限题) 一道类似的非权限题 题意 N个数的序列,每次修改一个数或者询问区间里的第K小.可以离线. 简要做法 假如要求在线,可以树状数组套个线段树~ 但是这题是可以离线的,就可以乱搞整体二 ...

  9. python强大的数据类型转换

    # 原始的二维表数据集 jsonObj=[] # 添加模拟的数据 for i in range(1001,1004): for j in range(1,34): jsonObj.append({&q ...

  10. .NetCore中的程序通过Docker在CentOS中部署

    基础说明 安装Docker过程就略过了 创建一个Asp.Net Core程序 启用Docker支持,会生成Dockerfile文件,接下来看下这个文件,当然不同的版本生成的具体可能不一致 FROM m ...