• Windows 驱动开发


        在《Windows 驱动开发 - 5》我们所说的读写操作在本篇实现。

        在WDF中实现此功能主要为:EvtIoRead和EvtIoWrite。

     

    首先,在EvtDeviceAdd设置以上两个回调事件。

    ioQueueConfig.EvtIoRead = EvtIoRead;
    ioQueueConfig.EvtIoWrite = EvtIoWrite;

    然后。在EvtDevicePrepareHardware中获取WDFUSBPIPE并測试他。

    pDeviceContext->BulkReadPipe = WdfUsbInterfaceGetConfiguredPipe(
                                                      pDeviceContext->UsbInterface,
                                                      BULK_IN_ENDPOINT_INDEX,
                                                      NULL);// pipeInfo
    
        WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(pDeviceContext->BulkReadPipe);
        
        pDeviceContext->BulkWritePipe = WdfUsbInterfaceGetConfiguredPipe(
                                                      pDeviceContext->UsbInterface,
                                                      BULK_OUT_ENDPOINT_INDEX,
                                                      NULL);// pipeInfo

    (1)获取WDFUSBPIPE

    使用WdfUsbInterfaceGetConfiguredPipe方法。

    WDFUSBPIPE WdfUsbInterfaceGetConfiguredPipe(
      [in]            WDFUSBINTERFACE           UsbInterface,
      [in]            UCHAR                     PipeIndex,
      [out, optional] PWDF_USB_PIPE_INFORMATION PipeInfo
    );

    (2) 測试WDFUSBPIPE

    使用WdfUsbTargetPipeSetNoMaximumPacketSizeCheck方法.

    VOID WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(
      [in] WDFUSBPIPE Pipe
    );


    最后,实现以上两个回调事件和他们的完毕例程。

    1. 获得传输缓存

    读:WdfRequestRetrieveOutputMemory

    NTSTATUS WdfRequestRetrieveOutputMemory(
      [in]  WDFREQUEST Request,
      [out] WDFMEMORY  *Memory
    );

    写:WdfRequestRetrieveInputMemory

    NTSTATUS WdfRequestRetrieveInputMemory(
      [in]  WDFREQUEST Request,
      [out] WDFMEMORY  *Memory
    );

    2. 格式化并发送一个请求对象到USB驱动程序堆栈

    读:WdfUsbTargetPipeFormatRequestForRead

    NTSTATUS WdfUsbTargetPipeFormatRequestForRead(
      [in]           WDFUSBPIPE        Pipe,
      [in]           WDFREQUEST        Request,
      [in, optional] WDFMEMORY         ReadMemory,
      [in, optional] PWDFMEMORY_OFFSET ReadOffset
    );

    写:WdfUsbTargetPipeFormatRequestForWrite

    NTSTATUS WdfUsbTargetPipeFormatRequestForWrite(
      [in]           WDFUSBPIPE        Pipe,
      [in]           WDFREQUEST        Request,
      [in, optional] WDFMEMORY         WriteMemory,
      [in, optional] PWDFMEMORY_OFFSET WriteOffset
    );

    3. 对请求实现一个完毕例程

    (1) 设置完毕例程

    使用WdfRequestSetCompletionRoutine方法。

    VOID WdfRequestSetCompletionRoutine(
      [in]           WDFREQUEST                         Request,
      [in, optional] PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine,
      [in, optional] WDFCONTEXT                         CompletionContext
    );
    


    (2)完毕例程

    1).检查请求状态

    status = CompletionParams->IoStatus.Status;

    2). 检查传输的字节数

    读完:

    bytesRead =  usbCompletionParams->Parameters.PipeRead.Length;

    写完:

    bytesWritten =  usbCompletionParams->Parameters.PipeWrite.Length;

    3). 检查USBD状态

    首先。赋值

    usbCompletionParams = CompletionParams->Parameters.Usb.Completion;

    最后,获取

    usbCompletionParams->UsbdStatus;


    注:

    读:EvtIoRead

    写:EvtIoWrite

    读完:EvtRequestReadCompletionRoutine

    写完:EvtRequestWriteCompletionRoutine


    附:

    step4.c

    /*++
    
    Step4: This steps shows:
           1) How to register Read and Write events on the default queue.
           2) Retrieve memory from read and write request, format the
              requests and send it to USB target.
    --*/
    
    #include "ntddk.h"
    #include "wdf.h"
    #include "prototypes.h"
    #pragma warning(disable:4200)  // suppress nameless struct/union warning
    #pragma warning(disable:4201)  // suppress nameless struct/union warning
    #pragma warning(disable:4214)  // suppress bit field types other than int warning
    #include "usbdi.h"
    #pragma warning(default:4200)
    #pragma warning(default:4201)
    #pragma warning(default:4214)
    #include "wdfusb.h"
    #include "initguid.h"
    
    DEFINE_GUID(GUID_DEVINTERFACE_OSRUSBFX2, // Generated using guidgen.exe
       0x573e8c73, 0xcb4, 0x4471, 0xa1, 0xbf, 0xfa, 0xb2, 0x6c, 0x31, 0xd3, 0x84);
    // {573E8C73-0CB4-4471-A1BF-FAB26C31D384}
    
    #define IOCTL_INDEX                     0x800
    #define FILE_DEVICE_OSRUSBFX2          0x65500
    #define USBFX2LK_SET_BARGRAPH_DISPLAY 0xD8
    #define BULK_OUT_ENDPOINT_INDEX        1
    #define BULK_IN_ENDPOINT_INDEX         2
    #define IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2,
                                                        IOCTL_INDEX + 5, 
                                                        METHOD_BUFFERED, 
                                                        FILE_WRITE_ACCESS)
    typedef struct _DEVICE_CONTEXT {
      WDFUSBDEVICE      UsbDevice;
      WDFUSBINTERFACE   UsbInterface;
      WDFUSBPIPE        BulkReadPipe;
      WDFUSBPIPE        BulkWritePipe;
    } DEVICE_CONTEXT, *PDEVICE_CONTEXT;
    
    WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_CONTEXT, GetDeviceContext)
    
    
    NTSTATUS
    DriverEntry(
        IN PDRIVER_OBJECT  DriverObject,
        IN PUNICODE_STRING RegistryPath
        )
    {
        WDF_DRIVER_CONFIG       config;
        NTSTATUS                status;
    
        KdPrint(("DriverEntry of Step4
    "));
    
        WDF_DRIVER_CONFIG_INIT(&config, EvtDeviceAdd);
    
        status = WdfDriverCreate(DriverObject,
                            RegistryPath,
                            WDF_NO_OBJECT_ATTRIBUTES, 
                            &config,     
                            WDF_NO_HANDLE 
                            );
    
        if (!NT_SUCCESS(status)) {
            KdPrint(("WdfDriverCreate failed 0x%x
    ", status));
        }
    
        return status;
    }
    
    NTSTATUS
    EvtDeviceAdd(
        IN WDFDRIVER        Driver,
        IN PWDFDEVICE_INIT  DeviceInit
        )
    {
        WDF_OBJECT_ATTRIBUTES               attributes;
        NTSTATUS                            status;
        WDFDEVICE                           device;
        PDEVICE_CONTEXT                     pDevContext;
        WDF_PNPPOWER_EVENT_CALLBACKS        pnpPowerCallbacks;
        WDF_IO_QUEUE_CONFIG                 ioQueueConfig;
        
        UNREFERENCED_PARAMETER(Driver);
    
        WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
        pnpPowerCallbacks.EvtDevicePrepareHardware = EvtDevicePrepareHardware;
        WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
    
        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);
    
        status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
        if (!NT_SUCCESS(status)) {
            KdPrint(("WdfDeviceCreate failed 0x%x
    ", status));
            return status;
        }
    
        pDevContext = GetDeviceContext(device);
    
        status = WdfDeviceCreateDeviceInterface(device,
                                    (LPGUID) &GUID_DEVINTERFACE_OSRUSBFX2,
                                    NULL);// Reference String
        if (!NT_SUCCESS(status)) {
            KdPrint(("WdfDeviceCreateDeviceInterface failed 0x%x
    ", status));
            return status;
        }
    
        WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
                                        WdfIoQueueDispatchParallel);
    
        ioQueueConfig.EvtIoDeviceControl = EvtIoDeviceControl;
        ioQueueConfig.EvtIoRead = EvtIoRead;
        ioQueueConfig.EvtIoWrite = EvtIoWrite;
    
        status = WdfIoQueueCreate(device,
                             &ioQueueConfig,
                             WDF_NO_OBJECT_ATTRIBUTES,
                             WDF_NO_HANDLE);
        if (!NT_SUCCESS(status)) {
            KdPrint(("WdfIoQueueCreate failed  %!STATUS!
    ", status));
            return status;
        }
    
        return status;
    }
    
    
    NTSTATUS
    EvtDevicePrepareHardware(
        IN WDFDEVICE    Device,
        IN WDFCMRESLIST ResourceList,
        IN WDFCMRESLIST ResourceListTranslated
        )
    {
        NTSTATUS                            status;
        PDEVICE_CONTEXT                     pDeviceContext;
        WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams;
    
        UNREFERENCED_PARAMETER(ResourceList);
        UNREFERENCED_PARAMETER(ResourceListTranslated);
    
        pDeviceContext = GetDeviceContext(Device);
    
        //
        // Create the USB device if it is not already created.
        //
        if (pDeviceContext->UsbDevice == NULL) {
    
            status = WdfUsbTargetDeviceCreate(Device,
                                        WDF_NO_OBJECT_ATTRIBUTES,
                                        &pDeviceContext->UsbDevice);
            if (!NT_SUCCESS(status)) {
                KdPrint(("WdfUsbTargetDeviceCreate failed 0x%x
    ", status));        
                return status;
            }
        }
    
        WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE(&configParams);
    
        status = WdfUsbTargetDeviceSelectConfig(pDeviceContext->UsbDevice,
                                            WDF_NO_OBJECT_ATTRIBUTES,
                                            &configParams);
        if(!NT_SUCCESS(status)) {
            KdPrint(("WdfUsbTargetDeviceSelectConfig failed 0x%x
    ", status));
            return status;
        }
    
        pDeviceContext->UsbInterface =  
                    configParams.Types.SingleInterface.ConfiguredUsbInterface;
        
        pDeviceContext->BulkReadPipe = WdfUsbInterfaceGetConfiguredPipe(
                                                      pDeviceContext->UsbInterface,
                                                      BULK_IN_ENDPOINT_INDEX,
                                                      NULL);// pipeInfo
    
        WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(pDeviceContext->BulkReadPipe);
        
        pDeviceContext->BulkWritePipe = WdfUsbInterfaceGetConfiguredPipe(
                                                      pDeviceContext->UsbInterface,
                                                      BULK_OUT_ENDPOINT_INDEX,
                                                      NULL);// pipeInfo
    
        WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(pDeviceContext->BulkWritePipe);
            
        return status;
    }
    
    VOID
    EvtIoDeviceControl(
        IN WDFQUEUE   Queue,
        IN WDFREQUEST Request,
        IN size_t     OutputBufferLength,
        IN size_t     InputBufferLength,
        IN ULONG      IoControlCode    
        )
    {
        WDFDEVICE                           device;
        PDEVICE_CONTEXT                     pDevContext;
        size_t                              bytesTransferred = 0;
        NTSTATUS                            status;
        WDF_USB_CONTROL_SETUP_PACKET        controlSetupPacket;
        WDF_MEMORY_DESCRIPTOR               memDesc;
        WDFMEMORY                           memory;
        WDF_REQUEST_SEND_OPTIONS            sendOptions;
         
        UNREFERENCED_PARAMETER(InputBufferLength);
        UNREFERENCED_PARAMETER(OutputBufferLength);
        
        device = WdfIoQueueGetDevice(Queue);
        pDevContext = GetDeviceContext(device);
    
        switch(IoControlCode) {
    
        case IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY:
    
            if(InputBufferLength < sizeof(UCHAR)) {
                status = STATUS_BUFFER_OVERFLOW;
                bytesTransferred = sizeof(UCHAR);
                break;
            } 
    
            status = WdfRequestRetrieveInputMemory(Request, &memory);
            if (!NT_SUCCESS(status)) {
                KdPrint(("WdfRequestRetrieveMemory failed 0x%x", status));
                break;
            }
    
            WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket,
                                            BmRequestHostToDevice,
                                            BmRequestToDevice,
                                            USBFX2LK_SET_BARGRAPH_DISPLAY, // Request
                                            0, // Value
                                            0); // Index                                                        
    
            WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&memDesc, memory, NULL);
    
           //
           // Send the I/O with a timeout to avoid hanging the calling 
           // thread indefinitely.
           //
            WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions,
                                      WDF_REQUEST_SEND_OPTION_TIMEOUT);
    
            WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions,
                                             WDF_REL_TIMEOUT_IN_MS(100));
        
            status = WdfUsbTargetDeviceSendControlTransferSynchronously(
                                            pDevContext->UsbDevice, 
                                            NULL, // Optional WDFREQUEST
                                            &sendOptions, // PWDF_REQUEST_SEND_OPTIONS
                                            &controlSetupPacket,
                                            &memDesc,
                                            (PULONG)&bytesTransferred);
            if (!NT_SUCCESS(status)) {
                KdPrint(("SendControlTransfer failed 0x%x", status));
                break;
            }
            break;
    
        default:
            status = STATUS_INVALID_DEVICE_REQUEST;
            break;
        }
    
        WdfRequestCompleteWithInformation(Request, status, bytesTransferred);
    
        return;
    }
    
    VOID 
    EvtIoRead(
        IN WDFQUEUE         Queue,
        IN WDFREQUEST       Request,
        IN size_t           Length
        )   
    {
        WDFUSBPIPE                  pipe;
        NTSTATUS                    status;
        WDFMEMORY                   reqMemory;
        PDEVICE_CONTEXT             pDeviceContext;
        BOOLEAN                     ret;
        
        UNREFERENCED_PARAMETER(Length);
    
        pDeviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));
        
        pipe = pDeviceContext->BulkReadPipe;
        
        status = WdfRequestRetrieveOutputMemory(Request, &reqMemory);
        if(!NT_SUCCESS(status)){
            goto Exit;
        }
       
        status = WdfUsbTargetPipeFormatRequestForRead(pipe,
                                            Request,
                                            reqMemory,
                                            NULL // Offsets
                                            ); 
        if (!NT_SUCCESS(status)) {
            goto Exit;
        }
    
        WdfRequestSetCompletionRoutine(Request,
                                EvtRequestReadCompletionRoutine,
                                pipe);
        ret = WdfRequestSend(Request, 
                        WdfUsbTargetPipeGetIoTarget(pipe), 
                        WDF_NO_SEND_OPTIONS);
        
        if (ret == FALSE) {
            status = WdfRequestGetStatus(Request);
            goto Exit;
        } else {
            return;
        }
       
    Exit:
        WdfRequestCompleteWithInformation(Request, status, 0);
    
        return;
    }
    
    VOID
    EvtRequestReadCompletionRoutine(
        IN WDFREQUEST                  Request,
        IN WDFIOTARGET                 Target,
        PWDF_REQUEST_COMPLETION_PARAMS CompletionParams,
        IN WDFCONTEXT                  Context
        )
    {    
        NTSTATUS    status;
        size_t      bytesRead = 0;
        PWDF_USB_REQUEST_COMPLETION_PARAMS usbCompletionParams;
    
        UNREFERENCED_PARAMETER(Target);
        UNREFERENCED_PARAMETER(Context);
    
        status = CompletionParams->IoStatus.Status;
        
        usbCompletionParams = CompletionParams->Parameters.Usb.Completion;
        
        bytesRead =  usbCompletionParams->Parameters.PipeRead.Length;
        
        if (NT_SUCCESS(status)){
            KdPrint(("Number of bytes read: %I64d
    ", (INT64)bytesRead));  
        } else {
            KdPrint(("Read failed - request status 0x%x UsbdStatus 0x%x
    ",
                    status, usbCompletionParams->UsbdStatus));
    
        }
    
        WdfRequestCompleteWithInformation(Request, status, bytesRead);
    
        return;
    }
    
    VOID 
    EvtIoWrite(
        IN WDFQUEUE         Queue,
        IN WDFREQUEST       Request,
        IN size_t           Length
        )   
    {
        NTSTATUS                    status;
        WDFUSBPIPE                  pipe;
        WDFMEMORY                   reqMemory;
        PDEVICE_CONTEXT             pDeviceContext;
        BOOLEAN                     ret;
        
        UNREFERENCED_PARAMETER(Length);
    
        pDeviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));
        
        pipe = pDeviceContext->BulkWritePipe;
    
        status = WdfRequestRetrieveInputMemory(Request, &reqMemory);
        if(!NT_SUCCESS(status)){
            goto Exit;
        }
    
        status = WdfUsbTargetPipeFormatRequestForWrite(pipe,
                                                  Request,
                                                  reqMemory,
                                                  NULL); // Offset
        if (!NT_SUCCESS(status)) {
            goto Exit;
        }
    
        WdfRequestSetCompletionRoutine(
                                Request,
                                EvtRequestWriteCompletionRoutine,
                                pipe);
        ret = WdfRequestSend(Request, 
                        WdfUsbTargetPipeGetIoTarget(pipe), 
                        WDF_NO_SEND_OPTIONS);
        if (ret == FALSE) {
            status = WdfRequestGetStatus(Request);
            goto Exit;
        } else {
            return;
        }
    
    Exit:    
        WdfRequestCompleteWithInformation(Request, status, 0);
    
        return;
    }
    
    VOID
    EvtRequestWriteCompletionRoutine(
        IN WDFREQUEST                  Request,
        IN WDFIOTARGET                 Target,
        PWDF_REQUEST_COMPLETION_PARAMS CompletionParams,
        IN WDFCONTEXT                  Context
        )
    {
        NTSTATUS    status;
        size_t      bytesWritten = 0;
        PWDF_USB_REQUEST_COMPLETION_PARAMS usbCompletionParams;
    
        UNREFERENCED_PARAMETER(Target);
        UNREFERENCED_PARAMETER(Context);
    
        status = CompletionParams->IoStatus.Status;
    
        usbCompletionParams = CompletionParams->Parameters.Usb.Completion;
        
        bytesWritten =  usbCompletionParams->Parameters.PipeWrite.Length;
        
        if (NT_SUCCESS(status)){
            KdPrint(("Number of bytes written: %I64d
    ", (INT64)bytesWritten));        
        } else {
            KdPrint(("Write failed: request Status 0x%x UsbdStatus 0x%x
    ", 
                    status, usbCompletionParams->UsbdStatus));
        }
    
        WdfRequestCompleteWithInformation(Request, status, bytesWritten);
    
        return;
    }



    參考文章:

        1. 《Working with USB Pipes》 

        2. 《How to send USB bulk transfer requests


  • 相关阅读:
    Python 的并发编程
    django搭建一个小型的服务器运维网站-拿来即用的bootstrap模板
    python 文件目录遍历
    Ubuntu 18.04 登陆界面进去,几秒之后自动退出到登陆界面
    terminal 快捷操作
    Boost 源代码交叉编译
    tar 常见操作
    vim 快捷设置和操作
    Visual Studio Linker选项设置
    5. glutInitDisplayMode 函数理解
  • 原文地址:https://www.cnblogs.com/jhcelue/p/6891327.html
Copyright © 2020-2023  润新知