📄 ircontrol.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 + -