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

📄 io.c

📁 ir 驱动程序源代码,make成功了,有兴趣的朋友可以看看
💻 C
📖 第 1 页 / 共 5 页
字号:
                //
                // Remember our position in the byte so we 
                //  can properly process the next sample
                //
                bitPos += numSamplesThisPacket;
                break;
                
            } else {
                
                //
                // We're finishing off a byte. May be leftover
                //  bits from a previous pass, so subtract our
                //  position from the total number of possible
                //  bits.
                //
                numSamplesThisPacket -= (8-bitPos);

                //
                // Put this byte in the FIFO.
                //
                txFifoData->FifoBuffer[bytesInFifo++] = fifoByte;
                
                //
                // Used all bits. Restart the position,
                //
                bitPos = 0;

                if (bytesInFifo > fifoBufferSize) {

                    //
                    // This shouldn't happen: we've exhausted our 
                    //  previous overallocation of the user buffer.
                    //
                    //  The only reason for this would be the user 
                    //  data buffer changing out from underneath us,
                    //  so this is a user mode app problem.
                    //
                    ExFreePool(txFifoData);
                    SmscIrTracePrint(
                        TRACE_LEVEL_ERROR,
                        SMSCDBG_TRANSMIT_INFO,
                        ("IrTransmitBuildFifoData: User data changed while "
                         "processing. Aborting TX"));
                    return STATUS_DATA_NOT_ACCEPTED;

                }

            }

        }

    }


    if (bitPos) {

        //
        // If bit position isn't zero, then the last packet
        //  was short on filling up the byte. imagine ON for 8,
        //  OFF for 2 being the last two samples...We now have
        //  a partially empty packet that needs to have the upper
        //  bits stuffed.
        //
        // We'll deal with that here by padding the last byte with 
        //  silence
        //
        fifoByte |= (0xFF << bitPos);
        txFifoData->FifoBuffer[bytesInFifo++] = fifoByte;
    }

    //
    // Add whatever silence we need at the end to make
    //  this SMSCIR_FIFO_SIZE aligned
    //
    paddingRequired 
            = (SMSCIR_FIFO_SIZE - (bytesInFifo & (SMSCIR_FIFO_SIZE-1)));

    for (i = 0; i < paddingRequired; i++) {

        txFifoData->FifoBuffer[bytesInFifo++] = 0xFF;

    }

    ASSERT((bytesInFifo % SMSCIR_FIFO_SIZE) == 0);

    txFifoData->FifoBufferLength = bytesInFifo;

    //
    // Done building the buffer.
    //
    *TxFifoData = txFifoData;
    return STATUS_SUCCESS;

}



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

    Returns device capabilities.  

Arguments:

    DeviceData - Our device extension

    Request    - An IOCTL_IR_GET_DEV_CAPS request

    OutputBufferLength - sizeof(IR_DEV_CAPS)

