⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 io.c

📁 ir 驱动程序源代码,make成功了,有兴趣的朋友可以看看
💻 C
📖 第 1 页 / 共 5 页
字号:
--*/
    //
    // Just flag that we've seen it and complete the 
    //  request
    //
    DeviceData->HandshakeAccepted = TRUE;

    SmscIrTracePrint(
            TRACE_LEVEL_INFORMATION,
            SMSCDBG_IOCTL_INFO,
            ("IrHandshake: Handshake from class arrived"));

    WdfRequestComplete(Request, STATUS_SUCCESS);
    return;

}

VOID
IrReceive(
    PSMSCIR_DATA DeviceData,
    WDFREQUEST Request, 
    SIZE_T OutputBufferLength
    ) {
/*++
Routine Description.

    This request is sent exclusively from IRCLASS and receives Run Length Coded
    (RLC) IR data when the device is not running in priority mode. When running
    in priority mode, these requests remain queued but receive no data. 

    An IOCTL_IR_RECEIVE request remains pending until one of two events occurs:

    1)  The data buffer provided in the request has been completely filled 
        with RLC IR data.

    2)  An IR timeout occurs. In the case of an IR timeout, the DataEnd 
        member of the output structure is set to TRUE. 

Arguments:

    DeviceData - Our device extension

    Request    - An IOCTL_IR_RECEIVE request

    OutputBufferLength - Size of a variable length IR_RECEIVE_PARAMS structure

--*/
    NTSTATUS           status = STATUS_SUCCESS;
    KIRQL              oldIrql;
    ULONG              amountData;
    PUCHAR             callersBuffer;
    PIR_RECEIVE_PARAMS receiveParams;
    BOOLEAN            dataEnd;
    ULONG              capturedByteCount;
    PIO_STATUS_BLOCK   ioStatus;

    //
    // Make sure the user is supplying a big enough buffer...
    //
    if (OutputBufferLength < sizeof(IR_RECEIVE_PARAMS)) {

        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_RECEIVE_INFO,
            ("IrReceive: Buffer size must be at least 0x%x bytes",
                    sizeof(IR_RECEIVE_PARAMS)));

               
        WdfRequestComplete(Request, STATUS_INVALID_BUFFER_SIZE);
        return;
    }


    status = WdfRequestRetrieveOutputBuffer(Request, 
                                            OutputBufferLength,
                                            &receiveParams,
                                            NULL);

    if (!NT_SUCCESS(status)) {
        
        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_RECEIVE_INFO,
            ("IrReceive: WdfRequestRetrieveOutputBuffer failed - 0x%x", 
                    status));
           
        WdfRequestComplete(Request, status);
        return;
        
    }

    ASSERT(receiveParams);

    //
    // Because the receiveParams are mapped via MDL, the user
    //  still has the ability to modify the buffer contents
    //  from underneath us. This means that we need to capture
    //  the input values and only use the captured value from
    //  then on.
    //
    //
    // Case to ULONG is OK, max transfer size in Windows
    //  is ULONG bytes, the ULONG_PTR is only for alignment
    //  purposes.
    // 
    capturedByteCount = (ULONG)receiveParams->ByteCount;

    //
    // Make sure we check the byte count against the overall
    //  buffer length first to avoid getting tricked into 
    //  an overflow (i.e. 0xFFFFFFFF + sizeof())
    //
    if (capturedByteCount >
         (OutputBufferLength - sizeof(IR_RECEIVE_PARAMS))) {


        //
        // Tricky user...
        //
        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_RECEIVE_INFO,
            ("IrReceive: Buffer size specified in structure is too large. "\
             "Buffer Size: 0x%x - Overall buffer size: 0x%Ix", 
            capturedByteCount, OutputBufferLength));
        WdfRequestComplete(Request, STATUS_INVALID_BUFFER_SIZE);
        return;
        
    }


    //
    // Setup the caller's buffer...
    //
    callersBuffer = (PUCHAR)&receiveParams->Data[0];

    KeAcquireSpinLock(&DeviceData->Receiver.ListSpinLock, &oldIrql);
   
    // 
    // If we don't have a current IR receive, set this up 
    //  to be it...
    //
    if (DeviceData->Receiver.CurrentIrReceiveRequest == NULL) {

        //
        // If we're not in PRIORITY mode, we can see 
        //  if there is some data to process. If we are in
        //  priority mode we need to be hands off...
        //
        amountData = 0;

        if (!DeviceData->InPriorityMode) {

            //
            // Any data out there?
            //
            amountData = SmscIrDequeueRLCData(&DeviceData->Receiver, 
                                              callersBuffer, 
                                              capturedByteCount,
                                              &dataEnd);
        
            if (dataEnd || 
                (amountData == capturedByteCount)){

                //
                // Filled the user's buffer already or we copied up to 
                //  a data end event. Complete the request.
                //
                SmscIrTracePrint(
                    TRACE_LEVEL_VERBOSE,
                    SMSCDBG_RECEIVE_INFO,
                    ("IrReceive: Data was waiting. Completing request."));

                KeReleaseSpinLock(&DeviceData->Receiver.ListSpinLock, oldIrql);
            
                //
                // Get the IO_STATUS_BLOCK for the underlying IRP. This is 
                //  ehere we'll be filling in the number of bytes 
                //  transferred.
                //
                ioStatus = &WdfRequestWdmGetIrp(Request)->IoStatus;

                ioStatus->Information
                     = FIELD_OFFSET(IR_RECEIVE_PARAMS, Data) + amountData;
                
                receiveParams->DataEnd = dataEnd;
            
                WdfRequestComplete(Request, STATUS_SUCCESS);
                return;
            
            }

        }
        
        //
        // Otherwise we're out of here, we'll complete the 
        //  request when we see all of the data.
        //
        DeviceData->Receiver.CurrentIrReceiveRequest = Request;
        DeviceData->Receiver.ReceiveBuffer           = callersBuffer;
        DeviceData->Receiver.ReceiveBufferSize       = capturedByteCount;
        DeviceData->Receiver.ReceiveCurrentOffset    = amountData;
        DeviceData->Receiver.ReceiveParams           = receiveParams;

        //
        // This request is going to hang out there, and may stay
        //  there indefinitely. We need to be able to cancel this
        //  request if the user wants to disable the device, 
        //  so we need a cancel routine...
        //
        WdfRequestMarkCancelable(Request, IrReceiveInProgressCancel);

            
    } else {

        //
        // Put the request in the queue.
        //
        status = WdfRequestForwardToIoQueue(
                                     Request, 
                                     DeviceData->Receiver.PendingReceiveQueue);

        if(!NT_SUCCESS(status)) {
            
            KeReleaseSpinLock(&DeviceData->Receiver.ListSpinLock, oldIrql);
     
            SmscIrTracePrint(
                TRACE_LEVEL_ERROR,
                SMSCDBG_RECEIVE_INFO,
                ("IrReceive: WdfRequestForwardToIoQueue failed - 0x%x", 
                        status));
            
            WdfRequestComplete(Request, status);
            return;
        }

    }

    KeReleaseSpinLock(&DeviceData->Receiver.ListSpinLock, oldIrql);
    return;

}


