📄 urb.txt
字号:
初始化请求
为了创建一个URB,你首先应该为URB分配内存,然后调用初始化例程把URB结构中的各个域填入请求要求的内容.
USB_DEVICE_DESCRIPTOR dd;
URB urb;
UsbBuildGetDescriptorRequest(&urb,//创建URB
sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST),
USB_DEVICE_DESCRIPTOR_TYPE,
0,
0,
&dd,
NULL,
sizeof(dd),
NULL);
当然,你还可以在系统堆上为URB动态地分配内存:
PURB urb = (PURB) ExAllocatePool(NonPagedPool, sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST));
if (!urb)
return STATUS_INSUFFICIENT_RESOURCES;
UsbBuildGetDescriptorRequest(urb, ...);//创建URB
...
ExFreePool(urb);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
发送URB
创建完URB后,你需要创建并发送一个内部I/O控制(IOCTL)请求到USBD驱动程序,USBD驱动程序位于驱动程序层次结构的低端。在大多数情况下,你需要等待设备回应,可以使用下面辅助函数:
NTSTATUS SendAwaitUrb(PDEVICE_OBJECT fdo, PURB urb)
{
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
KEVENT event; <--1
KeInitializeEvent(&event, NotificationEvent, FALSE);
IO_STATUS_BLOCK iostatus;
PIRP Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB, <--2
pdx->LowerDeviceObject,
NULL,
0,
NULL,
0,
TRUE,
&event,
&iostatus);
PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(Irp); <--3
stack->Parameters.Others.Argument1 = (PVOID) urb;
NTSTATUS status = IoCallDriver(pdx->LowerDeviceObject, Irp); <--4
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = iostatus.Status;
}
return status;
}
1、我们将等待URB完成,所以我们必须先创建一个内核事件对象。这与我在第六章"即插即用"中使用的辅助函数
ForwardAndWait类似。
2、创建内部IOCTL请求最简单的的方法是调用IoBuildDeviceIoControlRequest函数,第一个参数(IOCTL_INTERN
AL_USB_SUBMIT_URB)指出I/O控制代码。第二个参数(pdx->LowerDeviceObject)指定接收请求的设备对象;
3、IoBuildDeviceIoControlRequest使用这个指针来决定需要接收多少个堆栈单元。接下来的四个参数描述输入
输出缓冲区,提交这种URB并不需要这些信息,所以例子中将它们置成NULL或0值。第七个参数为TRUE,它指出我
们创建的是IRP_MJ_INTERNAL_DEVICE_CONTROL请求而不是IRP_MJ_DEVICE_CONTROL请求。最后两个参数指出等待
URB完成的事件和一个接收该操作最终状态的结构IO_STATUS_BLOCK。
4、被提交的URB的地址被填入Parameters.Others的Argument1域。对于普通的IOCTL请求,该偏移对应OutputBu
fferLength域。
5、我们用IoCallDriver把请求发送到下一层驱动程序。USBD将处理该URB请求并完成,然后I/O管理器将那个
IRP删除并置事件信号。由于我们没有提供自己的完成例程,所以不能确定I/O管理器在所有可能的完成情况下
都置事件信号。我们仅当低级派遣例程返回STATUS_PENDING时才等待那个事件。
………………………………………………………………………………………………………………………………
URB返回的状态
NTSTATUS status = SendAwaitUrb(fdo, &urb);
USBD_STATUS ustatus = URB_STATUS(&urb);
…………………………………………………………………………………………………………………………………
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -