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

📄 io.c

📁 ir 驱动程序源代码,make成功了,有兴趣的朋友可以看看
💻 C
📖 第 1 页 / 共 5 页
字号:
    // Setup the caller's buffer...
    //
    callersBuffer = (PUCHAR)&receiveParams->Data[0];

    KeAcquireSpinLock(&DeviceData->PriorityReceiver.ListSpinLock, &oldIrql);

    // 
    // If we don't have a current PRIORITY IR receive, set this up 
    //  to be it...
    //
    if (DeviceData->PriorityReceiver.CurrentIrReceiveRequest == NULL) {

        //
        // Any data out there?
        //
        amountData = SmscIrDequeueRLCData(&DeviceData->PriorityReceiver, 
                                          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,
                ("IrPriorityReceive: Data was waiting. Completing request."));

            KeReleaseSpinLock(&DeviceData->PriorityReceiver.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_PRIORITY_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->PriorityReceiver.CurrentIrReceiveRequest = Request;
        DeviceData->PriorityReceiver.ReceiveBuffer         = callersBuffer;
        DeviceData->PriorityReceiver.ReceiveBufferSize     = capturedByteCount;
        DeviceData->PriorityReceiver.ReceiveCurrentOffset  = amountData;
        DeviceData->PriorityReceiver.PriorityReceiveParams = 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, IrPriorityReceiveInProgressCancel);
            
    } else {

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

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

    }

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

}




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

    Cancel routine set for the in progress 
    PRIORITY receive request.

Arguments:

    Request - An IOCTL_IR_PRIORITY_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->PriorityReceiver.ListSpinLock, &oldIrql);


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


    SmscIrTracePrint(
        TRACE_LEVEL_VERBOSE,
        SMSCDBG_RECEIVE_INFO,
        ("IrPriorityReceiveInProgressCancel: Priority Request 0x%p is "\
        "the currently active receive request.", 
        Request));
    
    //
    // Need to get the next request active.
    //
    status = IrSetupNextRequest(&deviceData->PriorityReceiver,
                                &failedRequest,
                                &failureStatus);
    if (!NT_SUCCESS(status)) {
    
        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_RECEIVE_INFO,
            ("IrPriorityReceiveInProgressCancel: IrSetupNextRequest "\
             "failed - 0x%x", status));

    }

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

    WdfRequestComplete(Request, STATUS_CANCELLED);

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

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



}


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

    Transmits the given IR stream on the given port(s) at the given 
    carrier frequency.
    
    On legacy devices, this maintains the pre-existing carrier 
    frequency, port masks, and sample period values.  (ie. it gets the old 
    values, changes them, transmits, and then changes them back)

    This IOCTL is synchronous.  It does not return until the IR has actually 
    been transmitted.

Arguments:

    DeviceData - Our device extension

    Request    - An IOCTL_IR_TRANSMIT request

    OutputBufferLength - Size of a variable length IR_TRANSMIT_CHUNK structure

    InputBufferLength  - Size of an IR_TRANSMIT_PARAMS structure

