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

📄 ircontrol.cpp

📁 pci 底层驱动
💻 CPP
字号:
/*+++ *******************************************************************\
*
*   Copyright and Disclaimer:
*
*       ---------------------------------------------------------------
*       This software is provided "as is" without warranty of any kind,
*       either expressed or implied, including but not limited to the
*       implied warranties of merchantability and/or fitness for a
*       particular purpose.
*
*       Copyright (c) 1999-2000 Conexant Systems, Inc.
*       All Rights Reserved.
*       ---------------------------------------------------------------
*
*   Module Revision Id:
*
*
*   Abstract:
*
*       This file contains the I2C object access methods.
*
*   Routines:
*
*   Revision History:
*
*
\******************************************************************* ---*/

#include "common.h"
#include "ircontrol.h"
#include "ircommand.h"
#include "hid.h"

/////////////////////////////////////////////////////////////////////////////////////////
//IR_Control::static_dpcRoutine
//
// This is the DDK entry point for our DPC for ISR.  It just calls the non-static 
//  dpcRoutine()
//
VOID IR_Control::static_dpcRoutine(
                                   PKDPC        dpc,
                                   IR_Control*  p_this,     
                                   ULONG        sample,     //IR sample
                                   PVOID        p_context2) 
{
	p_this->dpcRoutine(sample);
}


/////////////////////////////////////////////////////////////////////////////////////////
//IR_Control::dpcRoutine
//
// This is the DPC for ISR routine.  It looks at the sample taken in the ISR, and passes
// it to RC5Decode to be decoded into a command.  It then uses RC5Command to convert the
// command into an HID report.  It then sends the HID report to the HID class to report
// it to the system.
//
// There are two other considerations: 
// 1) non auto-repeat commands should only be sent once.  So we store the last command
//   and do a comparison.  Note that the last command will be different even if the 
//   same key was pressed twice since the toggle bit changes with every keystroke.
// 2) keyboard keypresses require a key-up message.  We send these messages the next time
//   through the DPC to give the system some time to process the key-down message, but
//   before processing the next command
//
VOID IR_Control::dpcRoutine(ULONG sample)
{
    if(!_p_decoder)
    {
        return;
    }


    ULONG command = _p_decoder->submitSample(sample);

    //First send a key-up if we sent a key-down last time.
    //Note that the keystroke repeats until the key-up is sent.
    //A key-up consists of a keyboard report where all keystroke values
    // are zero.
    if(_send_key_up)
    {
        KEYBOARD_USAGE_PAGE_REPORT report;
        
        RtlZeroMemory(&report, sizeof(report));
        report.report_id = REPORT_ID_KEYBOARD;
        
        _p_hid->submitReport(&report, sizeof(report));
        _send_key_up = FALSE;
    }
    else if (_send_consumer_key_up)
    {
        CONSUMER_USAGE_PAGE_REPORT report;
        
        RtlZeroMemory(&report, sizeof(report));
        report.report_id = REPORT_ID_CONSUMER;
        
        _p_hid->submitReport(&report, sizeof(report));
       
        _send_consumer_key_up = FALSE;
    }


    if(command != 0xFFFFFFFF)
    {
        BOOLEAN is_repeat_command = (command == DECODE_REPEAT_COMMAND);

        IR_Command* p_command = _p_decoder->getIrCommand();

        //Auto-repeat processing.  If this is an auto repeat key,
        // we want to send it the first time, then skip the next 
        // few messages.  
        BOOLEAN is_auto_repeat = p_command->isAutoRepeatKey();
        if(is_auto_repeat && is_repeat_command)  
        {
            if(++_auto_repeat_count <= AUTO_REPEAT_COUNT)
            {
                enableInterrupt();
                return;
            }
            
        }
        else
        {
            _auto_repeat_count = 0;
        }
        
        //Only send the command if it is not a repeat of the 
        // last command, or if auto repeat is on for this key.
        if(is_auto_repeat || !is_repeat_command)
        {
            //Need to send a key-up message next time for keyboard keys
            if(p_command->isKeyboardKey())
            {
                _send_key_up = TRUE;
            }
            else
            {
                _send_consumer_key_up = TRUE;
            }
            
            //send the report
            _p_hid->submitReport(
                p_command->getReport(),
                p_command->getReportSize());
        }

    }

    enableInterrupt();
}

/////////////////////////////////////////////////////////////////////////////
// Constructor
/////////////////////////////////////////////////////////////////////////////
IR_Control::IR_Control(RegisterIo* p_registers,
                       HidProcessing* p_hid,
                       IR_STANDARD    ir_standard,
                       DWORD ir_command_table) :
_p_registers(p_registers),
_send_key_up(FALSE),
_send_consumer_key_up(FALSE),
_p_hid(p_hid),
_auto_repeat_count(0)
{
	//Set up the DPC 
    KeInitializeDpc(&_dpc, (PKDEFERRED_ROUTINE)IR_Control::static_dpcRoutine, this);

    if(ir_standard == IR_STANDARD_RC5)
    {
        _p_decoder = new RC5Decode(ir_command_table);
    }
    else //IR_STANDARD_NEC
    {
        _p_decoder = new NEC_Decode(ir_command_table);
    }
}


/////////////////////////////////////////////////////////////////////////////
// Destructor
/////////////////////////////////////////////////////////////////////////////
IR_Control::~IR_Control()
{
    disableInterrupt();
    clearInterrupt();

    //Make sure the DPC isn't queued
    KeRemoveQueueDpc(&_dpc);

	//Disable DDS
    _p_registers->writeDword(DDSCFG_IO, 0);

    delete _p_decoder;
    _p_decoder = NULL;
}

/////////////////////////////////////////////////////////////////////////////
// Handle GP shift register interrupt
/////////////////////////////////////////////////////////////////////////////
BOOLEAN IR_Control::interruptHandler()
{
    //Return immediately if this is not our interrupt
    if(!isIrInterrupt())
        return FALSE;
    
    //Get the current sample
    DWORD sample = _p_registers->readDword(SAMPLE_IO);

    //Stop interrupting, and disable further interrupts until after the DPC
    clearInterrupt();
    disableInterrupt();

	//Schedule the DPC
	KeInsertQueueDpc(&_dpc, (PVOID)sample, NULL);

    return TRUE;
}

⌨️ 快捷键说明

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