VOID
IrReceiveInProgressCancel(
    IN WDFREQUEST  Request
    ) {
/*++
Routine Description.

    Cancel routine set for the in progress 
    receive request.

Arguments:

    Request - An IOCTL_IR_RECEIVE request

--*/
    PSMSCIR_DATA deviceData;
    WDFQUEUE     ioQueue;
    KIRQL        oldIrql;
    BOOLEAN      completeRequest;
    WDFREQUEST   failedRequest = NULL;
    NTSTATUS     status;
    NTSTATUS     failureStatus;

    ioQueue = WdfRequestGetIoQueue(Request);

    SmscIrTracePrint(
            TRACE_LEVEL_VERBOSE,
            SMSCDBG_IOCTL_INFO,
            ("IrReceiveInProgressCancel: Entered"));


    deviceData = (PSMSCIR_DATA)GetIrData(WdfIoQueueGetDevice(ioQueue));

    KeAcquireSpinLock(&deviceData->Receiver.ListSpinLock, &oldIrql);


    
    //
    // We're here first. NULL out the current request
    //  in the extension  - the completion side will 
    //  never see this request.
    //
    deviceData->Receiver.CurrentIrReceiveRequest = NULL;


    SmscIrTracePrint(
        TRACE_LEVEL_VERBOSE,
        SMSCDBG_RECEIVE_INFO,
        ("IrReceiveInProgressCancel: Request 0x%p is the currently "\
         "active receive request.",
             Request));

    //
    // Need to get the next request active.
    //
    status = IrSetupNextRequest(&deviceData->Receiver,
                                &failedRequest,
                                &failureStatus);
    if (!NT_SUCCESS(status)) {
    
        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_RECEIVE_INFO,
            ("IrReceiveInProgressCancel: IrSetupNextRequest failed - 0x%x",
                status));

    }


    KeReleaseSpinLock(&deviceData->Receiver.ListSpinLock, oldIrql);

    WdfRequestComplete(Request, STATUS_CANCELLED);
    
    if (failedRequest) {
        WdfRequestComplete(failedRequest, failureStatus);
    }

    SmscIrTracePrint(
            TRACE_LEVEL_VERBOSE,
            SMSCDBG_IOCTL_INFO,
            ("IrReceiveInProgressCancel: Exited"));


}