--*/    

    NTSTATUS                    status = STATUS_SUCCESS;
    KIRQL                       oldIrql;
    PIR_TRANSMIT_PARAMS         transmitParams;
    PIR_TRANSMIT_CHUNK          transmitChunk;
    ULONG_PTR                   transmitMaxAddress;
    ULONG                       frequencyKHz;
    ULONG                       carrierDivider = 0;
    ULONG                       capturedCarrierPeriod;
    ULONG                       capturedRepeatCount;
    ULONG_PTR                   capturedNextOffset;
    ULONG                       capturedByteCount;
    UCHAR                       capturedTxPorts;
    BIRCC2_TX_CHANNEL_ENABLES   txEnables;
    BIRCC2_LINE_CONTROL         lineControl;
    BIRCC2_MASTER_BLOCK_CONTROL mbc;
    PSMSCIR_TX_FIFO_DATA        txFifoData = NULL;
    WDFREQUEST                  requestToComplete;
    NTSTATUS                    requestStatus;


    UNREFERENCED_PARAMETER(InputBufferLength);

    if (OutputBufferLength < sizeof(IR_TRANSMIT_CHUNK)) {

        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_TRANSMIT_INFO,
            ("IrTransmit: Output buffer too small, must be at least "\
             "0x%x bytes", sizeof(IR_TRANSMIT_CHUNK)));
        WdfRequestWdmGetIrp(Request)->IoStatus.Status 
                                        = STATUS_BUFFER_TOO_SMALL;
        WdfRequestCompleteWithInformation(Request, STATUS_BUFFER_TOO_SMALL,
                                          sizeof(IR_TRANSMIT_CHUNK));
        return;

    }

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

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


    //
    // The data structure contains byte counts and offsets.
    //  Calculate the largest possible address that we can 
    //  use when walking this data structure to ensure
    //  we don't walk all over memory we don't have access
    //  too 
    //
    transmitMaxAddress = ((ULONG_PTR)transmitChunk + OutputBufferLength);


    status = WdfRequestRetrieveInputBuffer(Request, 
                                           sizeof(IR_TRANSMIT_PARAMS),
                                           &transmitParams,
                                           NULL);

    if (!NT_SUCCESS(status)) {
        
        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_TRANSMIT_INFO,
            ("IrTransmit: WdfRequestRetrieveInputBuffer failed - 0x%x", 
                status));
        WdfRequestComplete(Request, status);
        return;
        
    }


    capturedCarrierPeriod = (ULONG)transmitParams->CarrierPeriod;
    if (capturedCarrierPeriod == 0) {

        if (transmitParams->Flags & TRANSMIT_FLAGS_DC_MODE) {
        
            SmscIrTracePrint(
                TRACE_LEVEL_ERROR,
                SMSCDBG_TRANSMIT_INFO,
                ("IrTransmit: Device does not support DC mode"));
            WdfRequestComplete(Request, STATUS_INVALID_DEVICE_REQUEST);
            return;

        }

        ASSERT(transmitParams->Flags & TRANSMIT_FLAGS_PULSE_MODE);

        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_TRANSMIT_INFO,
            ("IrTransmit: Pulse mode support not available"));
        WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
        return;

    } else {

        //
        // We've been given the carrier period for the device
        //  in usecs.
        //

        //
        // Calculate the frequency in Hz to keep things integral
        //
        frequencyKHz 
            = SMSCIR_USEC_P_TO_KHZ_F(capturedCarrierPeriod);

        //
        // And turn the value into something for our CFD register (see
        //  section 2.1.1 in the CIRCC2 data book)
        //

        //
        // Beware an obscenely large period from an unsavory user.
        //
        if (frequencyKHz != 0) {

            carrierDivider = SMSCIR_KHZ_TO_CFD(frequencyKHz);

        }
        
        SmscIrTracePrint(
            TRACE_LEVEL_INFORMATION,
            SMSCDBG_IOCTL_INFO,
                ("IrTransmit: Blasting will occur at %dKHz", 
                    frequencyKHz));

        if (carrierDivider == 0 ||
            carrierDivider > UCHAR_MAX) {

            SmscIrTracePrint(
                TRACE_LEVEL_ERROR,
                SMSCDBG_TRANSMIT_INFO,
                    ("Frequency divider result out of range (%d), "\
                     "Defaulting to %d", 
                        carrierDivider, SMSCIR_RC6_CARRIER_DIVIDER));

        }

    }



    //
    // Figure out which emitters this request is going
    //  out on. 
    //
    // Note that we only have 4 emitter jacks, so only
    //  look at the botton four bits 
    //
    capturedTxPorts = (UCHAR)(transmitParams->TransmitPortMask & 0xF);

    //
    // Write out the emitters we're using
    //
    SmscIrTracePrint(
        TRACE_LEVEL_INFORMATION,
        SMSCDBG_IOCTL_INFO,
        ("IrTransmit: Blasting on port mask 0x%x", capturedTxPorts));


    //
    // Need to modify registers, so we need the lock.
    //  The registers on this device use a windowing
    //  scheme, so we always need the lock to avoid
    //  banging into someone else.
    //
    WdfInterruptAcquireLock(DeviceData->Interrupt);

    //
    // Disable interrupts.
    //
    mbc.AsUChar = 0;
    WRITE_TRANSMIT_UCHAR(DeviceData,
                         BIRCC2_MASTER_BLOCK_CONTROL_ADDR,
                         mbc.AsUChar);

    //
    // Reset the fifo
    //
    lineControl.AsUChar   = 0;
    lineControl.FifoReset = 1;
    WRITE_TRANSMIT_UCHAR(DeviceData,
                         BIRCC2_LINE_CONTROL_ADDR,
                         lineControl.AsUChar);

    //
    // Write it out to the blaster mask
    //
    txEnables.AsUChar = capturedTxPorts;
    WRITE_TRANSMIT_UCHAR(DeviceData,
                         BIRCC2_TX_CHANNEL_ENABLES_ADDR,
                         txEnables.AsUChar);

    


    //
    //  Figure out if we need to modify the carrier settings
    //
    if (SMSCIR_RC6_CARRIER_DIVIDER != carrierDivider) {

        //
        // Indeed we do. Update it...
        //
        mbc.AsUChar = 0;
        mbc.RegisterBlockSelect = 1;
        WRITE_TRANSMIT_UCHAR(DeviceData,
                             BIRCC2_MASTER_BLOCK_CONTROL_ADDR,
                             mbc.AsUChar);

        WRITE_TRANSMIT_UCHAR(DeviceData,
                             BIRCC2_CONSUMER_IR_CARRIER,
                             (UCHAR)carrierDivider);

    }

    //
    // Re-enable interrupts on the device (this also puts
    //  us back to register block 0).
    //
    mbc.AsUChar = 0;
    mbc.RegisterBlockSelect = 0;
    mbc.MasterInterruptEnable = TRUE;
    WRITE_TRANSMIT_UCHAR(DeviceData,

⌨️ 快捷键说明

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