MSDN WinUSB Example

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 }

时间: 2024-11-03 02:28:04

MSDN WinUSB Example的相关文章

第三十六篇:WinUSB调试实例

有人问,前面的博文,分别列出了USB xHCI, USB3 HUB, UCX01000的符号有什么用? 答案是,虽然我们不能看到MICROSOFT 的源代码,但通过这些符号,可以帮助我们调试USB子系统. 下面给出一例: 做USB设备驱动这些年,用过Cypress的USB3.0驱动,改过Philips USB1.1, Cypress USB2.0的驱动代码, 开发了基于Microsoft USBSamp的USB IP测试软件包. 最近,又借助WinUSB来完成一个音视频设备项目. 使用WinUS

来自微软的一封学习网站的信-【关于MSDN的使用教程】

相信"微软公司"大家都是耳濡目染的一个公司. 前段时间一直在研究微软公司的社区和它的视频系列课程怎么用,今天就来介绍介绍一下,这视频系列的怎么使用,以及下载问题! 这里面的课程都是外教的课程,同时你也可以调整语速,真的是特别方便! 使用Microsoft Developer Network 学习开发是多么方便的网站,而且外国人的思想有些还是特别有新意的! 教程开始啦! 首先在百度搜索"MSDN",然后点击它的官方网站,具体的看以下图片 另外再看看Google上搜索情

Linq善解人意之通过MSDN对14个“查询关键字“逐个解剖

linq中存在的 14个关键字 网址: https://msdn.microsoft.com/zh-cn/library/bb310804.aspx from: 迭代变量 where:对数据源进行逻辑筛选 select:对数据进行塑形. group: 分组 into: 分组链接 orderby[ascending/descending]: 排序 join:表关联 let:就是局部变量 string[] strings = { "A penny saved is a penny earned.&q

来自MSDN的RibbonGadgets练习

来自MSDN的RibbonGadgets练习 RibbonGadgets是少见的来自官方的资源. 如果选择Menu Items = 集合,则会有向下的小箭头,同时会出现下来菜单. 这个都关系叫做gallery button 同时设置这个可以获得 而colorbutton主要是为了获得color而获得的对应 这个所谓库按钮,可是非常有用的.它比较小,但是好用的. 可以multi-line,可以link,应该是比较好用的. 就差一个上下文了,没有资料呀. 来自为知笔记(Wiz) 附件列表

办公软件套装 MSDN Office 2016 专业增强版

Microsoft Office 2016 是微软推出的又一代全新的办公自动化软件套装,其开发代号为 Office 16,实际上是第十四个发行版本,目前微软针对该套装在订户下载专区仅提供专业增强版,其将维持用户一直以来熟悉的操作体验,非常适合配备鼠标键盘的电脑使用. Office 2016 延续了 Office 2013 的扁平化用户界面设计,同时也和 Windows 10 有重要的整合,包括 Windows Hello 支持.Cortana 可以通过 Outlook 2016 获取到你的信息和

英文VS2010安装中文版MSDN文档方法

英文VS2010安装中文版MSDN文档方法 2010-06-01 11:52 by 李永京, 51409 阅读, 50 评论, 收藏, 编辑 在2010年4月12号发布Visual Studio 2010 and .NET 4正式版.5月26日微软发布了Visual Studio 2010 and .NET 4 RTM中文版,我们还是喜欢使用英文版本VS2010,但是想安装中文版MSDN文档学习下新东西. 发现我们使用Help Library Manager指向cn_visual_studio_

MSDN for VS2012 的安装

在VS2012中,由于MSDN默认不内置,VS2008 以上的就没有独立的 MSDN 了 ,而是被 Microsoft Help Viewer 取代了. 该组件包含在 VS2012 的 ISO 安装镜像中,在安装 VS2012 的过程中会一并装上. 因此,安装就要调用Microsoft Help Viewer来安装,用快捷键Ctrl+Alt+F1可调出. MSDN for Vs2012 在这里下载:http://www.microsoft.com/zh-CN/download/details.a

装机员U盘启动PE制作工具V5.0(UEFI+UD+首发自动安装MSDN版系统)

软件名称: 装机员U盘启动PE制作工具V5.0(UEFI+UD) 软件语言: 简体中文 软件大小: 288 大小: MB 发布日期: 2016-10-02 文件名称: ZhuangJiYuanPESetup_V5.0.exe M D 5: E8EBB32CB08E914F3C5E0B8BC1A4ACAB 软件封面: 迅雷下载: thunder://QUFodHRwOi8vZG93bi56aHVhbmdqaXl1YW4uY29tOjk1My9aaHVhbmdKaVl1YW5QRVNldHVwX1Y

细谈MSDN

MSDN其实就是软件库, 这套MSDN资料库涵盖了微软全套可开发产品线的技术开发文档和科技文献,部分包括源代码,也包括过刊的 MSDN 杂志节选和部分经典书籍的节选章节. 顺便说一下,msdn网站的备案作者 是中国人,并非微软公司,虽然提供微软镜像产品.并非违法.作者是一位软件工程师,因为订阅msdn是要收开发费用的,作者名字忘记啦. MSDN 库为使用 Microsoft工具.产品.技术和服务的开发人员提供必不可少的信息资源,是win32开发人员必备的重要参考资料.这款MSDN Library