zoukankan      html  css  js  c++  java
  • 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


  • 相关阅读:
    【crontab】误删crontab及其恢复
    New Concept English there (7)
    New Concept English there (6)
    New Concept English there (5)
    New Concept English there (4)
    New Concept English there (3)
    New Concept English there (2)Typing speed exercise
    New Concept English there (1)Typing speed exercise
    New Concept English Two 34 game over
    New Concept English Two 33 94
  • 原文地址:https://www.cnblogs.com/jhcelue/p/6891327.html
Copyright © 2011-2022 走看看