Windows驱动资源的使用一

来源:互联网 发布:传统武术知乎 编辑:程序博客网 时间:2024/05/22 21:04
                   今天买了飞机票,好贵啊!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.