--*/
    PIR_DEV_CAPS devCaps;
    NTSTATUS status;

    UNREFERENCED_PARAMETER(DeviceData);

    if (OutputBufferLength < sizeof(IR_DEV_CAPS)) {
        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_IOCTL_INFO,
                ("IrGetDevCaps: Buffer size must be at least 0x%x",
                sizeof(IR_DEV_CAPS)));
        WdfRequestWdmGetIrp(Request)->IoStatus.Status 
                                        = STATUS_BUFFER_TOO_SMALL;
        WdfRequestCompleteWithInformation(Request, STATUS_BUFFER_TOO_SMALL, 
                                          sizeof(IR_DEV_CAPS));
        return;
    }

    status = WdfRequestRetrieveOutputBuffer(Request,
                                            sizeof(IR_DEV_CAPS),
                                            &devCaps,
                                            NULL);

    if (!NT_SUCCESS(status)) {

        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_IOCTL_INFO,
            ("WdfRequestRetrieveOutputBuffer failed with Status code 0x%x", 
                status));
        WdfRequestComplete(Request, status);
        return;

    }

    //
    // Fill in the capabilities based on what we just happen to  "know" 
    //  about out device
    //
    devCaps->ProtocolVersion      = DEV_CAPS_PROTOCOL_VERSION;
    devCaps->DevCapsFlags         = 0;
    devCaps->NumReceivePorts      = DEVCAPS_NUM_RECEIVE_PORTS;
    devCaps->LearningReceiverMask = DEVCAPS_LEARNING_MASK;
    devCaps->NumTransmitPorts     = DEVCAPS_TRANSMIT_PORTS;

    SmscIrTracePrint(
        TRACE_LEVEL_INFORMATION,
        SMSCDBG_IOCTL_INFO,
        ("IrGetDevCaps: Returning capabilities:"));
    SmscIrTracePrint(
        TRACE_LEVEL_INFORMATION,
        SMSCDBG_IOCTL_INFO,
        ("\tProtocolVersion = %Id", devCaps->ProtocolVersion));
    SmscIrTracePrint(
        TRACE_LEVEL_INFORMATION,
        SMSCDBG_IOCTL_INFO,
        ("\tDevCapsFlags = 0x%Ix", devCaps->DevCapsFlags));
    SmscIrTracePrint(
        TRACE_LEVEL_INFORMATION,
        SMSCDBG_IOCTL_INFO,
        ("\tNumReceivePorts = %Id", devCaps->NumReceivePorts));
    SmscIrTracePrint(
        TRACE_LEVEL_INFORMATION,
        SMSCDBG_IOCTL_INFO,
        ("\tLearningReceiverMask = 0x%Ix", devCaps->LearningReceiverMask));
    SmscIrTracePrint(
        TRACE_LEVEL_INFORMATION,
        SMSCDBG_IOCTL_INFO,
        ("\tNumTransmitPorts = %Id", devCaps->NumTransmitPorts));

    
    WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS,
                                      sizeof(IR_DEV_CAPS));

}


VOID
IrUserOpen(
    PSMSCIR_DATA DeviceData,
    WDFREQUEST Request
    ) {
/*++
Routine Description.

    Called here by IRCLASS when our port FDO is indirectly
    opened by a user opening the IRCLASS FDO. 

    This IOCTL is simply informational, IRCLASS will not
    reject the open if this is failed.

Arguments:

    DeviceData - Our device extension

    Request    - An IOCTL_IR_USER_OPEN request

--*/

    UNREFERENCED_PARAMETER(DeviceData);

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

    //
    // Just complete the request.
    //
    WdfRequestComplete(Request, STATUS_SUCCESS);

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

    return;

}

VOID
IrUserClose(
    PSMSCIR_DATA DeviceData,
    WDFREQUEST Request
    ) {
/*++
Routine Description.

    Called here by IRCLASS when our port FDO is indirectly
    closed by a user closing its handle to the IRCLASS FDO. 

Arguments:

    DeviceData - Our device extension

    Request    - An IOCTL_IR_USER_CLOSE request


--*/

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

    //
    // For closes, make sure that the user did us
    //  right and exited priority mode if he entered it.
    //  If he didn't, fix it for him...
    //
    if (DeviceData->InPriorityMode) {

        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_IOCTL_INFO,
            ("IrUserClose: The application exited without exiting priority "\
             "mode! Cleaning up"));
        IrExitPriorityMode(DeviceData,
                      Request);
        return;

    }

    //
    // Otherwise just complete it...
    //
    WdfRequestComplete(Request, STATUS_SUCCESS);

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

    return;

}


