windows USB 装备驱动开发-USB复合装备的注册

[复制链接]
发表于 2026-2-26 07:13:09 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
USB 多功能装备的驱动步调(称为复合驱动步调)可以向根本 USB 驱动步调堆栈注册和注销复合装备。 Microsoft 提供的驱动步调(Usbccgp.sys)是由 Windows 加载的默认复合驱动步调。 本文中的过程实用于更换Usbccgp.sys的基于 WDM的自界说 Windows 驱动步调模子 。
通用串行总线 (USB) 装备可以提供多个同时处于运动状态的功能。 此类多功能装备也称为 复合装备。 比方,复合装备大概为键盘功能界说一个函数,为鼠标界说另一个函数。 复合驱动步调罗列装备的功能。 复合驱动步调可以在团体模子中管理这些函数本身,或为每个函数创建物理装备对象 (PDO) 。 这些单独的 PDO 由各自的 USB 功能驱动步调、键盘驱动步调和鼠标驱动步调管理。
USB 3.0 规范界说了 函数停息和长途唤醒功能 ,使各个函数可以或许进入和退出低功耗状态,而不会影响其他功能或整个装备的电源状态。 
若要使用该功能,复合驱动步调须要将装备注册到根本 USB 驱动步调堆栈。 由于该功能实用于 USB 3.0 装备,因此复合驱动步调必须确保根本堆栈支持版本USBD_INTERFACE_VERSION_602。 通过注册哀求,复合驱动步调:

  • 关照根本 USB 驱动步调堆栈,驱动步调负责发送哀求,以支持功能驱动举行长途唤醒。 长途唤醒哀求由 USB 驱动步调堆栈处理处罚,该堆栈将须要的协议哀求发送到装备;
  • 获取 (USB 驱动步调堆栈分配的每个函数) 一个函数句柄的列表。 然后,复合驱动步调可以在驱动步调的哀求中使用函数句柄,以便长途唤醒与句柄关联的函数;
通常,复合驱动步调在驱动步调的 AddDevice 或启动装备例程中发送注册哀求来处理处罚 IRP_MN_START_DEVICE。 因此,复合驱动步调会开释在驱动步调的卸载例程,比方 stop-device (IRP_MN_STOP_DEVICE ) 或 remove-device 例程 (IRP_MN_REMOVE_DEVICE) 中为开释在注册时分配的资源。
先决条件

发送注册哀求之前,请确保:

  • 你拥有装备中的函数数。 该数字可以派生 get-configuration 哀求检索到的形貌符;
  • 在对 USBD_CreateHandle 的上一次调用中,你已得到 USBD 句柄;
  • 根本 USB 驱动步调堆栈支持 USB 3.0 装备。 为此,请调用 USBD_IsInterfaceVersionSupported 并将 USBD_INTERFACE_VERSION_602 作为版本转达给 查抄;
注册复合装备

以下过程先容怎样天生和发送注册哀求,以将复合驱动步调与 USB 驱动步调堆栈相干联。
1.分配 COMPOSITE_DEVICE_CAPABILITIES 布局并通过调用 COMPOSITE_DEVICE_CAPABILITIES_INIT 宏对其举行初始化;
2.将 COMPOSITE_DEVICE_CAPABILITIES 的 CapabilityFunctionSuspend 成员设置为 1;
3.分配 REGISTER_COMPOSITE_DEVICE 布局,并通过调用 USBD_BuildRegisterCompositeDevice 例程初始化 布局 。 在调用中,指定 USBD 句柄、初始化 COMPOSITE_DEVICE_CAPABILITIES 布局和函数数;
4.通过调用 IoAllocateIrp (IRP) 分配 I/O 哀求数据包,并通过调用 IoGetNextIrpStackLocation 获取指向 IRP 的第一个堆栈位置的指针 (IO_STACK_LOCATION) ;
5.为足以容纳函数句柄数组的缓冲区分配内存 (USBD_FUNCTION_HANDLE) 。 数组中的元素数必须是 PDO 的数目;
6.通过设置 IO_STACK_LOCATION的以下成员来天生哀求:

  • 通过将 Parameters.DeviceIoControl.IoControlCode 设置为 IOCTL_INTERNAL_USB_REGISTER_COMPOSITE_DEVICE,指定哀求的范例。
  • 通过将 Parameters.Others.Argument1 设置为初始化的 REGISTER_COMPOSITE_DEVICE 布局的地点来指定输入参数。
  • 通过将 AssociatedIrp.SystemBuffer 设置为在步调 5 中分配的缓冲区来指定输出参数。
