📄 ir_control.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 noninfringement, merchantability and/or
* fitness for a particular purpose.
* ---------------------------------------------------------------
*
* Copyright (c) 2008 Conexant Systems, Inc.
* All rights reserved.
*
\******************************************************************* ---*/
#include "Ir_control.h"
#include "PolarisUsbInterface.h"
#include "miscfuncs.h"
/////////////////////////////////////////////////////////////////////////////////////////
IR_Control::IR_Control( CUsbInterface* p_usb, PolarisUsbInterface* p_firmware,
UsbI2cInterface* p_i2c_interface,
PDEVICE_OBJECT pdo,
PcbConfig* p_current_config) :
_p_usb(p_usb),
_p_usb_firmware(p_firmware),
_p_i2c_interface(p_i2c_interface),
_p_thread_object(NULL),
_p_queue_thread(NULL),
_key_queue(16),
_last_command(0xFFFFFFFF),
_was_started(FALSE),
_queue_started(FALSE),
_pdo(pdo),
_buffer_count(0),
_pipe(0),
_interface(1), ///default is index 0
_p_current_config(p_current_config),
_config_index(0)
{
DbgLogInfo(("ir_control::ir_control constructor\n"));
_data_queue.count =0;
_free_queue.count = 0;
KeInitializeEvent(
&_thread_event,
SynchronizationEvent, // single wait satisfied resets it
FALSE); // not signaled
KeInitializeEvent(
&_queue_event,
SynchronizationEvent, // single wait satisfied resets it
FALSE); // not signaled
InitializeListHead (&_data_queue.queue_head);
InitializeListHead (&_free_queue.queue_head);
KeInitializeSpinLock (&_data_queue.spin_lock);
KeInitializeSpinLock (&_free_queue.spin_lock);
_urb_size = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
_p_current_pcb = _p_current_config->getCurrentPcb();
}
/////////////////////////////////////////////////////////////////////////////////////////
IR_Control::~IR_Control()
{
}
/////////////////////////////////////////////////////////////////////////////////////////
NTSTATUS IR_Control::start()
{
NTSTATUS status =STATUS_SUCCESS;
for(int i=0;i<IR_BUFFER_NUM;i++)
{
PBUFFER_ENTRY_MINI p_buffer = allocateBuffer();
if(p_buffer)
{
p_buffer->buffer_id=i;
sendBuffer(p_buffer);
}
else
{
status = STATUS_INSUFFICIENT_RESOURCES;
}
if(!NT_SUCCESS(status))
break;
}
if(_buffer_count)
{
status = startQueueThread();
}
if(status == STATUS_SUCCESS)
{
_queue_started = TRUE;
}
status = startThread();
if(status == STATUS_SUCCESS)
{
_was_started = TRUE;
}
return status;
}
/////////////////////////////////////////////////////////////////////////////////////////
VOID IR_Control::stop()
{
_was_started = FALSE;
_queue_started = FALSE;
stopThread();
}
/////////////////////////////////////////////////////////////////////////////////////////
VOID IR_Control::powerDown()
{
stopThread();
}
/////////////////////////////////////////////////////////////////////////////////////////
VOID IR_Control::powerUp()
{
if(_was_started)
{
startThread();
}
}
/////////////////////////////////////////////////////////////////////////////////////////
NTSTATUS IR_Control::startThread()
{
if (_p_thread_object)
{
return STATUS_UNSUCCESSFUL;
}
KeClearEvent(&_thread_event);
HANDLE thread_handle;
NTSTATUS status = PsCreateSystemThread(
&thread_handle,
THREAD_ALL_ACCESS,
NULL,
NULL,
NULL,
(PKSTART_ROUTINE) IR_Control::static_ThreadFunction, // Thread routine
this); // Context
if(!NT_SUCCESS(status))
return status;
return ObReferenceObjectByHandle(
thread_handle,
THREAD_ALL_ACCESS,
NULL,
KernelMode,
&_p_thread_object,
NULL);
}
/////////////////////////////////////////////////////////////////////////////////////////
NTSTATUS IR_Control::startQueueThread()
{
if (_p_queue_thread)
{
return STATUS_UNSUCCESSFUL;
}
KeClearEvent(&_queue_event);
HANDLE thread_handle;
NTSTATUS status = PsCreateSystemThread(
&thread_handle,
THREAD_ALL_ACCESS,
NULL,
NULL,
NULL,
(PKSTART_ROUTINE) IR_Control::static_ThreadQueue, // Thread routine
this); // Context
if(!NT_SUCCESS(status))
return status;
return ObReferenceObjectByHandle(
thread_handle,
THREAD_ALL_ACCESS,
NULL,
KernelMode,
&_p_queue_thread,
NULL);
}
/////////////////////////////////////////////////////////////////////////////////////////
VOID IR_Control::stopThread()
{
PBUFFER_ENTRY_MINI p_buffer;
if(_p_thread_object)
{
KeSetEvent(&_thread_event, IO_NO_INCREMENT, TRUE);
//Wait for the buffer complete thread to exit
KeWaitForSingleObject(
_p_thread_object,
Executive,
KernelMode,
TRUE,
NULL);
_p_thread_object = NULL;
}
while(_data_queue.count)
{
p_buffer = getBuffer(&_data_queue);
while(p_buffer)
{
freeBuffer(p_buffer);
p_buffer = getBuffer(&_data_queue);
}
if(_data_queue.count && !p_buffer)
{
waitForTimes(500);
p_buffer = getBuffer(&_data_queue);
}
}
if(_p_queue_thread)
{
KeSetEvent(&_queue_event, IO_NO_INCREMENT, TRUE);
//Wait for the buffer complete thread to exit
KeWaitForSingleObject(
_p_queue_thread,
Executive,
KernelMode,
TRUE,
NULL);
_p_queue_thread = NULL;
}
while(_free_queue.count)
{
p_buffer = getBuffer(&_free_queue);
while(p_buffer)
{
freeBuffer(p_buffer);
p_buffer = getBuffer(&_data_queue);
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////
VOID IR_Control::static_ThreadFunction(IR_Control* p_this)
{
p_this->threadFunction();
}
/////////////////////////////////////////////////////////////////////////////////////////
VOID IR_Control::static_ThreadQueue(IR_Control* p_this)
{
p_this->threadQueue();
}
/////////////////////////////////////////////////////////////////////////////////////////
VOID IR_Control::threadQueue()
{
PBUFFER_ENTRY_MINI p_buffer = NULL;
while(_queue_started)
{
p_buffer = getBuffer(&_free_queue);
if(p_buffer)
{
sendBuffer(p_buffer);
}
}
PsTerminateSystemThread(STATUS_SUCCESS);
}
/////////////////////////////////////////////////////////////////////////////////////////
///jerry_xu 2007-03-20, modify to delete IR control
VOID IR_Control::threadFunction()
{
PBUFFER_ENTRY_MINI p_buffer = NULL;
PBYTE p_ir = new BYTE[IR_LENGTH*DATA_BLOCK_NUM];
PBYTE p_event = new BYTE[EVENT_LENGTH*DATA_BLOCK_NUM];
PBYTE p_pre_event = new BYTE[EVENT_LENGTH]; //TO store pre-event
RtlZeroMemory(p_pre_event,EVENT_LENGTH);
while(_was_started)
{
RtlZeroMemory(p_ir,IR_LENGTH*DATA_BLOCK_NUM);
RtlZeroMemory(p_event,EVENT_LENGTH*DATA_BLOCK_NUM);
p_buffer = getBuffer(&_data_queue);
if(p_buffer)
{
sliced_data(p_buffer->p_buffer, p_ir,p_event);
ProcessEvent(p_event,p_pre_event);
sendFreeBuffer(p_buffer);
}
}
delete [] p_ir;
delete [] p_event;
delete [] p_pre_event;
p_ir = NULL;
p_event = NULL;
p_pre_event = NULL;
PsTerminateSystemThread(STATUS_SUCCESS);
}
/////////////////////////////////////////////////////////////////////////////////////////
VOID IR_Control::flushQueue()
{
_key_queue.Flush();
//TODO: Flush the firmware's queue
}
/////////////////////////////////////////////////////////////////////////////////////////
VOID IR_Control::getKeystroke(DWORD* p_command, DWORD* p_address)
{
if(!_key_queue.IsEmpty())
{
KEYSTROKE keystroke = _key_queue.Remove();
*p_command = keystroke.dwCommand;
*p_address = keystroke.dwAddress;
}
else
{
*p_command = 0;
*p_address = 0;
}
}
/////////////////////////////////////////////////////////////////////////////////////////
PBUFFER_ENTRY_MINI IR_Control::allocateBuffer()
{
PBUFFER_ENTRY_MINI p_buffer = new BUFFER_ENTRY_MINI;
if(!p_buffer)
{
return NULL;
}
p_buffer->p_buffer = new BYTE[IR_BUFFER_SIZE];
p_buffer->p_irp = IoAllocateIrp(_pdo->StackSize, FALSE);
p_buffer->p_urb = (PURB) new BYTE[_urb_size];
if(!p_buffer->p_buffer ||
!p_buffer->p_irp ||
!p_buffer->p_urb)
{
if(p_buffer->p_irp) IoFreeIrp(p_buffer->p_irp);
delete [] p_buffer->p_buffer;
delete [] p_buffer->p_urb;
delete p_buffer;
return NULL;
}
RtlZeroMemory(p_buffer->p_urb, _urb_size);
p_buffer->buffer_in_list = FALSE;
p_buffer->buffer_dirty = FALSE;
InterlockedIncrement(&_buffer_count);
return p_buffer;
}
/////////////////////////////////////////////////////////////////////////////////////////
VOID IR_Control::sendBuffer(PBUFFER_ENTRY_MINI p_buffer)
{
//Initialize our completion context
p_buffer->p_data_transfer = (DWORD*)this;
p_buffer->read_context.pIrp = p_buffer->p_irp;
p_buffer->read_context.pUrb = p_buffer->p_urb;
p_buffer->read_context.pCompletion = (USBCOMPLETION)static_BufferComplete;
p_buffer->read_context.UserContext = p_buffer;
p_buffer->bytes_completed = 0;
//Start a data transfer
NTSTATUS status = _p_usb->UsbAsyncIo(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -