Windows驱动资源的使用一

                   今天买了飞机票,好贵啊!2400又没了!没办法!该用的钱还是得用! 难过

              上次讲到了,Windows驱动中的资源,今天着重讲一下,Windows资源,如何使用。关于中断,内存,IO这些,以后再讲。今天重点讲一下,总线驱动的引用。我们知道,在设备驱动中,经常会使用I2C,GPIO这些资源,但是我们如何进行操作了,当然,我们可以直接进行IO映射。直接I2C,GPIO地址进行操作,但是这种方式不安全,且MSFT不推荐。所以,MSFT在后来的CM_PARTIAL_RESOURCE_DESCRIPTOR结构体中,加上了如下结构体:

95.        struct { 
96.                  UCHAR Class; 
97.                  UCHAR Type; 
98.                  UCHAR Reserved1; 
99.                  UCHAR Reserved2; 
100.               ULONG IdLowPart; 
101.               ULONG IdHighPart; 
102.              } Connection;

              我们通过这个结构体,可以得到一个对我们配置资源总线的一个引用。即通过这个域,我们可以把它组成了一ID,通过这个ID,就可以和我们设备驱动底层的GPIO,I2C这些驱动进行通讯。

              下面贴出MSDN中的一个实例。

             

NTSTATUS
  EvtDevicePrepareHardware(
    _In_ WDFDEVICE Device,
    _In_ WDFCMRESLIST ResourcesRaw,
    _In_ WDFCMRESLIST ResourcesTranslated
    )
{
    int ResourceCount, Index;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
    XYZ_DEVICE_CONTEXT *DeviceExtension;

    ...

    DeviceExtension = XyzDrvGetDeviceExtension(Device);
    ResourceCount = WdfCmResourceListGetCount(ResourcesTranslated);
    for (Index = 0; Index < ResourceCount; Index += 1) {
        Descriptor = WdfCmResourceListGetDescriptor(ResourcesTranslated, Index);
        switch (Descriptor->Type) {

        //
        // GPIO I/O descriptors
        //

        case CmResourceTypeConnection:

            //
            // Check against expected connection type.
            //

            if ((Descriptor->u.Connection.Class == CM_RESOURCE_CONNECTION_CLASS_GPIO) &&
                (Descriptor->u.Connection.Type == CM_RESOURCE_CONNECTION_TYPE_GPIO_IO)) {

                DeviceExtension->ConnectionId.LowPart = Descriptor->u.Connection.IdLowPart;
                DeviceExtension->ConnectionId.HighPart = Descriptor->u.Connection.IdHighPart;

        ...

}


我们得到这个描述符。就可以进行和目标IO进行通讯了,继续看:

NTSTATUS IoRoutine(WDFDEVICE Device) 
{
    XYZ_DEVICE_CONTEXT *DeviceExtension;
    UNICODE_STRING ReadString;
    WCHAR ReadStringBuffer[100];
    WDF_OBJECT_ATTRIBUTES ObjectAttributes;
    WDF_IO_TARGET_OPEN_PARAMS OpenParams;
    WDFIOTARGET IoTarget;
    BOOL DesiredAccess;
    NTSTATUS Status;

    DeviceExtension = XyzDrvGetDeviceExtension(Device);
    RtlInitEmptyUnicodeString(&ReadString,
                              ReadStringBuffer,
                              sizeof(ReadStringBuffer));

    Status = RESOURCE_HUB_CREATE_PATH_FROM_ID(&ReadString,
                                              DeviceExtension->ConnectionId.LowPart,
                                              DeviceExtension->ConnectionId.HighPart);

    NT_ASSERT(NT_SUCCESS(Status));

    WDF_OBJECT_ATTRIBUTES_INIT(&ObjectAttributes);
    ObjectAttributes.ParentObject = Device;

    Status = WdfIoTargetCreate(Device, &ObjectAttributes, &IoTarget);
    if (!NT_SUCCESS(Status)) {
        goto IoErrorEnd;
    }   

    if (ReadOperation != FALSE) {
        DesiredAccess = FILE_GENERIC_READ;
    } else {
        DesiredAccess = FILE_GENERIC_WRITE;
    }

    WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME(&OpenParams, ReadString, DesiredAccess);

    Status = WdfIoTargetOpen(IoTarget, &OpenParams);
    if (!NT_SUCCESS(Status)) {
        goto IoErrorEnd;
    }
    ...


再看实际的GPIO读写状态:

WDF_OBJECT_ATTRIBUTES RequestAttributes;
    WDF_OBJECT_ATTRIBUTES Attributes;
    WDF_REQUEST_SEND_OPTIONS SendOptions;
    WDFREQUEST IoctlRequest;
    WDFIOTARGET IoTarget;
    WDFMEMORY WdfMemory;
    NTSTATUS Status;

    WDF_OBJECT_ATTRIBUTES_INIT(&RequestAttributes);
    Status = WdfRequestCreate(&RequestAttributes, IoTarget, &IoctlRequest);
    if (!NT_SUCCESS(Status)) {
        goto RwErrorExit;
    }

    //
    // Set up a WDF memory object for the IOCTL request.
    //

    WDF_OBJECT_ATTRIBUTES_INIT(&Attributes);
    Attributes.ParentObject = IoctlRequest;
    Status = WdfMemoryCreatePreallocated(&Attributes, Data, Size, &WdfMemory);
    if (!NT_SUCCESS(Status)) {
        goto RwErrorExit;
    }

    //
    // Format the request.
    //

    if (ReadOperation != FALSE) {
        Status = WdfIoTargetFormatRequestForIoctl(IoTarget,
                                                  IoctlRequest,
                                                  IOCTL_GPIO_READ_PINS,
                                                  NULL,
                                                  0,
                                                  WdfMemory,
                                                  0);

    } else {
        Status = WdfIoTargetFormatRequestForIoctl(IoTarget,
                                                  IoctlRequest,
                                                  IOCTL_GPIO_WRITE_PINS,
                                                  WdfMemory,
                                                  0,
                                                  WdfMemory,
                                                  0);
    }

    if (!NT_SUCCESS(Status)) {
        goto RwErrorExit;
    }

    //
    // Send the request synchronously (with a 60-second time-out).
    //

    WDF_REQUEST_SEND_OPTIONS_INIT(&SendOptions,
                                  WDF_REQUEST_SEND_OPTION_SYNCHRONOUS);
    WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&SendOptions,
                                         WDF_REL_TIMEOUT_IN_SEC(60));

    Status = WdfRequestAllocateTimer(IoctlRequest);
    if (!NT_SUCCESS(Status)) {
        goto RwErrorExit;
    }

    if (!WdfRequestSend(IoctlRequest, IoTarget, &SendOptions)) {
        Status = WdfRequestGetStatus(IoctlRequest);
    }

    ...


       我们再来看下Connection的MSDN的说明:

      先看Class:

     CM_RESOURCE_CONNECTION_CLASS_GPIO或者CM_RESOURCE_CONNECTION_CLASS_SERIAL

     再看Type:

    CM_RESOURCE_CONNECTION_TYPE_GPIO_IO或者CM_RESOURCE_CONNECTION_TYPE_SERIAL_I2C,CM_RESOURCE_CONNECTION_TYPE_SERIAL_SPI,CM_RESOURCE_CONNECTION_TYPE_SERIAL_UART

    IdLowPart:64位连接ID的低32位。

    IdHighPart:64位连接ID的高32位。

    我们可以举一反三,在I2C, SPI中都可以这样用,当然,有使用,MSFT为我们封装了后序的IOCTL的操作,比如,直接提供I2CReadRegister,或者I2CWriteRegister.

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,以下是Windows系统的启动步骤: 1. 开机自检(POST):当计算机启动时,它会进行一些自我检测和初始化,以确保硬件设备正常运行。这个过程被称为“开机自检”或“POST”。 2. BIOS检查:在完成开机自检后,计算机会进入BIOS(Basic Input/Output System)检查。BIOS是一个固化在计算机主板上的程序,它检查并初始化计算机的硬件设备,例如硬盘、内存、键盘、鼠标等。如果BIOS检查发现有问题,它会发出警报声并显示错误消息。 3. 启动加载程序:在BIOS检查完成后,计算机会查找并加载启动加载程序(Boot Loader),通常是操作系统的一部分。启动加载程序负责加载操作系统内核,并将其装入内存。 4. 加载操作系统内核:一旦启动加载程序被加载到内存中,它会加载操作系统内核。内核是操作系统的核心部分,负责管理计算机的硬件和软件资源。加载内核后,操作系统就开始运行了。 5. 初始化操作系统:在操作系统启动后,它会进行一些初始化,包括加载设备驱动程序、启动服务等。 6. 用户登录:当操作系统初始化完成后,用户可以输入用户名和密码登录系统,进入桌面界面。 ### 回答2: 编写一个Windows驱动需要具备一定的知识和技能。以下是一个简单的示例: 首先,我们需要一台运行Windows操作系统的计算机和安装有Visual Studio的开发环境。 1. 打开Visual Studio并创建一个新的项目。 2. 在项目模板中选择“驱动程序”。 3. 选择适合你的需求的驱动类型,比如显示器驱动、打印机驱动等。 4. 编写驱动的代码。这涉及到使用C或C++语言和Windows驱动开发框架(Windows Driver Kit,简称WDK)的特定API。 5. 定义驱动所需的函数、数据结构和相关操作。 6. 实现驱动中所需的功能,如设备注册、初始化和关闭等。 7. 编译驱动代码以生成驱动程序文件(.sys)。 8. 安装驱动程序。这可以通过使用Windows的设备管理器或使用命令行工具(如DevCon)来完成。 9. 测试驱动程序,确保它能够与相关硬件设备正确通信并执行所需的功能。 在编写驱动程序时,要特别小心避免错误和安全漏洞。驱动程序运行在内核模式下,因此任何编码错误都可能导致系统的不稳定性甚至崩溃。 总结起来,编写Windows驱动程序需要专业的开发工具和知识,以及对驱动开发的理解和实践经验。这只是一个简要的概述,实际编写一个Windows驱动需要更详细的步骤和深入的了解。 ### 回答3: 编写一个Windows驱动是一项相对复杂且需要深入了解系统内核和驱动相关知识的任务。由于篇幅限制,我不能详细描述整个过程,但我可以给出简要的概述。 首先,编写Windows驱动的工具通常是微软提供的Windows驱动开发工具包(Windows Driver Kit,简称WDK)。WDK包含了与Windows内核交互的API、库、示例代码等工具,供开发者使用。 接下来,计划和设计你的驱动。你需要明确你的驱动的功能和目的,并决定你的驱动是一个内核驱动(Kernel Mode Driver)还是一个用户模式驱动(User Mode Driver)。 在编写代码之前,你需要了解驱动程序的基本结构和组成。显然,不同类型的驱动会有不同的结构。内核驱动需要实现驱动对象(Driver Object)、设备对象(Device Object)和IRP(I/O Request Packet)处理程序。用户模式驱动则需要实现驱动入口点和相应的功能逻辑。 然后,根据你的计划开始编写代码。你可以使用C或C++编程语言进行开发。在这一阶段,你可以使用WDK提供的示例代码作为起点,进行修改和扩展以满足你的需求。 完成代码编写后,你需要将代码编译为驱动程序。WDK提供了相关的编译工具和命令。 最后,你需要将编译得到的驱动程序安装到目标系统上。这可以通过设备管理器或命令行工具(如devcon)来完成。 需要强调的是,编写Windows驱动是一项技术上的挑战,需要深入了解相关知识,并在实践中获得经验。这里只给出了一个粗略的概述,实际开发过程中还有很多细节需要考虑和处理。如果你有具体的驱动需求,建议你参考相关的文档和教程进行详细学习和实践。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值