7.调用 IoCallDriver ,通过将 IRP 转到达下一个堆栈位置来发送哀求;
完成后,查抄 USB 驱动步调堆栈返回的函数句柄数组。 可以将数组存储在驱动步调的装备上下文中,以供未来使用;
下面的代码示例演示怎样天生和发送注册哀求。 该示例假定复合驱动步调将从前获取的函数数和 USBD 句柄存储在驱动步调的装备上下文中。
  1. VOID  RegisterCompositeDriver(PPARENT_FDO_EXT parentFdoExt)  
  2. {  
  3.     PIRP                            irp;  
  4.     REGISTER_COMPOSITE_DRIVER       registerInfo;  
  5.     COMPOSITE_DRIVER_CAPABILITIES   capabilities;  
  6.     NTSTATUS                        status;  
  7.     PVOID                           buffer;  
  8.     ULONG                           bufSize;  
  9.     PIO_STACK_LOCATION              nextSp;  
  10.     buffer = NULL;  
  11.     COMPOSITE_DRIVER_CAPABILITIES_INIT(&capabilities);  
  12.     capabilities.CapabilityFunctionSuspend = 1;  
  13.     USBD_BuildRegisterCompositeDriver(parentFdoExt->usbdHandle,  
  14.         capabilities,  
  15.         parentFdoExt->numFunctions,  
  16.         &registerInfo);  
  17.     irp = IoAllocateIrp(parentFdoExt->topDevObj->StackSize, FALSE);  
  18.     if (irp == NULL)
  19.     {  
  20.         //IoAllocateIrp failed.
  21.         status = STATUS_INSUFFICIENT_RESOURCES;  
  22.         goto ExitRegisterCompositeDriver;   
  23.     }  
  24.     nextSp = IoGetNextIrpStackLocation(irp);  
  25.     bufSize = parentFdoExt->numFunctions * sizeof(USBD_FUNCTION_HANDLE);  
  26.     buffer = ExAllocatePoolWithTag (NonPagedPool, bufSize, POOL_TAG);  
  27.     if (buffer == NULL)
  28.     {  
  29.         // Memory alloc for function-handles failed.
  30.         status = STATUS_INSUFFICIENT_RESOURCES;  
  31.         goto ExitRegisterCompositeDriver;   
  32.     }  
  33.     nextSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;     
  34.     nextSp->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_REGISTER_COMPOSITE_DRIVER;  
  35.     //Set the input buffer in Argument1      
  36.     nextSp->Parameters.Others.Argument1 = &registerInfo;  
  37.     //Set the output buffer in SystemBuffer field for USBD_FUNCTION_HANDLE.      
  38.     irp->AssociatedIrp.SystemBuffer = buffer;  
  39.     // Pass the IRP down to the next device object in the stack. Not shown.
  40.     status = CallNextDriverSync(parentFdoExt, irp, FALSE);  
  41.     if (!NT_SUCCESS(status))
  42.     {  
  43.         //Failed to register the composite driver.
  44.         goto ExitRegisterCompositeDriver;   
  45.     }  
  46.     parentFdoExt->compositeDriverRegistered = TRUE;  
  47.     parentFdoExt->functionHandleArray = (PUSBD_FUNCTION_HANDLE) buffer;  
  48. End:  
  49.     if (!NT_SUCCESS(status))
  50.     {  
  51.         if (buffer != NULL)
  52.         {  
  53.             ExFreePoolWithTag (buffer, POOL_TAG);  
  54.             buffer = NULL;  
  55.         }  
  56.     }  
  57.     if (irp != NULL)
  58.     {  
  59.         IoFreeIrp(irp);  
  60.         irp = NULL;  
  61.     }  
  62.     return;  
  63. }
复制代码
取消注册复合装备


  • 通过调用 IoAllocateIrp 分配 IRP,并通过调用 IoGetNextIrpStackLocation 获取指向 IRP 的第一个堆栈位置 (IO_STACK_LOCATION) 的指针;
  • 通过将 IO_STACK_LOCATION 的 Parameters.DeviceIoControl.IoControlCode 成员设置为IOCTL_INTERNAL_USB_UNREGISTER_COMPOSITE_DEVICE来天生哀求;
  • 调用 IoCallDriver ,通过将 IRP 转到达下一个堆栈位置来发送哀求;
复合驱动步调在 remove-device 例程的上下文中发送一次 IOCTL_INTERNAL_USB_UNREGISTER_COMPOSITE_DEVICE 哀求。 哀求的目标是删除 USB 驱动步调堆栈与复合驱动步调及其罗列函数之间的关联。 该哀求还会整理为维护该关联而创建的全部资源,以及上一个注册哀求中返回的全部函数句柄。
下面的代码示例演示怎样天生并发送取消注册复合装备的哀求。 该示例假定复合驱动步调从前是通过注册哀求注册的,如本主题前面所述。
  1. VOID  UnregisterCompositeDriver(  
  2.     PPARENT_FDO_EXT parentFdoExt )  
  3. {  
  4.     PIRP                irp;  
  5.     PIO_STACK_LOCATION  nextSp;  
  6.     NTSTATUS            status;  
  7.     PAGED_CODE();  
  8.     irp = IoAllocateIrp(parentFdoExt->topDevObj->StackSize, FALSE);  
  9.     if (irp == NULL)
  10.     {  
  11.         //IoAllocateIrp failed.
  12.         status = STATUS_INSUFFICIENT_RESOURCES;  
  13.         return;  
  14.     }  
  15.     nextSp = IoGetNextIrpStackLocation(irp);  
  16.     nextSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;     
  17.     nextSp->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_UNREGISTER_COMPOSITE_DRIVER;  
  18.     // Pass the IRP down to the next device object in the stack. Not shown.
  19.     status = CallNextDriverSync(parentFdoExt, irp, FALSE);  
  20.     if (NT_SUCCESS(status))
  21.     {  
  22.         parentFdoExt->compositeDriverRegistered = FALSE;      
  23.     }  
  24.     IoFreeIrp(irp);  
  25.     return;  
  26. }
复制代码
在后续会报告复合装备的电源管理题目。 
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表