VOID
IrPriorityReceive(
    PSMSCIR_DATA DeviceData,
    WDFREQUEST Request, 
    SIZE_T OutputBufferLength
    ) {
/*++
Routine Description.

    This request is sent from user mode to receive RLC IR data for the 
    purpose of learning. If the device is not already in priority mode, 
    initiated by an IOCTL_ENTER_PRIORITY_RECEIVE, the request is failed 
    immediately. If in priority mode, the request will remain pending until 
    one of two events occurs:

        1)  The data buffer provided in the request has been completely 
            filled with priority IR data.

        2)  An IR timeout occurs. The length of time required for the IR 
            timeout was specified when entering priority mode.

    While in priority mode and processing IOCTL_IR_PRIORITY_RECEIVE requests, 
    IOCTL_IR_RECEIVE requests remain pending and are not filled with IR data.

Arguments:

    DeviceData         - Our device extension

    Request            - An IOCTL_IR_PRIORITY_RECEIVE request

    OutputBufferLength - Size of a variable length IR_PRIORITY_RECEIVE_PARAMS 
                         structure

--*/
    NTSTATUS                    status = STATUS_SUCCESS;
    KIRQL                       oldIrql;
    ULONG                       amountData;
    PUCHAR                      callersBuffer;
    PIR_PRIORITY_RECEIVE_PARAMS receiveParams = NULL;
    BOOLEAN                     dataEnd;
    ULONG                       capturedByteCount;
    PIO_STATUS_BLOCK            ioStatus;

    //
    // If we're not in priority mode, there's nothing to do here.
    //
    if (!DeviceData->InPriorityMode) {

        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_RECEIVE_INFO,
                ("IrPriorityReceive: Device is NOT in priority mode. "\
                 "Failing PRIORITY receive"));

        WdfRequestComplete(Request, STATUS_INVALID_DEVICE_STATE);
        return;

    }

    if (OutputBufferLength < sizeof(IR_PRIORITY_RECEIVE_PARAMS)) {
        
        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_RECEIVE_INFO,
                ("IrPriorityReceive: Buffer size must be at least 0x%x",
                sizeof(IR_PRIORITY_RECEIVE_PARAMS)));

        //
        // Work around for the current version of WDF Verifier, which
        //  checks the amount of data to be returned before setting
        //  the status in the IRP (the default status in the IRP is
        //  SUCCESS, so if we don't do this it believes we're going to
        //  copy sizeof(IR_PRIORITY_RECEIVE_PARAMS) into a user buffer
        //  that is < sizeof(IR_PRIORITY_RECEIVE_PARAMS)
        //
        WdfRequestWdmGetIrp(Request)->IoStatus.Status   
                                        = STATUS_BUFFER_TOO_SMALL;
        WdfRequestCompleteWithInformation(Request, STATUS_BUFFER_TOO_SMALL, 
                                          sizeof(IR_PRIORITY_RECEIVE_PARAMS));
        return;
    }


    status = WdfRequestRetrieveOutputBuffer(Request, 
                                            OutputBufferLength,
                                            &receiveParams,
                                            NULL);

    if (!NT_SUCCESS(status)) {
        
        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_RECEIVE_INFO,
            ("IrPriorityReceive: "\
             "WdfRequestRetrieveOutputBuffer failed - 0x%x", 
                status));
        WdfRequestComplete(Request, status);
        return;
        
    }

    //
    // See IrReceive for the reasoning behind capturedByteCount
    //
    capturedByteCount = (ULONG)receiveParams->ByteCount;
    
    //
    // Watch out for a malformed ByteCount...
    //
    if (capturedByteCount >
         (OutputBufferLength - sizeof(IR_PRIORITY_RECEIVE_PARAMS))) {

        //
        // Tricky user...
        //
        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_RECEIVE_INFO,
            ("IrPriorityReceive: Buffer size specified in structure is too "\
             "large. Buffer Size: 0x%x - Overall buffer size: 0x%Ix", 
            capturedByteCount, OutputBufferLength));
        WdfRequestComplete(Request, STATUS_INVALID_BUFFER_SIZE);
        return;
        
    }

    ASSERT(receiveParams);

    //

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -