本节具体介绍如何进行 USB 驱动的开发,本节采用的源码来源自 DDK 的源程序,其位置在 DDK 子目录的 src\wdm\usb\bulkusb 目录下。该示例很全面地支持了即插即用 IRP的处理,也很全面地支持了电源管理,同时很好地支持了 USB 设备的 bulk 读写。如果从头开发 USB 驱动,往往很难达到 USB 驱动的稳定性,所以强烈建议读者在此驱动修改的基础上进行 USB 驱动开发。
### USB驱动开发和实例
#### 一、USB驱动开发概览
USB (Universal Serial Bus) 驱动的开发是一项复杂但重要的任务,特别是在嵌入式系统和操作系统领域。本篇文档详细介绍如何进行USB驱动的开发,特别是基于DDK (Driver Development Kit) 源代码的开发方法。本文档中的例子来源于DDK的源程序,具体位于`src\wdm\usb\bulkusb`目录下。该示例涵盖了几个关键特性,包括即插即用(IRP)的处理、电源管理和USB设备的bulk读写。
#### 二、USB驱动架构
**1. 功能驱动与物理总线驱动**
DDK 提供了一个强大的USB物理总线驱动(PDO),而开发人员的主要工作是实现功能驱动(FDO)。功能驱动负责处理特定的逻辑,比如处理设备的读写请求,而不需要关心USB协议的具体细节。当功能驱动需要向USB设备发起读写请求时,它会构建一个URB (USB Request Block) 并将其发送给USB总线驱动,后者会解析URB并进一步将请求转发给USB主机控制器或USB集线器。
#### 三、构造USB请求包
构造USB请求包是USB驱动开发中的一个重要环节。所有的USB通信都通过创建URB来完成。URB包含了关于USB请求的所有必要信息,例如请求类型、数据长度、缓冲区地址等。通过使用DDK提供的内核函数 `UsbBuildGetDescriptorRequest` 可以轻松构造URB。
**函数原型**:
```c
VOID UsbBuildGetDescriptorRequest(
IN OUT PURB Urb,
IN USHORT Length,
IN UCHAR DescriptorType,
IN UCHAR Index,
IN USHORT LanguageId,
IN PVOID TransferBuffer OPTIONAL,
IN PMDL TransferBufferMDL OPTIONAL,
IN ULONG TransferBufferLength,
IN PURB Link OPTIONAL
);
```
**参数说明**:
- **Urb**: URB结构的指针。
- **Length**: URB结构的大小。
- **DescriptorType**: 描述符类型。
- **Index**: 设备描述符的索引。
- **LanguageId**: 语言ID。
- **TransferBuffer**: 缓冲区指针。
- **TransferBufferMDL**: MDL指针。
- **TransferBufferLength**: 内存大小。
- **Link**: 链接URB的指针。
**示例**:
```c
UsbBuildGetDescriptorRequest(
urb,
(USHORT)sizeof(struct_URB_CONTROL_DESCRIPTOR_REQUEST),
USB_DEVICE_DESCRIPTOR_TYPE,
0,
0,
deviceDescriptor,
NULL,
siz,
NULL
);
```
#### 四、发送USB请求包
一旦URB构造完成,接下来需要将其发送给底层总线驱动。这通常通过创建一个包含URB的IRP (I/O Request Packet) 来实现。可以使用 `IoBuildDeviceIoControlRequest` 创建IRP,并通过 `IoCallDriver` 发送。
**示例代码**:
```c
NTSTATUS status;
PIRP irp = IoBuildDeviceIoControlRequest(
IOCTL_USB_GET_DESCRIPTOR, // 控制码
PhysicalDeviceObject, // 物理设备对象
NULL, // 输入缓冲区
0, // 输入缓冲区大小
urb, // 输出缓冲区 (URB)
sizeof(struct_URB_CONTROL_DESCRIPTOR_REQUEST), // 输出缓冲区大小
TRUE, // 同步调用
&asyncContext, // 异步上下文
&irp
);
if (irp) {
status = IoCallDriver(PhysicalDeviceObject, irp);
}
```
在这个示例中,`IOCTL_USB_GET_DESCRIPTOR` 是用于获取USB描述符的控制码,`PhysicalDeviceObject` 是物理设备对象,`urb` 是之前构造的URB。
#### 五、总结
本文档详细介绍了USB驱动开发的基本流程和技术要点,包括功能驱动与物理总线驱动的区别、URB的构造及发送方法。对于初学者来说,这些知识点是非常宝贵的资源,可以指导他们快速入门USB驱动的开发过程。同时,强烈推荐开发者们在现有稳定的基础上进行修改和扩展,而不是从零开始开发,这样可以大大提升驱动的稳定性和效率。
- 1
- 2
前往页