windows USB 设备驱动开发- 选择备用设备

news/2024/7/8 2:43:24 标签: 驱动开发

可以选择接口请求以激活 USB 接口中的备用设置。 客户端驱动程序必须在选择 USB 配置后发出此请求。 默认情况下,选择配置还会激活该配置中每个接口中的第一个备用设置。

每个 USB 配置必须支持一个或多个多个 USB 接口。 每个接口都会公开一个或多个终结点,这些终结点用于向设备传输数据或从设备传输数据。 USB 接口必须具有用于标识接口的设备定义的 接口索引 。 接口还必须具有一个或多个对接口终结点进行分组的 备用设置 。 作为设备配置的一部分,客户端驱动程序必须在接口中选择一个备用设置。 由于终结点可以在备用设置之间共享,因此在给定时间只能有一个设置处于活动状态。 备用设置处于活动状态后,其终结点将可用于数据传输。

对于多接口设备,两个接口可以在给定的时间处于活动状态。 客户端驱动程序必须在每个接口中激活备用设置。 终结点不在接口之间共享,因此,每个同时的数据传输都可以在每个接口上执行。

备用设置是设备定义的,并使用一个名为 设置索引的数字进行标识。 索引 0 处的备用设置称为本文档集中 的默认备用设置 。 USB_INTERFACE_DESCRIPTOR结构中介绍了备用设置。 结构包含与设置关联的接口索引以及设置定义的终结点数。 它还包含有关接口功能符合的类规范的信息。 终结点的分组方式取决于设备的功能。

例如,接口通过三个备用设置 (索引 0、1、2) 公开两个常时等量终结点和两个批量终结点。 备用设置 0 不定义任何终结点;备用设置 1 定义批量终结点;备用设置 2 定义常量终结点。 由于备用设置 0 没有终结点,因此客户端驱动程序可以选择此设置来禁用数据传输,以节省带宽。 当其他任一设置处于活动状态时,设备已准备好进行数据传输。 备用设置 1 可用于传输批量数据。 当设备处于流模式时,可以选择备用设置 2。 因此,备用设置使客户端驱动程序能够根据需要灵活地更改设备配置。 在此示例中,客户端驱动程序只需选择备用设置即可将设备功能从批量传输切换到流式传输。

备用设置还可用于设置带宽要求。 有关示例,请参阅 USB 设备布局。

Windows Driver Foundation (WDF) 在 内核模式驱动程序框架 和 用户模式驱动程序框架 中提供方法,客户端驱动程序可以调用这些方法以选择其他备用设置。 KMDF 客户端驱动程序可以通过指定设置索引、设置的接口描述符或提交包含请求的 URB 来选择设置。 UMDF 客户端驱动程序只能通过指定其设置索引来选择备用设置。

选择配置请求成功完成后,将停用以前处于活动状态的备用设置。

准备工作

在客户端驱动程序可以选择备用设置之前,请确保满足以下要求:

1. 客户端驱动程序必须已创建框架 USB 目标设备对象;

KMDF 客户端驱动程序必须调用 WdfUsbTargetDeviceCreateWithParameters 方法来获取 WDFUSBDEVICE 句柄;

UMDF 客户端驱动程序必须通过查询框架目标设备对象获取 IWDFUsbTargetDevice 指针; 

如果使用 Microsoft Visual Studio Professional 2012 随附的 USB 模板,则模板代码会执行这些任务。 模板代码会获取目标设备对象的句柄并将其存储在设备上下文中;

2. 设备必须具有活动配置:

KMDF 客户端驱动程序必须调用 WdfUsbTargetDeviceSelectConfig 方法;

对于 UMDF 客户端驱动程序,框架为该配置中的每个接口选择第一个配置和默认备用设置;

如果使用 USB 模板,则代码会选择每个接口中的第一个配置和默认备用设置;

在 KMDF 客户端驱动程序中选择备用设置

1.获取具有备用设置的接口的 WDFUSBINTERFACE 句柄。

若要获取句柄,首先通过调用 WdfUsbTargetDeviceGetNumInterfaces 获取所选配置的接口数,然后在循环中枚举接口。 在每个迭代中,调用 WdfUsbTargetDeviceGetInterface 方法,并从零开始递增索引 。

注意 在设备枚举期间,USB 驱动程序堆栈会将数字分配给备用设置。 接口编号是从零开始的和顺序的。 这些数字可能与设备定义的设置索引不同。 若要获取设备定义的设置索引,请调用 WdfUsbInterfaceGetInterfaceNumber 方法。

2.通过调用 WdfUsbInterfaceSelectSetting 方法启动 select-interface 请求。 在调用的 Params 参数中,选择以下选项之一:

  • 指定 USB 驱动程序堆栈分配的备用设置编号。 通常,传递在步骤 1 中用于枚举设置的相同索引;
  • 指定描述备用设置的接口描述符的指针。 然后,驱动程序可以获取接口描述符,同时通过调用 WdfUsbInterfaceGetDescriptor 方法枚举接口中的备用设置。 枚举完成后,驱动程序将获取 有关USB_INTERFACE_DESCRIPTOR 结构中所有枚举的备用设置的信息;
  • 指定指向 URB 的指针,该 URLB 包含选择接口请求所需的所有信息;

分配 USBD_INTERFACE_LIST_ENTRY 结构的数组。 此数组中的元素数取决于所选配置中的接口数。 通过调用 USBD_SelectInterfaceUrbAllocateAndBuild 例程为 select 接口请求分配 URB。 在此调用中,指定在选择配置后获取的接口列表数组和配置句柄。 可以通过调用 WdfUsbTargetDeviceWdmGetConfigurationHandle 方法获取该句柄,调用 WdfUsbInterfaceSelectSetting 并指定 URB。注意在WDM 驱动程序中,若要提交 URB,请将 URB 与 IRP 关联,然后将 IRP 提交到 USB 驱动程序堆栈。

列表中的选项为客户端驱动程序提供了指定选择条件的灵活性。 如果已知道备用设置的终结点功能,请选择列表中第一个选项 (备用设置编号) 。 否则,请选择指定接口描述符的第二个选项。 检查 USB_INTERFACE_DESCRIPTOR 结构中是否有所有备用设置。 对于每个设置,枚举其终结点及其特征,例如终结点类型、最大数据包大小等。 找到数据传输所需的终结点集时,请通过指定指向该接口描述符的指针来调用 WdfUsbInterfaceSelectSetting 。 通常,不需要第三个选项,除非你是一个基于 WDM 的客户端驱动程序,该驱动程序只能通过提交 URL 将请求发送到 USB 驱动程序堆栈。

然后,根据客户端驱动程序提供的信息,USB 驱动程序堆栈 (SET INTERFACE) 生成标准控制请求并将其发送到设备。 如果请求成功完成,USB 驱动程序堆栈将获取指向备用设置终结点的管道句柄。

选择备用设置后,客户端驱动程序必须始终获取新设置中终结点的管道句柄。 如果不这样做,可能会导致驱动程序使用过时的管道句柄发送数据传输请求。 

NTSTATUS  FX3SelectInterfaceSetting(  
    _In_ WDFDEVICE Device,
    _In_ UCHAR SettingIndex)

{
    NTSTATUS                 status;  
    PDEVICE_CONTEXT          pDeviceContext;  
    WDF_OBJECT_ATTRIBUTES               pipeAttributes;

    WDF_USB_INTERFACE_SELECT_SETTING_PARAMS settingParams;

    PAGED_CODE();  

    pDeviceContext = GetDeviceContext(Device);

    if (pDeviceContext->UsbInterface == NULL)
    {
        status = USBD_STATUS_BAD_NUMBER_OF_INTERFACES;
        goto Exit;
    }

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pipeAttributes, PIPE_CONTEXT);  

    pipeAttributes.EvtCleanupCallback = FX3EvtPipeContextCleanup;

    WDF_USB_INTERFACE_SELECT_SETTING_PARAMS_INIT_SETTING (&settingParams, SettingIndex);

    status = WdfUsbInterfaceSelectSetting (
        pDeviceContext->UsbInterface,
        &pipeAttributes,
        &settingParams);

    if (status != STATUS_SUCCESS)
    {
        goto Exit;
    }

    if (WdfUsbInterfaceGetNumConfiguredPipes (pDeviceContext->UsbInterface) > 0)
    {
        status = FX3EnumeratePipes (Device);

        if (status != STATUS_SUCCESS)
        {
            goto Exit;
        }
    }

Exit:
    return status;
}
在 UMDF 客户端驱动程序中选择备用设置
  1. 通过调用 IWDFUsbTargetDevice::GetNumInterfaces 方法获取活动配置支持的 USB 接口数;
  2. 获取配置中每个接口的 IWDFUsbInterface 指针。通过在循环中调用 IWDFUsbTargetDevice::RetrieveUsbInterface 方法枚举所有接口,直到函数返回 NULL。 每次迭代时,从零开始递增成员索引。 循环检索指向所有枚举接口的 IWDFUsbInterface 指针;
  3. 对于每个接口,通过调用 IWDFUsbInterface::GetWinUsbHandle 获取 WinUSB 句柄。 下一步需要此句柄;
  4. 调用 WinUsb_GetAssociatedInterface 以获取接口的句柄。 在 AssociatedInterfaceIndex 参数中,指定步骤 2 中的索引;
  5. 确定接口中的备用设置数。在循环中调用 WinUsb_QueryInterfaceSettings 函数,并在每次迭代中递增索引 (从零开始的) 。 枚举所有设置后,函数将返回ERROR_NO_MORE_ITEMS。 函数还为每个设置返回接口描述符;
  6. 通过使用在每个接口描述符的 bNumEndpoints 成员中收到的值,并枚举其终结点。 检查终结点描述符并确定哪个设置符合要求;
  7. 通过调用 WinUsb_SetCurrentAlternateSetting 函数启动选择接口请求。 在调用中,指定与步骤 4 中的索引关联的备用设置编号;
  8. 释放通过调用 WinUsb_Free 函数在步骤 4 中获取的接口句柄;
  9. 通过调用 WinUsb_Free 函数释放在步骤 3 中获取的 WinUSB 句柄;
  10. 如果已完成 IWDFUsbInterface 方法的用法,请释放步骤 2 中检索到的所有接口指针;

对于 KMDF 客户端驱动程序,在其 WdfUsbInterfaceSelectSetting 调用中,驱动程序可以提供指向驱动程序定义的管道上下文的指针。 客户端驱动程序可以在管道上下文中存储有关管道的信息。 

配置 Usbccgp.sys 以选择非默认 USB 配置

在注册表设置的信息中,有些设置配置 Usbccgp.sys 选择 USB 配置的方式;同时Usbccgp.sys可以处理由控制复合设备功能之一的客户端驱动程序发送的选择配置请求。

USB 复合设备由多个功能设备组成的单个 USB 设备。 如果 Windows 为复合设备加载 Microsoft 提供的 USB 通用父驱动程序 (Usbccgp.sys) ,则从该点开始,Usbccgp.sys 负责选择设备的配置。 在很多方面,复合设备的每个接口或接口集合都类似于具有其自己的物理设备对象的单独设备 (PDO) 。 重置设备的配置会更改设备的所有接口的配置,而不仅仅是客户端驱动程序控制的接口。 操作系统不允许这样做。 因此,控制一组接口或复合设备的接口集合的客户端驱动程序无法更改最初由 Usbccgp.sys 设置的配置。

但是,在 Windows Vista 和更高版本的 Windows 中,可以添加以下注册表值来指定要选择的配置: 

默认情况下,上述注册表设置不存在。 必须在 硬件/设备USB 设备的密钥下添加它们。

注册表设置允许 CCGP 驱动程序选择备用配置。

上表中所述的注册表值对应于 USB 定义的配置索引,由配置描述符的 bConfigurationValue 成员 (USB_CONFIGURATION_DESCRIPTOR) 指示, 而不是 由设备配置描述符中报告的 bConfigurationNum 值指示。 首先,Usbccgp.sys 使用 OriginalConfigurationValue 指定的 USB 配置索引将选择配置请求发送到父 USB 总线驱动程序 (Usbhub.sys) 。 如果该请求失败,Usbccgp.sys 尝试使用 AlternateConfigurationValue 中指定的值。 如果 AlternateConfigurationValue 或 OriginalConfigurationValue 无效,Usbccgp.sys 使用默认值。

选择配置请求可能由于多种原因而失败。 当设备未正确响应请求或 bMaxPower 值 (所请求的配置所需的电源) 超过中心端口支持的电源值时,会发生最常见的故障。 例如,由 OriginalConfigurationValue) 指定的特定配置 (bMaxPower 为 100 毫安,但中心端口只能提供 50 毫安。 当 Usbccgp.sys 发送该配置的选择配置请求时,USB 驱动程序堆栈 中的USB 端口驱动程序会将请求失败。 Usbccgp.sys 然后通过指定 AltConfigurationValue 指示的配置发送另一个选择配置请求。 如果备用配置需要 50 毫安或更少,并且没有发生其他问题,则选择配置请求将成功完成。

兼容性功能

即使复合设备中某个函数的客户端驱动程序无法选择复合设备的配置,客户端驱动程序仍然可以向 Usbccgp.sys 发送选择配置请求。  Usbccgp.sys 从客户端驱动程序收到选择配置请求后执行以下任务:

  • 使用 USB 端口驱动程序用于验证任何选择配置请求的相同条件来验证收到的请求;
  • 如果请求指定与当前设置不同的接口或管道设置,Usbccgp.sys 发送类型为URB_FUNCTION_SELECT_INTERFACE的 URB,以将现有设置更改为新接口和管道设置,从而发出选择接口请求;
  • 将 USBD_INTERFACE_INFORMATION 和 USBD_PIPE_INFORMATION 结构的缓存内容复制到 URB 中;
  • 完成 URB;

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

相关文章

暄桐好作业之《临吴昌硕〈萧斋清供图〉》

暄桐是一间传统美学教育教室,创办于2011年,林曦是创办人和授课老师,教授以书法为主的传统文化和技艺,皆在以书法为起点,亲近中国传统之美,以实践和所得,滋养当下生活。      其中“暄桐好作…

简历–求职信–通用

每个毕业生的简历首页大概都会是一封求职信。如果说对求职者的简历正文我们只是浮光掠影看上几眼的话,那么对求职信,简直连浮光掠影都称不上。说实话,我在看求职者简历的时候一般会把这一页翻过去,很少去看。为什么呢?…

探索视频合成新境界:加快加长视频生成,PAB加速与ExVideo延展技术介绍

一、摘要 随着人工智能技术的不断进步,视频合成领域正迎来前所未有的发展机遇。本文介绍近期两项视频生成方向的创新技术:PAB(Pyramid Attention Broadcast)和ExVideo。这两篇文章合在一起主要介绍如何提升视频生成的速度与长度&a…

opencv实现人脸检测功能----20240704

opencv实现人脸检测 早在 2017 年 8 月,OpenCV 3.3 正式发布,带来了高度改进的“深度神经网络”(dnn)模块。 该模块支持多种深度学习框架,包括 Caffe、TensorFlow 和 Torch/PyTorch。OpenCV 的官方版本中包含了一个更准确、基于深度学习的人脸检测器, 链接:基于深度学习…

基于单片机的出租车计价器实验教学案例设计

摘 要 为了让学生加深单片机的理解,加强学生的单片机技术应用、实践动手、创新能力的培养,根据单片机课程设计教学情况精心设计了基于单片机的出租车计价器实验教学案例。本教学案例的基本原理是速度的检测,里程、价格的计算和显示。学生通…

工程安全监测仪器振弦采集仪提升工程质量和安全水平

工程安全监测仪器振弦采集仪提升工程质量和安全水平 振弦采集仪是一种重要的工程安全监测仪器,可以用来监测建筑物、桥梁、隧道等工程结构的振动情况。它通过测量结构物的振动频率和振幅,可以提供关键的数据用于评估结构的安全性和稳定性。振弦采集仪在…

Django REST Framework(四)DRF APIVIEW

REST framework 传入视图的request对象不再是Django默认的HttpRequest对象,而是REST framework提供的扩展了HttpRequest类的Request类的对象。 REST framework 提供了Parser解析器,在接收到请求后会自动根据Content-Type指明的请求数据类型(…

单片机软件架构连载(4)-结构体

枚举、指针、结构体,我愿称为C语言"三板斧"。 用人话来讲,几乎所有c语言高阶编程,都离不开这这3个知识点的应用。 今天站在实际产品常用的角度,给大家讲一下结构体。 1.结构体概念 结构体可以用来构建更复杂的数据结…