VOID
IrEnterPriorityMode(
    PSMSCIR_DATA DeviceData,
    WDFREQUEST Request, 
    SIZE_T InputBufferLength
    ) {

/*++
Routine Description.

    This request is sent from a user mode application to prepare the port to 
    return priority IR data. While the device is in priority mode, all 
    IOCTL_IR_RECEIVE requests should be starved and IOCTL_IR_PRIORITY_RECEIVE 
    requests should be completed with RLC IR data.

Arguments:

    DeviceData - Our device extension

    Request    - An IOCTL_IR_ENTER_PRIORITY_RECEIVE request

    InputBufferLength  - sizeof(IOCTL_IR_ENTER_PRIORITY_RECEIVE_PARAMS)

--*/
    NTSTATUS                status = STATUS_SUCCESS;
    PIOCTL_IR_ENTER_PRIORITY_RECEIVE_PARAMS priorityModeParams = NULL;
    ULONG                   numFFs;
    ULONG                   localTimeoutInUSec;
    MASTER_BLOCK_CONTROL    mbc;
    SCE_CONFIG_B            configB;
    LINE_CONTROL_B          lcb;
    LINE_CONTROL_A          lca;
    CONSUMER_IR_CTRL        irCtrl;
    KIRQL                   oldIrql;
    WDFREQUEST              successfulRequest = NULL;
    WDFREQUEST              failedRequest = NULL;
    NTSTATUS                failureStatus;
    ULONG                   minusOne;
    CARRIER_CAPTURE_CONTROL captureControl;
    ULONG                   receiver;


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

    //
    // Sorry buddy, can't help you if we're already in priority mode...
    //
    if (DeviceData->InPriorityMode) {
        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_IOCTL_INFO,
                ("IrEnterPriorityMode: Device is already in priority mode. "\
                 "Failing ENTER_PRIORITY_RECEIVE"));
        WdfRequestComplete(Request, STATUS_INVALID_DEVICE_STATE);
        return;

    }

    if (InputBufferLength < sizeof(IOCTL_IR_ENTER_PRIORITY_RECEIVE_PARAMS)) {
        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_IOCTL_INFO,
                ("IrEnterPriorityMode: Buffer size must be at least 0x%x",
                sizeof(IOCTL_IR_ENTER_PRIORITY_RECEIVE_PARAMS)));
        WdfRequestWdmGetIrp(Request)->IoStatus.Status 
                                        = STATUS_BUFFER_TOO_SMALL;
        WdfRequestCompleteWithInformation(
                               Request, 
                               STATUS_BUFFER_TOO_SMALL, 
                               sizeof(IOCTL_IR_ENTER_PRIORITY_RECEIVE_PARAMS));
        return;
    }


    status = WdfRequestRetrieveInputBuffer(Request, 
                                           InputBufferLength,
                                           &priorityModeParams,
                                           NULL);

    if (!NT_SUCCESS(status)) {
        
        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_IOCTL_INFO,
            ("IrEnterPriorityMode: WdfRequestRetrieveInputBuffer failed "\
             "with Status code 0x%x",
                status));
        WdfRequestComplete(Request, status);
        return;
        
    }

    ASSERT(priorityModeParams);

    //
    // Get the receiver the caller wants to use
    //
    receiver = (ULONG)priorityModeParams->Receiver;

    if (receiver > DEVCAPS_NUM_RECEIVE_PORTS) {

        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_IOCTL_INFO,
            ("IrEnterPriorityMode: Receiver #%d invalid. Device only has %d "\
             "receivers ", receiver, DEVCAPS_NUM_RECEIVE_PORTS));
        WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
        return;

    }


    //
    // Figure out the number of FFs we need to see for a timeout.
    //  Any timeout less than 8 * 50usecs will be rounded up, but it
    //  prevents us from having to calculate RLC from within the ISR
    //  (which isn't an option anyway)
    //
    //
    // Timeout is given in milliseconds....
    //
    localTimeoutInUSec = (ULONG)priorityModeParams->TimeOut * 1000;


    if (!localTimeoutInUSec) {

        //
        // Invalid to not give some sort of timeout
        //
        SmscIrTracePrint(
            TRACE_LEVEL_ERROR,
            SMSCDBG_IOCTL_INFO,
            ("IrEnterPriorityMode: Zero timeout supplied. Invalid."));
        WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
        return;
    }
    //
    // Round it up to the next 50usec unit...
    //
    numFFs = (localTimeoutInUSec + (IR_SAMPLE_PERIOD-1)) & ~(IR_SAMPLE_PERIOD-1);
    //
    // And divide by 50usec...
    //
    numFFs = numFFs / IR_SAMPLE_PERIOD;

    //
    // Divide into number of FF bytes required for a data end...
    //
    numFFs = (numFFs/8);

    if (numFFs != DeviceData->NumFFsForDataEnd) {

        SmscIrTracePrint(
            TRACE_LEVEL_INFORMATION,
            SMSCDBG_IOCTL_INFO,
                

⌨️ 快捷键说明

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