马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
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 句柄存储在驱动步调的装备上下文中。- VOID RegisterCompositeDriver(PPARENT_FDO_EXT parentFdoExt)
- {
- PIRP irp;
- REGISTER_COMPOSITE_DRIVER registerInfo;
- COMPOSITE_DRIVER_CAPABILITIES capabilities;
- NTSTATUS status;
- PVOID buffer;
- ULONG bufSize;
- PIO_STACK_LOCATION nextSp;
- buffer = NULL;
- COMPOSITE_DRIVER_CAPABILITIES_INIT(&capabilities);
- capabilities.CapabilityFunctionSuspend = 1;
- USBD_BuildRegisterCompositeDriver(parentFdoExt->usbdHandle,
- capabilities,
- parentFdoExt->numFunctions,
- ®isterInfo);
- irp = IoAllocateIrp(parentFdoExt->topDevObj->StackSize, FALSE);
- if (irp == NULL)
- {
- //IoAllocateIrp failed.
- status = STATUS_INSUFFICIENT_RESOURCES;
- goto ExitRegisterCompositeDriver;
- }
- nextSp = IoGetNextIrpStackLocation(irp);
- bufSize = parentFdoExt->numFunctions * sizeof(USBD_FUNCTION_HANDLE);
- buffer = ExAllocatePoolWithTag (NonPagedPool, bufSize, POOL_TAG);
- if (buffer == NULL)
- {
- // Memory alloc for function-handles failed.
- status = STATUS_INSUFFICIENT_RESOURCES;
- goto ExitRegisterCompositeDriver;
- }
- nextSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
- nextSp->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_REGISTER_COMPOSITE_DRIVER;
- //Set the input buffer in Argument1
- nextSp->Parameters.Others.Argument1 = ®isterInfo;
- //Set the output buffer in SystemBuffer field for USBD_FUNCTION_HANDLE.
- irp->AssociatedIrp.SystemBuffer = buffer;
- // Pass the IRP down to the next device object in the stack. Not shown.
- status = CallNextDriverSync(parentFdoExt, irp, FALSE);
- if (!NT_SUCCESS(status))
- {
- //Failed to register the composite driver.
- goto ExitRegisterCompositeDriver;
- }
- parentFdoExt->compositeDriverRegistered = TRUE;
- parentFdoExt->functionHandleArray = (PUSBD_FUNCTION_HANDLE) buffer;
- End:
- if (!NT_SUCCESS(status))
- {
- if (buffer != NULL)
- {
- ExFreePoolWithTag (buffer, POOL_TAG);
- buffer = NULL;
- }
- }
- if (irp != NULL)
- {
- IoFreeIrp(irp);
- irp = NULL;
- }
- return;
- }
复制代码 取消注册复合装备
- 通过调用 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 驱动步调堆栈与复合驱动步调及其罗列函数之间的关联。 该哀求还会整理为维护该关联而创建的全部资源,以及上一个注册哀求中返回的全部函数句柄。
下面的代码示例演示怎样天生并发送取消注册复合装备的哀求。 该示例假定复合驱动步调从前是通过注册哀求注册的,如本主题前面所述。- VOID UnregisterCompositeDriver(
- PPARENT_FDO_EXT parentFdoExt )
- {
- PIRP irp;
- PIO_STACK_LOCATION nextSp;
- NTSTATUS status;
- PAGED_CODE();
- irp = IoAllocateIrp(parentFdoExt->topDevObj->StackSize, FALSE);
- if (irp == NULL)
- {
- //IoAllocateIrp failed.
- status = STATUS_INSUFFICIENT_RESOURCES;
- return;
- }
- nextSp = IoGetNextIrpStackLocation(irp);
- nextSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
- nextSp->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_UNREGISTER_COMPOSITE_DRIVER;
- // Pass the IRP down to the next device object in the stack. Not shown.
- status = CallNextDriverSync(parentFdoExt, irp, FALSE);
- if (NT_SUCCESS(status))
- {
- parentFdoExt->compositeDriverRegistered = FALSE;
- }
- IoFreeIrp(irp);
- return;
- }
复制代码 在后续会报告复合装备的电源管理题目。
|